First Person Narrative Coding

Hey everyone I’m brand new to 3d development and am dipping my toe by trying to construct a few small, simple first person narrative experiences.

My question is a simple one but something I’ve not been able to find scouring the internet for a few days… What coding magic do I need for the player to click on an object in the world and have an associated text prompt come up on the GUI (think reading a note in any modern narrative game). I’ve done my homework on raycasting and currently have a ray that projects from my player and can log the console when the the ray is touching something and the player presses mouse down, but nothing else.

I know it’s a simple request but any help would be gladly appreciated!

I’m brand new to 3d development and am dipping my toe

Ok, I’ll tune the answer for simplicity. There are many ways to solve problems but I think making simple steps to achieve behaviour is a good way forward. Then the solution can be improved further at a later point, should the need arise.

What coding magic do I need for the player to click on an object in the world and have an associated text prompt come up on the GUI

The object should have a mechanism to support clicking on them, and handling the click event to generate a response. The absolutely simplest way to achieve this is probably using OnMouseDown, but since you have a Raycast going on, let’s move on from there.

A simple way onward after determining you’ve hit an object is to tell the object it was clicked through SendMessage.

I present three scripts that hopefully is simple to understand:

Interact.cs

The idea is that you’ll call Interact.With(hit.collider.gameObject) from your code that already logs the ray is touching someting.

using UnityEngine;

public static class Interact
{
    public static void With(GameObject go)
    {
        // Call the function "Interact" on all scripts that have it on the game object
        go.SendMessage("Interact", SendMessageOptions.DontRequireReceiver);
    }
}

Note.cs

Note implements Interact and decides what to do when it has been interacted with. For this simple example, we just want to tell the note reader to read the message of the note but it could do more things like playing audio as well as tell the reader to read the message.

using UnityEngine;

public class Note : MonoBehaviour
{
    public string message = "The note is empty";
    public NoteReader reader;

    public void Interact()
    {
        reader.ReadNote(message);
    }
}

**NoteReader **

The NoteReader accepts a message and outputs the message somewhere to the user. In this example, I decided it could just set the text of a Text component but it could have more complicated behaviour like making typewriter-like sounds and revealing the text one character at a time for instance.

using UnityEngine;
using UnityEngine.UI;

public class NoteReader : MonoBehaviour
{
    public Text messageText;

    public void ReadNote(string message)
    {
        messageText.text = message;
    }
}

To put it all together, you’d first create a UI Text object in the scene where the message will appear. Next, you’d probably want to add the NoteReader component to the same Text object, although it is not necessary. The NoteReader must know of the Text component, so drag it into place using the inspector.

Next, go to your note game object and add the Note component to it. Edit the message if you wish. The note must know of a NoteReader so it can tell the reader to present the message of the note when it has been interacted with, so make sure you drag the NoteReader you created earlier to the reader field on the Note component.

Repeating what has been said

It may look like a lot of hoops, but in essence the solution would do something like this:

When user click the mouse, a raycast test says it hit something. User want to interact with that object. In this case it happened to be a Note. Interacting with a note causes a reader to read the note message to the user. Reading a message is just setting the text contents of a Text UI component, which renders it to the user.

I find it that reading through the same information twice but at a different level of speech, it’s easier to grok the solution.

@Statement I don’t know if you’ll see this, but after a few days these scripts stopped working and I’m not sure what I did. From what I can tell the two things not working as intended are:

I can no longer drag NoteReader onto the Reader component of Note

I was never able to drag NoteReader onto my ui text object either

The interact script doesn’t seem to do… Anything. My ray now only casts when the mouse button is clicked down, so that might have something to do with it?