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

UnityEvents are not usable in prefabs

Discussion in 'Prefabs' started by SurprisedPikachu, Apr 10, 2020.

  1. SurprisedPikachu

    SurprisedPikachu

    Joined:
    Mar 12, 2020
    Posts:
    84
    I have an annoying problem which makes UnityEvents unusable with prefabs.
    I have a prefab in the scene which has this:
    upload_2020-4-10_16-51-3.png

    When I go into prefab mode, The prefab looks like this:
    upload_2020-4-10_16-51-56.png

    Now if I want to add another callback to the event in Prefab Mode, the 4th event that is assigned in the scene starts to override the newly added callback in the prefab mode.

    It makes prefabs with unity events IMPOSSIBLE to scale.

    Is there any solution to this?
     
  2. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    Hi,

    What you have encountered is a limitation in how property overrides on arrays are handled in Unity.

    Basically when you change an array on a prefab instance the following happens.
    • A absolute change in size is recorded, e.g size is now 4.
    • A change at an element in recorded, e.g element 3 equals GameObject.SetActive
    This is fine until you change the array in the prefab asset.

    In your case you have resized the array in the prefab asset to 4 and set the element at index 3 to something.

    Now when the prefab asset in the scene applies its overrides, the size if still 4 because that is what is stored in the scene and the scene also sets the element at index 3 to `GameObject.SetActive` basically overwriting your change in the prefab asset.

    Of course what should have happened is the size of the array in the scene become 5 and the scene should set the element at index 4 to GameObject.SetActive

    or should it really?

    What do you as the user actually expect will happen in this case. What if you really wanted the scene to insert its element at index 3 pushing the new element in the prefab asset to the end?

    Alright. Then Unity should do an interactive merge of the array that allows the user to specify what should happen, but when should that be done.
    • When you open the scene?
      • Then what about all the scenes you forget about and don't open and you build a standalone player that is broken.
    • When saving the prefab?
      • Potentially forcing Unity to open hundreds of scenes where you might have to perform the merge on hundreds of prefabs
    I guess that what should really happen depends on the prefab and your setup and it might differ between prefabs, so we can't specify one single rule that will perform the expected action on all types of array changes.

    I am open for suggestions to changing the behavior of array merging.

    Cheers.
     
    JoNax97 likes this.
  3. SurprisedPikachu

    SurprisedPikachu

    Joined:
    Mar 12, 2020
    Posts:
    84
    What I was initially expected was to work just like prefab variants.
    With prefab variants, the original objects and order of them is kept at the beginning of the gameobject.
    For example:
    Code (csharp):
    1.  
    2. Original:
    3. > Root
    4. --> Obj1_In_Original
    5. --> Obj2_In_Original
    6.  
    7. Variant:
    8. > Root
    9. --> Obj1_In_Original
    10. --> Obj2_In_Original
    11. --> Obj1_In_Variant
    12. --> Obj2_In_Variant
    13.  
    You cannot change the order of Obj1_In_Original and Obj2_In_Original objects in a variant. You cannot delete them, You can only deactivate them. But you have full control over Obj1_In_Variant and Obj2_In_Variant.

    And if you add another object in original prefab, it will look like this in Variant:
    Code (csharp):
    1. > Root
    2. --> Obj1_In_Original
    3. --> Obj2_In_Original
    4. --> Obj3_In_Original
    5. --> Obj1_In_Variant
    6. --> Obj2_In_Variant
    7.  

    With UnityEvents, I was expecting that all callbacks in original prefabs should be kept at the beginning of the event, and then scene callbacks should come after them.

    Of course this approach may stop some people from doing some specific use cases (Like putting a new callback before every callback in original prefab) but it makes it FAR FAR more usable. Actually I don't know if anyone is using UnityEvents for anything serious in their projects in its current state.
     
    sp-LeventeLajtai likes this.
  4. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    The problem is that it is not only for Events.

    Events are stored in an array, so in this case it has to be a generic solution for merging of arrays, which I simply don't see a solution for as it is different for each prefab how you want the arrays to merge
     
  5. sp-LeventeLajtai

    sp-LeventeLajtai

    Joined:
    Jul 11, 2019
    Posts:
    10
    What SurprisedPikachu says makes a lot of sense, I was expecting the same behaviour: take the values from the base, disallow removing in variants, but allow modifying, and new elements go to the end of the list. I don't see any problem to make arrays work this way. Or if there is a problem, another option is to specialize it for UnityEvents.
     
  6. victor_apihtin

    victor_apihtin

    Unity Technologies

    Joined:
    Mar 2, 2021
    Posts:
    28
    I dont know whether this is fixed later on, but for me in 2019 LTS there is also an issue with UnityEvent where you can only revert the elements, but not the list itself. It makes it weird. As @SteenLund mentioned, the override applies to the entire list, but display name of an event does not get bold when changed, and it is not context-clickable.
    Fortunatelly it is possible to go into Debug mode and get apply/discard option for the entire list