Search Unity

Lock Prefab Variant/child (and all its components) from editing in Editor.

Discussion in 'Prefabs' started by cubrman, Jan 6, 2020.

  1. cubrman

    cubrman

    Joined:
    Jun 18, 2016
    Posts:
    412
    Here is a unique question:

    [Short version of the question:]
    Is there a way to disable editing of values of components of a prefab variant, so that the only way of editing them is to go to the base prefab and edit them there?

    Wonder why I need this weird feature - read the long version.

    [Long version of the same question:]
    guns in my games are prefabs that have many AudioSource components in them. Originally I used the same prefab for my players (to actually implement shooting mechanics and the sound accompanying it) as well as for guns lying on the ground, waiting to be picked up. Through trial and error I realized that having a lot of guns in my scene slowed the game quite noticeably. I traced the problem to AudioSource-s. Once I removed all AudioSource-s from my guns - the lags were gone. To take advantage of this I created (for each gun) a base gun prefab that had no AudioSources on it and then inherited that prefab (created a variant) that had the AudioSources. Thus I used lightweight prefabs for guns on the ground and full prefabs for my players. The problem is - I quite often forget to change values of my components on the BASE prefab, instead of changing them on variants which results in some problems. Is there a way to lock component editing for prefab variants?
     
  2. olejuer

    olejuer

    Joined:
    Dec 1, 2014
    Posts:
    211
    I thought this was an interesting problem, so here you go. This property drawer will automatically revert all overrides to a field attributed with [NoOverride]. It will also make those fields uneditable so you immediately see they are blocked. It would be possible to do the same stuff for the entire component as well.

    Code (CSharp):
    1. public class NoOverrideAttribute : PropertyAttribute
    2.     { }
    Code (CSharp):
    1.  
    2. [CustomPropertyDrawer(typeof(NoOverrideAttribute))]
    3. public class NoOverrideDrawer : PropertyDrawer
    4. {
    5.     public override void OnGUI(Rect position,
    6.                                SerializedProperty property,
    7.                                GUIContent label)
    8.     {
    9.         bool wasEnabled = GUI.enabled;
    10.         if (property.prefabOverride)
    11.             PrefabUtility.RevertPropertyOverride(property, InteractionMode.AutomatedAction);
    12.         if (PrefabUtility.IsPartOfVariantPrefab(property.serializedObject.targetObject)
    13.             && !PrefabUtility.IsAddedComponentOverride(property.serializedObject.targetObject))
    14.             GUI.enabled = false;
    15.  
    16.         EditorGUI.PropertyField(position, property, label, true);
    17.         GUI.enabled = wasEnabled;
    18.     }
    19. }
    20.  
     
    Last edited: Jan 9, 2020
    cubrman likes this.
  3. cubrman

    cubrman

    Joined:
    Jun 18, 2016
    Posts:
    412
    Damn dude, this is really cool, thanks!
     
  4. olejuer

    olejuer

    Joined:
    Dec 1, 2014
    Posts:
    211
    Sure, hope it's helpful. There are probably some things I overlooked and it won't work when the property has some other custom PropertyDrawer. Also, if you have a larger variant hierarchy, this will block all overrides downstream. Would be cool if Unity just added such a lock to their editor, because PrefabUtility does offer all the relevant functions...