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