Creating a four-state toggle?

Hi, I’m trying to create a four-state toggle for the purpose of determining whether or not an NPC has a quest for the player, and whether or not the player has completed the quest. I’ve managed to accomplish this using two separate toggles, but I’d like to be able to do it with just one for the sake of efficiency.

The four states I need are as follows:

Right now the method I’m using has two separate booleans:

The problem with my current method, however, is that having to deal with two separate variables to control the script creates excessive complication in the code, which makes errors more likely and makes it more difficult to write the code efficiently. Unfortunately, since I’m still a beginner when it comes to writing code, I don’t know how to create a four-state toggle like I want.

If anyone could help out or give some pointers, that would be great.

Check out the finite state machine script on the Unify Community.

If you’re new to C# it might be a little overwhelming but it’s well commented and should give you a good starting point.

a simple solution would be to just an int and then put it into a switch/case statement.

Wow, yeah, um, thanks for the help, but I’m afraid that script is way beyond my current ability, and trying to use it at my current skill level would only create more headaches than its worth. The reason I want to change the method of my code is to make the script simpler and easier to deal with. Using that script would only make things more complicated and confusing, and I just know I’d have to spend an inordinate amount of time debugging it if I even tried.

See, my current code looks like this:

var hasQuest : boolean ; // Determines whether or not the NPC currently has a quest
var QuestCompleted : boolean;	// Determines whether or not the quest is completed

It’s very simple and easy, and I can just toggle those two variables by using hasQuest = true; and QuestCompleted = false; to indicate all the necessary states. But it requires more thinking than if I just had a single variable with four states.

I appreciate your help, but do you think perhaps there’s another, simply method?

How would I do that?

Represent the quest status with an Int.
0 for no quest, 1 for has a quest, 2 for currently doing quest, 3 for completed.

int npcQuest = 0;

if(npcQuest == 0)
{
  // doesn't have a quest
}

if(npcQuest == 2)
{
  // has a quest
}
etc

using switch would be -

switch(npcQuest)
{
  case 0:
    // doesn't have a quest
    break;

  case 1:
    // has a quest
    break;

  etc..

  default:
    break;
}

enumerators make it easier to read.

enum Quest
{
  None,
  Available,
  Current,
  Complete
}

Quest npcQuest = Quest.None;

switch(npcQuest)
{
  case Quest.None:
    break;

  case Quest.Available:
    break;

  etc..

  case default:
    break;
}

What calla said :).

Enumerating from his post just means assigning a word to the number.

Also just think of a switch as a chain of if else statements.

Sounds like a perfect opportunity to use binary flags. This is good because it allows you to then use bitwise tests to check for a range of conditions very easily. Here is a nice simple explanantion of how to do it using Javascript (I’m sure c# is very similar):

There is a beguiling elegance to doing it this way that I hope you discover :slight_smile:

Thanks for the help, callahan.44. I’ve decided to go with the enumerators method since it seems to be the easiest to read at a glance. However, the code you posted seems to be returning a couple of errors when I try to run it.

Quest npcQuest = Quest.None;

The above line of code returns the following error:
Assets/scripts/NPCdialogue.js(20,6): UCE0001: ‘;’ expected. Insert a semicolon at the end.
I’m not sure why it’s giving that error, since there clearly is a semicolon at the end of the line.

case default:    break;

The above line of code returns the following error:
Assets/scripts/NPCdialogue.js(28,8): BCE0043: Unexpected token: default.
I’m not quite sure how to use the case default command. Still a newbie to this whole scripting thing. But this is all definitely helping me learn. :slight_smile:

callahan posted C# code. I’m guessing you’re rolling with JavaScript? If so, there’s an example of the syntax here: http://answers.unity3d.com/questions/7950/how-to-declare-and-use-a-enum-variable-in-javascript

You don’t need to use an int, I probably wouldn’t because there’s no logical association with the state the NPC is in and the number value of the int, so it makes it difficult to read.

Using an enumerator in javascript to make a basic state machine is very easy, and does not need to be nearly as complicated as the FSM script on the unify community is. Use this as a base:

enum questState{ noQuest, hasQuest, onQuest, completedQuest };
var myState : questState;

function Update(){

        myState = questState.onQuest; //This is the syntax for setting myState to the state you want

	switch(myState){
		case questState.noQuest:
			//Do stuff
			break;
		case questState.hasQuest:
			//Do stuff
			break;
		case questState.onQuest:
			//Do stuff
			break;
		case questState.completedQuest:
			//Do stuff
			break;
	}

}

Sweet! Thanks for the help, guys! I don’t know what I would have done without you! :slight_smile:

Anyway, thanks to all the wonderful helpful people in this topic, I’ve got my code working to the point where the quest switch itself works perfectly, and I can print the current quest state in the debug log.

But now that’s done, I’d like to make it so that there’s an icon floating above the NPC’s head, and I want that icon to change depending on the current quest state. I’ve got the icon to display just fine, and I have all my different texture files ready, but I don’t know how to toggle the texture files.

Here’s the code:

// Controls the Quest Marker icon that displays above the NPC's head
var icon : GUITexture;
var questIcon1 : Texture;
var questIcon2 : Texture;

// Determines whether or not the NPC has a quest for you,
// and whether or not you have completed that quest:
enum questState {None, Available, Current, Complete};


npcQuest = questState.Available;

function Update()
{
 switch (npcQuest)
 {
   case questState.None:
     icon.renderer.material.mainTexture = null;
   break;

   case questState.Available:
     icon.renderer.material.mainTexture = questIcon1;
   break;

   case questState.Current:
     icon.renderer.material.mainTexture = null;
   break;

   case questState.Complete:
     icon.renderer.material.mainTexture = questIcon2;
   break;	
 }
}

The above code does not return any errors, but it also doesn’t work. Perhaps I’m simply not assigning the textures correctly?

Since you’re assigning a texture to a GUITexture class, you don’t need to mess about with materials.

http://unity3d.com/support/documentation/ScriptReference/GUITexture-texture.html

Oh, thanks, that fixed the problem.

Though now the debug log returns an error when I try to clear the texture:
Trying to set null texture on a GUITexture
UnityEngine.GUITexture:set_texture(Texture)
NPCdialogue:Update() (at Assets/scripts/NPCdialogue.js:33)
As you can see from observing my code above, I only want an icon to display under two of the four states. The icons seem to display just fine when they’re needed, but when they’re not needed I get the above error. Perhaps I’m simply not using the correct syntax again?

Here’s the code:

switch (npcQuest)
{
  case questState.None:		icon.guiTexture.texture = null; 	break;
  case questState.Available:	icon.guiTexture.texture = questIcon1;	break;
  case questState.Current:	icon.guiTexture.texture = null;		break;
  case questState.Complete: 	icon.guiTexture.texture = questIcon2;	break;
}

What else could I use besides null to clear the texture?