Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Toggling on/off update() event

Discussion in 'Scripting' started by Nanako, Sep 26, 2014.

  1. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    So i'm still new here (but not new to coding in general) going through one of the unity tutorials, the stealth one where iwe're first introduced to code.

    It wants me to make this function:

    Code (CSharp):
    1. void Update ()
    2.     {
    3.         // If the light is on...
    4.         if(alarmOn)
    5.         {
    6.             // ... Lerp the light's intensity towards the current target.
    7.             light.intensity = Mathf.Lerp(light.intensity, targetIntensity, fadeSpeed * Time.deltaTime);
    8.            
    9.             // Check whether the target intensity needs changing and change it if so.
    10.             CheckTargetIntensity();
    11.         }
    12.         else
    13.             // Otherwise fade the light's intensity to zero.
    14.             light.intensity = Mathf.Lerp(light.intensity, 0f, fadeSpeed * Time.deltaTime);
    15.     }
    I went and checked the documentation just to be sure that's doing what i think it is. And i was right, update() is called every frame

    The object this script is in, DOES need to do things every frame, but only when the alarm is on. In this game, the alarm is not on by default, and i think it's going to be possible to turn it off too. So this doesn't need to be running at all times.

    I know in the grand scheme of things, this is relatively little. It's basically nothing in terms of CPU time. But this is a matter of principle. It is an inefficiency and i will not have it in my code, at least if i can help it.

    Is there any way i can make a script start/stop recieving update events? Does C# support switching to different states ? (a similar feature from another scripting language i've used, which would solve this nicely)
     
  2. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    Code (csharp):
    1. enabled = true;
    2. enabled = false;
    This is a property of all MonoBehaviours. It will prevent Start(), Update(), LateUpdate(), and FixedUpdate() from getting called. It will also cause OnEnabled() and OnDisabled() to be called when the MonoBehaviour is enabled or disabled.
    http://docs.unity3d.com/ScriptReference/Behaviour-enabled.html
     
    Nanako likes this.
  3. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047

    Thank you. Although that has to be the shortest and least helpful reference document i've ever seen :(

    I need a little clarification. how would i use if? Something like this?

    Code (CSharp):
    1. Update.enabled = false;
    To turn off the update event ?
     
  4. Kogar

    Kogar

    Joined:
    Jun 27, 2013
    Posts:
    80
    An alternative would be the usage of coroutines and getters/setters In this case you also would not need update() and can completly remove it from the script. But you won't be able to see alarmOn in the inspector. CustomEditor/PropertyDrawer can solve that.

    Not tested but should be something like that
    Code (csharp):
    1. private bool _alarmOn;
    2. public bool alarmOn
    3. {
    4.    get{ return _alarmOn; }
    5.    set
    6.    {
    7.      _alarmOn = value;
    8.        StopCoroutine("alphaFade");
    9.      if(_alarmOn==false)
    10.        StartCoroutine("alphaFade", 0));
    11.      else
    12.        StartCoroutine("alphaFade", targetIntensity));
    13.    }
    14. }
    15.  
    16. public float alphaFadeSeconds = 0.1f;
    17. IEnumerator alphaFade(float alpha)
    18. {
    19.    float start = Time.time;
    20.    while(light.intensity != alpha)
    21.    {
    22.      float elapsed = Time.time - start;
    23.      float normalisedTime = Mathf.Clamp((elapsed / alphaFadeSeconds)*Time.deltaTime, 0, 1);
    24.      light.intensity = Mathf.Lerp(light.intensity, alpha, normalisedTime) ;
    25.      yield return 0;  
    26.    }
    27.    CheckTargetIntensity();
    28.    yield return true;
    29. }
     
    Nanako likes this.
  5. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    No, not like that. With that property you can turn on/off a whole script as a component. It won't be running anymore until you enable it again. Thus i'd recommend to control it from the outsight of the script, unless you don't want the alarm to be triggered again, in this case you can set it in the script itself with the code which @Garth Smith posted. You may of course want to add some sort of control
     
    Nanako likes this.
  6. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    So you can see here, we can enable or disable the "EnableDisableClass". This is the same as unchecking the box next to the script in the inspector, which is different from unchecking and deactivating the entire GameObject.

    So here you can see by running SetEnabled(false) it will cause Update() to stop running and OnDisabled() will get called once.

    Here I wrote some code that I hope is more understandable. Setting enabled to false does not stop the script from working, it only stops certain functions from getting called.
    Code (csharp):
    1. public class EnableDisableClass : MonoBehaviour
    2. {
    3.   /// True to run Update(), Start(), FixedUpdate() and LateUpdate().
    4.   /// False to stop running those functions.
    5.   /// Will also cause OnEnabled() and OnDisabled() to get called.
    6.   /// Can call this even if enabled == false already.
    7.   public void SetEnabled(bool trueOrFalse)
    8.   {
    9.     // Affects this EnableDisableClass object only.
    10.     // enabled is a bool that is inherited from MonoBehaviour
    11.     enabled = trueOrFalse;
    12.   }
    13.  
    14.   /// This will only display if enabled == true.
    15.   /// If enabled == false then Update() will not even run.
    16.   void Update()
    17.   {  
    18.     Debug.Log("We are on frame " + Time.frameCount);
    19.   }
    20.  
    21.   /// This will be called once when we change enabled from false to true.
    22.   void OnEnabled()
    23.   {
    24.     Debug.Log(name + " was enabled.");
    25.   }
    26.  
    27.   /// This will be called once when we change enabled from true to false.
    28.   void OnDisabled()
    29.   {
    30.     Debug.Log(name + " was disabled.");
    31.   }
    32. }
     
    Last edited: Sep 27, 2014
  7. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    referencing public functions in a class from externally is something i haven't gotten to yet, but i'm sure it won't be too hard once i do.

    But does disabling the script prevent all code execution, or just prevent these events from being triggered? If i try to call a function in a script which is disabled, would it work and return a value ? For example, that setEnabled function right there in the example above. If the script started in a disabled state, could i call that from an external script in order to enable the alarm ?
     
  8. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    Yeah the functions all work normally even if enabled is false. The update functions just don't run. You could still call Update() yourself if you really wanted to, it just won't get called automatically.
     
    Nanako likes this.
  9. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    Wow, i completely skipped over this post first time, but i just went and researched it. Wow, i am definitely going to need coroutines for a future project i have planned. Thank you for bringing this to my attention <3 I think it's a bit over my head at the moment though, i won't use this for now. But biiiig thanks still.
     
  10. Charles-Andrew

    Charles-Andrew

    Joined:
    Dec 14, 2015
    Posts:
    2
    Just a question, i know this is very old but if you disable a script that has an update on it, an you enable it inside a method, will the update run at the same time as the method that enabled it or will it run on the next frame?
     
  11. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    OnEnabled will be run at the time you enable the MonoBehaviour. Update will run the next time Update methods are called, along with all the other Update methods. I don't know if you enable the MonoBehaviour inside another script's Update method if the now enabled Update method will be called that frame or the following frame. Should be easy to test through with some debug.log messages.
     
  12. blairhoughton

    blairhoughton

    Joined:
    Jan 5, 2019
    Posts:
    9
    I just tried that. I have an object with a method called Clicked is called from the actual click handler in a button object; and of course it has the Update and Start functions. When the button is pressed its handler instantiates one object and then calls the Click method for every object instantiated so far.

    I instrumented all three functions to print Time.frameCount to the debug console.

    When the button is pressed, the Clicked frameCount is shown, then Start prints the same frameCount, and the first Update prints an incremented frameCount.

    When the button is pressed again, the Clicked and Update frameCounts for the first object are equal, and the counts for the second object look like before.

    But, if I gate the enabled flag by turning it false in Update (after printing the frameCount) and enabling it in Clicked, what happens?

    The frameCount for the Update method is 1 more than the frameCount for the Clicked method, always. The Start frameCount is equal to the Clicked frameCount.

    Bottom line:
    1. Setting enabled=true in an event handler in one frame doesn't take effect until the following frame.
    2. If enabled is already true then the event can change data used by the update in the same frame.
    3. If the event instantiates the object then Start will be called in the same frame but the first update will happen in the next frame.
     
    atomicjoe and gitlinjoss like this.
  13. gitlinjoss

    gitlinjoss

    Joined:
    Mar 16, 2020
    Posts:
    6
    Reviving an old thread, I know, but I'm trying to externally reference @GarthSmith 's EnableDisableClass.SetEnabled(bool) function from another class in a different script file. The problem I run into, when referencing it using
    EnableDisableClass updateDisable = gameObject.GetComponent<EnableDisableClass>();
    updateDisable.SetEnabled(false);

    is that the Update() function that gets disabled is the one in the EnableDisableClass script, not the Update() function in the script I'm trying to disable it in. I'm sure this is basic object-oriented programming 101 but I'm new to this so if anyone can help it would be awesome! Cheers.
     
  14. atomicjoe

    atomicjoe

    Joined:
    Apr 10, 2013
    Posts:
    1,865
    You don't need this class for anything, it was just an example.
    If you want to disable the update function of a component, just set it's own "enabled" property to false: component.enabled = false
    If you want to disable the update function of a component from inside it's own code, just use "this.enabled = false" and you're done. But keep in mind that if you want to reenable it again, you will have to change it's "enabled" property from another script, since this script will not be running by itself anymore.