I’m trying to get conversations with NPCs working, and am hitting a small glitch. (Maybe a simpler approach will work better?)
What should happen:
When the player initiates a conversation, a text window appears, and closes when the player hits a key/clicks a button. If the conversation takes more than one window, move on to the next dialogue window until the conversation is done.
So, the functions that run the conversation look something like this: (Edited a bit in an attempt for brevity/clarity…)
bool messageOn = false;
... ...
public void Convo01(){
MessageWindow("I am a knight who says 'Ni!'", MessageType.Friendly);
MessageWindow("Do you suspect the Spanish Inquisition?", MessageType.Friendly);
MessageWindow("Always look on the bright side of life.", MessageType.Friendly);
MessageWindow("Goodbye", MessageType.Hostile);
}
public void MessageWindow(string message, MessageType type){
//Set variables to control how/where window will appear and display, etc.
... ...
messageOn = true;
}
void OnGUI(){
if (messageOn){
GUI.Label(new Rect(x,y,width,height), messageStr, styleSettings);
if (Input.anyKey){
messageOn = false;
}
}
}
Of course, running this will blaze through and only show the last message since there’s nothing to make the code pause between MessageWindow calls. I’ve tried setting up MessageWindow as a coroutine, but can’t figure out how to make it wait until the message window is closed before telling the original funciton to continue… I’ve gone through the scripting manual and haven’t found much help, either…
Any thoughts? (Am I going about this completely back asswards?)
you can’t make it wait.
OnGUI is called on each frame and only the gui code thats executed at the time will be shown. so code thats locked / can’t be reached will result in the corresponding gui not beeing available.
what you would do is having states that tell you where you were before to show that again.
dreamora is right, having an Event Driven FSM will be the best way to handle this. The best way to approach this is to have a “MessageWindow” class, and have each message window of the conversation built from it. Then you make a state controller class, and call those from there according to what part of the conversation you’re in.
eg
public class MessageWindowClass
{
string message;
Rect guiSpace;
public void Initialize(string _message, Rect _guiRect)
{
// Setup the message variables here
}
public void MessageWindow()
{
// Draw the message in the window
}
}
Then you have the state controller make these
public class MessageStateController
{
// you can store more of the as required
MessageWindowClass currentMessage;
MessageWindowClass previousMessage;
public voidSetNewMessage(string newMessage)
{
Destory(previousMessage);
previousMessage = currentMessage;
currentMessage = gameObject.AddComponent(typeof(MessageWindowClass)) as MessageWindowClass;
currentMessage.Initialize(newMessage, defaultGUIRect);
}
public void OnGUI()
{
if(currentMessage != null)
currentMessage.MessageWindow();
}
}
It obviously needs to be a bit deeper than this, but it should give you a basic idea of whats needed. If you get that setup properly, you just need to write scripts to define the conversations, and what order they get called in. Some of that functionality could go into the state machine, but it’s probably best to seperate it so the state machine is re-usable for lots of different conversations.
Hmm - yeah, that makes sense. And with a little thought into the library building, this could be quite robust. Time to play with this - I think I’ve got the system worked out now!