attached component and event scope logic

Hi Unity Devs

Im hoping to get some deeper understanding of the best method for creating utility classes (unityscripts)
of which im going to need multiple instances of within another script. I have a working solution for my problem
but it requires me to set a reference … and alas im stuck now pondering if there is something im missing in the understanding of
unitys gameobject /component relationships and would love some input.

The issue Im trying to grasp here is unity event system working under the nested component system which only seems to trickle downwards
, let me give an example :

I have a “animal” GameObject , attached is a script “AnimalAI” , the controller.

In this script “AnimalAI” I would like to create two instances of an untility script with encapsulates state Management named “StateManager”, One to handle mood states and another to handle Acion states.

here is what ive all tested:

(option a) If I attach “StateManager” to “animal” GameObject and then within “AnimalAI” get a reference to use it for instancing with Instantiate
it recreates the “animal” GameObject as well , as the documentation explains … so this is not an option…

next test…

(option b) IF I create a variable in “AnimalAI” for “StateManager” I can not directly drag a “StateManager” script from project view onto this as the IDE will not permit this and has no drop action.

next test…

(option c) So I create an empty gameObject in the scene , add the “StateManager” script to this and now I drag this gameobject onto the variable reference
I created within"AnimalAI" which is datatyped to “StateManager” .

This works and I create two instances of it with ease and can target the “StateManager” variables directly , unity seems to bypass the actual gameobject scope (on which the “StateManager” script is attached)
when using Instantiate and now references the attached scripts.

BUT now if I want to use SendMessage or BroadcastMessage within “StateManager” instances , It seems to now remember the gameobject (on which it is attached) and the scope for receiving the message
the animal gameobject , is one up. Im baffeled here … documentation says for unity messages to work they need to be in the same scope of gameObject or a child etc…
but I cant attach them within the same scope as when calling Instantiate on one of them it recreates the whole parent gameobject as mentioned above?

In actionscript the holding instance that creates another registers itself for an event of that instance and this sets the scope.

(option d) So I solved this problem by the reference I mentioned in the start of this post , using (option c) In “StateManager” I created a variable named “targetGameObject”, and when
“AnimalAI” creates an instance of “StateManager” it sets “targetGameObject” to “gameObject” , which is then “animal” GameObject.
“StateManager” then calls targetGameObject.SendMessage or targetGameObject.BroadcastMessage and “AnimalAI” picks up the event as it is a child of “animal” GameObject.

how else do you get this child component and event system to work ??? …?

If you have read this far and understand what im pondering here (attached component and event scope logic ) , and have a suggestion
or opinion for what the best method would be to achieve this kind of OOP in unityscript , I have 6+ years experience with
actionscript and have some knowledge of other languages as well so feel free to explode with meaty answers here… im all ears.

(option e any thoughts?)

Thanks

It sounds like you have some confusion around the purpose and use of the Instantiate() function; it’s for creating game objects in your scene, not for creating instances of scripts. You can create an instance of a script the same as you create an instance of any class type:

var manager : StateManager = new StateManager();

In that case, StateManager should not inherit from MonoBehaviour, but it shouldn’t anyway unless you need it to get the MonoBehaviour events like Start(), Update(), etc.

If StateManager does need those events, then it needs to derive from MonoBehaviour and be attached to a game object. However, I don’t understand why you’d want it attached to a different game object in that case. Assuming an AnimalAI script needs its own StateManagers (rather than needing to call a StateManager belonging to a different AI unit), there’s no reason to start adding game objects just to hold StateManagers. The easiest way would probably be to use AddComponent() in AnimalAI’s Start() method to create the StateManager instances.

You also don’t need SendMessage() – in fact, you should avoid its use unless you specifically need the flexibility it provides, since it’s somewhat slow. You’re much better off calling functions directly, unless you have a situation where you want to say ‘call this function everywhere it exists’ without knowing what might be implementing the function. SendMessage() is like a broadcast: it ‘waves a flag’ indicating that something happened, and any script interested in reacting ‘notices the flag’ by implementing the receiver function.

In short, ignore Instantiate(); it’s not relevant to the problem you’re trying to resolve. Read the scripting guide sections on accessing other scripts and game objects; there’s probably a much simpler way to do what you want. And if all else fails, post again with a more focussed description of what you want to achieve and some sample (pseudo)code.

Thanks laurie

I ran some tests after your reply and AddComponent was the way to go. No need to have any dependency injection as it seems to just find the script in the project view. eg : moodStateManager = gameObject.AddComponent(“StateManager”)

and it seems that by default unityscripts that dont explicitly declare themselves as a class are extentions of MonoBehaviour by default an so I have all the functionality of Awake , Update etc… (which I did require and use within my code). I actually have a class declared within this script for the instances of each individual state that are registered with the manager, Its an functional state manager and not a value object storage unit eg… it can register static states , timed states with queued state sets on timeout if needed and all have priority overwrite conditions etc blah blah let me know if you wanna have a look at the code.

So all is working now and the scripts are within the same scope / gameobject for the SendMessage , on that note I was not aware of the speed issue with SendMessage , how bad is it ?? as my current set up has no dependencies back onto its creator which is how I thought it be best done from an OOP point of view , otherwise I need to create a untyped variable within the class to keep it portable between any other script , or perhaps a function pointer mm. lemme go check that out.

Thanks again.

I wouldn’t worry too much about the speed.

On a very slow machine, I’m seeing little to no hit on the frame rate with 100 messages sent per frame. Even at 10,000 messages sent per frame, I’m still getting around 30 fps.

Granted, I’m not passing an argument, that might slow it down more.