Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

ChangeCheckScope vs BeginChangeCheck ... Which to use?

Discussion in 'Scripting' started by Michael-Ryan, Apr 19, 2020.

  1. Michael-Ryan

    Michael-Ryan

    Joined:
    Apr 10, 2009
    Posts:
    184
    Is using UnityEditor.ChangeCheckScope recommended over EditorGUI.BeginChangeCheck, or vice versa?

    I'm asking, because using the scope creates a new temporary object every time the OnGUI method is called, and the scope constructor then calls
    UnityEditor.ChangeCheckScope internally.

    It seems like for simple code that is unlikely to produce any exceptions or early terminations, it would be better to call
    BeginChangeCheck directly and avoid the object creation, assuming the corresponding EndChangeCheck will be called after right afterward.

    However in the following code, the
    value parameter could be null and that would generate an exception. When that happens, I believe using the ChangeCheckScope would be better, since it should automatically call EndChangeCheck when the scope is terminated.

    Is this correct?


    It is recommended to always use ChangeCheckScope or should BeginChangeCheck be used where it makes sense?

    Code (CSharp):
    1. private static void Toggle1(GUIContent label, BoolObject value, Action<bool> action)
    2. {
    3.    EditorGUI.BeginChangeCheck();
    4.  
    5.    var toggle = EditorGUILayout.Toggle(label, value.Bool);
    6.    if (EditorGUI.EndChangeCheck())
    7.    {
    8.       value.Bool = toggle;
    9.       action?.Invoke(toggle);
    10.    }
    11. }
    12.  
    13. private static void Toggle2(GUIContent label, BoolObject value, Action<bool> action)
    14. {
    15.    using (var check = new EditorGUI.ChangeCheckScope())
    16.    {
    17.       var toggle = EditorGUILayout.Toggle(label, value.Bool);
    18.       if (check.changed)
    19.       {
    20.          value.Bool = toggle;
    21.          action?.Invoke(toggle);
    22.       }
    23.    }
    24. }
     
    hamza_unity995 likes this.
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,843
    Well not if you check it for null first and don't bang on it if it's null!!!

    I honestly don't know what API would be better as I haven't used either approach in quite a while, but I do know how to guard against null references.
     
  3. Michael-Ryan

    Michael-Ryan

    Joined:
    Apr 10, 2009
    Posts:
    184
    Yeah. I understand a null could be performed before the Toggle(). I was just trying to provide a simple case that would potentially cause the EndChangeCheck to not get called.
     
  4. Xtro

    Xtro

    Joined:
    Apr 17, 2013
    Posts:
    610
    I have the same question. Which one to use when?
     
  5. Xtro

    Xtro

    Joined:
    Apr 17, 2013
    Posts:
    610
    I just looked at the source of ChangeCheckScope. It's actually using BeginChangeCheck internally. I wonder why they implemented ChangeCheckScope as a wrapper.
     
  6. tylertempdev

    tylertempdev

    Joined:
    Dec 20, 2019
    Posts:
    5
    Cuz `ChangeCheckScope` will automatically call the `EndChangeCheck` once you leave the `using` code scope. "creates a new temporary object" is not THAT performance-consuming. Thus I'd recommend`ChangeCheckScope`
     
    hamza_unity995 likes this.
  7. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,013
    I wonder if this was to help make IMGUI code a little more 'C#' and readable, as most often I see folks using
    {   }
    code blocks between begin/end methods, like so:

    Code (CSharp):
    1. GUILayout.BeginHorizontal();
    2. {
    3.     // IMGUI here
    4. }
    5. GUILayout.EndHorizontal();
    6.  
    7. // can just be
    8.  
    9. GUILayout.BeginHorizontal();
    10. // IMGUI here
    11. GUILayout.EndHorizontal();
    The Scope methods implementing the IDispoable using-block pattern I find to be more readable, especially helpful when IMGUI often creates rather messy code in general.