Finding the Name of a Script Attached to a GameObject

I have been learning Unity for about 6 months. I am doing well with it, but always learning new things. The Unity Docs and the threads in this forum have been a great source of information.

I am making an attempt at a Finite State Machine using examples from Mat Buckland’s book, “Programming Game AI by Example.” He encourages the use of encapsulated objects for each state in a Finite State Machine. Each state knows the rules and conditions for state changes. His code is in C++ and I am using Unity Javascript. My knowledge of C++ and OOP is limited but I am learning as I try to translate.

Here is where I am at and what I am trying to figure out/understand.

I have a Player GO that was instantiated from a prefab.

I have a Finite State Wander GO with a script attached that was also instantiated from a prefab.

The Player GO calls the Execute() function from the Wander GO script and the Player GO does it’s thing (wander around).

Eventually the Player GO gets tired and needs to sleep. The Wander GO instantiates a Finite State Sleep GO from a prefab and assigns the new Sleep GO to the Player GO and then destroys itself.

The Player GO calls the Execute() function from Sleep GO script and gets some rest. And this goes on with dozens of other FSMState GO’s

So I am using prefabs for FSM States and instantiating an instance of it for the Player GO. Every FSMState has an Execute() function in its script so that is all the Player GO has to call no matter what FSMState is current.

Here is the code from the Player script that calls the Execute() function from the current state GO:

var currentState : GameObject;
.....
.....
currentState.GetComponent(currentState.name).Execute();

I have the currentState variable exposed to the inspector in the Player script, but the FSMState script does the assignment:

var fsmState = Instantiate(FsmSleep, player.transform.position, player.transform.rotation);
player.GetComponent(player.name).currentState = fsmState;

When a state change occurs, the current state instantiates the next state and destroys itself.

The problem I have here is that the I have to append “(Clone)” to all my State script names for this code to work. For instance, I make a prefab called FSMSleep. The script that I attach to it I call FSMSleep(Clone). I do this because when FSMSleep prefab is instantiated, the GO is called FSMSleep(Clone). And the code in the above line (currentState.name) actually returns the name of the GO (FSMSpeep(Clone)) and since I name my scripts with that in mind, Unity accesses the script and it’s Execute() function.

Is there any way to get the name of a script attached to a GO? I could not figure that out - all the documentation I could find assumes that you know the name of the script, but in this case I don’t since the scripts are being instantiated and destroyed along with the GO they are attached to. So I got around it with the “(Clone)'” solution.

Nevertheless, it’s all working really great, very modular, easily edited and tweaked, code is compact and encapsulated. Seems to do everything that Buckland says it should do. And I am utilizing Unity’s drag and drop architecture.

But am I doing this in a ridiculous way? Am I missing something obvious? I am still learning to program and somehow I get the feeling that I am going about this in an unusual way especially with having to name all my scripts with the “(Clone)” suffix. Any thoughts on this?

Sorry for the long post - just trying to describe this as best as I could.

Any thoughts/ideas/suggestions to do this in a more clever/efficient way? It’s all about learning for me.

Thank you for your time.

Mitch

Any time you call Instantiate on an object, it adds (clone) to the name. So when you instantiate it, you can do something like: (note: code is not tested)

var newGO : GameObject = Instantiate(myPrefab);
newGO.name = newGO.name.Substring(newGO.name.Length - 7);

which should remove “(clone)” from the end of the name. (You may have to make that - 8 to remove the space as well, I’m not sure.)

Hope this helps.

The problem is that you have to know the name of the script before you can retrieve it with GetComponent. If each state GO is guaranteed only to have one script attached, then you might be able to find it by iterating through all components until you find one that is a subclass of MonoBehaviour.

Another possibility might be to derive all your state script classes from a subclass of MonoBehaviour. If you had a class called StateScript, say, with a method called Execute, then you could override this method in all of your state classes. The currentState variable in the Player object would then be of type StateScript (ie, the same superclass but with different behaviour depending on which exact subclass it was). However, I’m not sure if you can subclass from anything but MonoBehaviour in Unity JavaScript - you might need to use C# or Boo for this.

Buckland’s encapsulation approach is quite a good way to ensure that the state transition and action code is independent for each state and doesn’t end up as one giant switch statement. (I don’t find his robot kitten analogy as funny as he evidently does, though.) As you say, it lends itself well to the Unity inspector, and there is the possibility of arranging your state objects spatially in some meaningful way and then using Gizmos to draw transition arrows between them - a great visualisation tool.

The problem is that in some cases, states tend to have data or code in common and it can be a nuisance to share all of it between states when they are in different classes. For example, you might resort to putting the common data in the Player class and accessing this from the state classes. Also, the state “action” will often be something very short - the overhead of creating a new class, Execute method, etc, just for a single line of actual code will probably get boring even quicker than the robot kitten.

A completely different approach is discussed in Rabin et al’s “Game AI Programming Wisdom I” (in fact it covers state machines and several other techniques in some depth - well worth reading). This uses a single FSM class with C++ macros to implement a mini state machine “language” which is actually a switch statement underneath, but heavily abstracted to make it safe and convenient to use. There are no macros in Unity, but I have achieved much the same effect using attributes to mark methods out as state actions (ie, you write a method and then add an attribute that says “this is the state entry function for states 1, 4 and 8”, etc). I can post this code if you think it might be useful, but I will need a bit of time to remind myself exactly how it works and write a brief explanation.

In summary, there are several approaches to building a state machine and some may be more convenient than others, depending on what your game is doing.

Thanks guys - it worked. I had to tweak the code a little

var newGO : GameObject = Instantiate(myPrefab);
newGO.name = newGO.name.Substring(0, newGO.name.Length - 7);

And thanks Andeeee for your recommendation on Rabin’s book. When I am done with Buckland, I’ll start on that.

I hear what you are saying about a state class and an execute method. I’m trying to learn all about that because I think that is probably the better way to do this.

I’d love to see your code you mention - it may be over my head, but I’m learning quite a bit the deeper I dive.

Thank you both for helping!