- Home /
Start, Awake, Update. Any other ways to call functions from an empty GameObject?
So I know that I can call functions that I write in my Start(), Awake(), Update(), and FixedUpdate() functions, but is there any other place or any other way to call custom functions on an empty GameObject?
Basically, there are a lot of functions that I want to happen just once, but that are inappropriate to call from Start() or Awake(). I'm currently using booleans to turn them on and off inside Update(), but this seems tedious and backwards. Is there a better way to call a particular function only once when I need it? Do I Instantiate() a prefab with another script attached with the function being called in its Start()? That seems wasteful. Advice?
Answer by TonyLi · Sep 25, 2013 at 01:13 PM
It depends on when you need to call them.
When the component is enabled or the game object is activated? Use OnEnable(). (Or OnDisable() when it's disabled/deactivated.)
On collision with another object? Use OnCollisionEnter() or OnTriggerEnter().
The whole list is on the MonoBehaviour reference: http://docs.unity3d.com/Documentation/ScriptReference/MonoBehaviour.html
The order in which they're called is documented here: http://docs.unity3d.com/Documentation/Manual/ExecutionOrder.html
If none of those fit, then a good general solution is to use coroutines. To can start a coroutine in Start(). The coroutine can hang around until it's time to do something. Then it can do something and end.
How would a coroutine "hang around" and then end? I understand they can yield return and yield return new WaitForSeconds(), but I must be missing something.
Say you want your component to disable itself 2 seconds after it becomes enabled.
function OnEnable() {
DisableAfter2Seconds();
}
function DisableAfter2Seconds() {
yield WaitForSeconds(2);
enabled = false;
}
In the code above (warning: untested, and I'm switching $$anonymous$$dsets from C# so pardon any errors), when the component is enabled, the DisableAfter2Seconds() function will idle for 2 seconds, then disable the component, and then the function will exit.
Or say you want to wait until a condition is true, and then do something. In the example below, the coroutine waits until the game object is within 5 units of a target object and then plays an animation.
function Start() {
ExplodeWhenInRange();
}
function ExplodeWhenInRange() {
var distance = Vector3.Distance(transform.position, target.position);
while (distance > 5) {
yield;
}
animation.Play("Explode");
}
Brilliant! Sometimes you just get stuck on an idea and you need someone to spell it out for you. Thanks!
Answer by Jamora · Sep 25, 2013 at 05:08 PM
Your question is quite vague, but my first idea would be to use events.
You subscribe to a particular event in each script that is interested in it, then fire that event at appropriate times.
This is only available in C# as far as I know, though you can emulate it with a construct like in this answer.
An alternative to events is SendMessage. It uses reflection so it's not a good idea to use it in Update or anything that runs frequently.
Thanks for this. I'm looking into events now, though it's a little over my head. I'll see if they can help.
Answer by dorpeleg · Sep 25, 2013 at 09:50 AM
Start(), Awake(), Upadte(), etc. are function (you don't write function within them).
They are functions that are called automatically at a certain order (decided by the "MonoBehavior").
Any other functions you create (you can create any and as much as you want), needs to be called manually.
To call functions from one gameobject to the other, use GetComponent.
The most basic answer is: yes, you have to call your functions from within one of the MonoBehaviors for them to happen.