In my game I’m making dialogues, and I originally made a first script managing all the dialogue actions:
public class Dialogues : MonoBehaviour
{
public TextMeshProUGUI dialogueText;
public string[] lines;
public float textSpeed = 0.1f;
public int index;
void Start()
{
dialogueText.text = string.Empty;
gameObject.SetActive(false);
}
void Update()
{
if (Input.GetMouseButton(0))
{
NextLine();
}
}
public void StartDialogue()
{
index = 0;
gameObject.SetActive(true);
StartCoroutine(WriteLine());
}
IEnumerator WriteLine()
{
foreach (char letter in lines[index].ToCharArray())
{
dialogueText.text += letter;
yield return new WaitForSeconds(textSpeed);
}
}
public void NextLine()
{
if (index < lines.Length - 1)
{
index++;
dialogueText.text = string.Empty;
StartCoroutine(WriteLine());
}
else
{
gameObject.SetActive(false);
}
}
}
Where lines are each piece of dialogue shown on screen before having to write the next one, and for various NPCs talking I made this global script:
public class Talk : MonoBehaviour
{
public string[] dialogue1;
public Dialogues dialogues;
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.name == "Player")
{
dialogues.lines[dialogues.index] = dialogue1[dialogues.index];
if (Input.GetKey(KeyCode.E))
{
dialogues.StartDialogue();
}
}
}
}
Where dialogue1 is the dialogue pieces I put for a first dialogue.
In overall what should happen is that when you approach an NPC and press E it should show the dialogue box with the dialogue, but once I approach it and press E nothing happens, could someone help me out?
Don’t use Trigger stay. it is bad practice for your case.
Store the dialoge in a variable on trigger enter. then in update check if dialoge not null and key press, play the dialoge.
Something like having a function to play the current dialogue, and on trigger enter you assign current dialogue.
On trigger exit, set current dialogue to null.
If you decide to use OnTriggerStay, then replace Input.GetKey with Input.GetKey__Down__ to trigger the dialogue only once. It’s also preferable to move line 10 into a block that will execute after the E key is pressed.
Even better (in my opinion) is to create a bool and change its value in TriggerEnter/Exit. In the Update function, you can then check this bool along with the pressed keys.
OnTiggerStay is to check overlaps. not the scenario proposed. that will kill performance.
As i mentioned, store currentdialoge on a variable on trigger enter and check if you have a current dialogue when press key. just make sure you clear current dialogue on trigger exit. So you don’t pop up the dialogue a mile away.
If you just need a dialog system, you may wish to consider Fungus or Inkle.
Otherwise…
Whenever you need more information about what your program is doing as well as how and where it is deviating from your expectations, that means it is…
Time to start debugging!
By debugging you can find out exactly what your program is doing so you can fix it.
Here is how you can begin your exciting new debugging adventures:
You must find a way to get the information you need in order to reason about what the problem is.
Once you understand what the problem is, you may begin to reason about a solution to the problem.
What is often happening in these cases is one of the following:
the code you think is executing is not actually executing at all
the code is executing far EARLIER or LATER than you think
the code is executing far LESS OFTEN than you think
the code is executing far MORE OFTEN than you think
the code is executing on another GameObject than you think it is
you’re getting an error or warning and you haven’t noticed it in the console window
To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.
Doing this should help you answer these types of questions:
is this code even running? which parts are running? how often does it run? what order does it run in?
what are the names of the GameObjects or Components involved?
what are the values of the variables involved? Are they initialized? Are the values reasonable?
are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)
Knowing this information will help you reason about the behavior you are seeing.
You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as Debug.Log("Problem!",this);
If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.
You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.
You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.
You could also just display various important quantities in UI Text elements to watch them change as you play the game.
Visit Google for how to see console output from builds. If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer for iOS: How To - Capturing Device Logs on iOS or this answer for Android: How To - Capturing Device Logs on Android
If you are working in VR, it might be useful to make your on onscreen log output, or integrate one from the asset store, so you can see what is happening as you operate your software.
Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.
If your problem is with OnCollision-type functions, print the name of what is passed in!
Here’s an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:
This is the bare minimum of information to report:
what you want
what you tried
what you expected to happen
what actually happened, log output, variable values, and especially any errors you see
links to actual Unity3D documentation you used to cross-check your work (CRITICAL!!!)
The purpose of YOU providing links is to make our job easier, while simultaneously showing us that you actually put effort into the process. If you haven’t put effort into finding the documentation, why should we bother putting effort into replying?
Probably because you don’t prevent it from executing again if the dialogue is already open. You only want the dialogue to run if there isn’t already dialogue happening.
It’s really difficult to figure out other people’s projects and identify where bugs are originating. My advice is to break it down into basic steps and build your own dialogue manager.
Start by deciding how to detect the distance between a player and an NPC (consider transform distance vs. collision detection). Then, write a simple debugging system (for example, on collider enter, display ‘Hi’; on collider exit, display ‘Bye’). Once this works, add detection for a key press. Following that, make the key press activate or deactivate an object. Then, switch the object to a UI element, and finally, integrate a script to monitor the text inside the UI.
This approach might seem too basic for some, but it could be quite helpful for newcomers who might read this in the future. Remember, don’t trust your code blindly. Sometimes, we are so biased that we miss basic mistakes. Good luck!
P.S. On a lighter note, if it’s about using overly complicated third-party editor tools, I personally opted for creating my own tools that simply read… a plain text file. Believe it or not, sometimes writing things in a linear way and feeding it into a script capable of interpreting it is the easiest solution. It also offers the most flexibility for modifications. Lately, I’ve been considering making it fancier by enabling it to read simple JSON files…