Search Unity

Run code on "Add Component"

Discussion in 'Editor & General Support' started by kipete, Jan 23, 2017.

  1. kipete

    kipete

    Joined:
    Nov 24, 2015
    Posts:
    47
    I would like to write some code that will automatically set up particular components the way i like them set up when someone adds that component from the "Add Component" button at the bottom of the inspector. I already have my code as a menu item however would prefer this method as well.

    Can anyone suggest anything?
     
  2. Nabren

    Nabren

    Joined:
    Mar 7, 2014
    Posts:
    61
  3. kipete

    kipete

    Joined:
    Nov 24, 2015
    Posts:
    47
    I need this on the editor side not on the non-editor side.
     
  4. SarfaraazAlladin

    SarfaraazAlladin

    Joined:
    Dec 20, 2013
    Posts:
    280
    I have no idea if this would work, but you could try making a custom constructor for your class, and in it look for the components you want to set. If they exist, than GetComponent<>() and do what you gotta do
     
  5. kipete

    kipete

    Joined:
    Nov 24, 2015
    Posts:
    47
    that would most likely work non-editor side. however i need something editor side
     
  6. BFS-Kyle

    BFS-Kyle

    Joined:
    Jun 12, 2013
    Posts:
    883
    This is exactly what you want. Execute in edit mode will run code in Edit Mode (i.e. in the Editor). Then you would check if you are in the editor, and the game is not playing (i.e. edit-mode), then run whatever code you want.

    Alternatively, you can make use of the Reset function, which is called whenever you Add a component in the editor, or choose to Reset it (https://docs.unity3d.com/ScriptReference/MonoBehaviour.Reset.html)
     
    skabed and Nabren like this.
  7. kipete

    kipete

    Joined:
    Nov 24, 2015
    Posts:
    47
    No that is not what i want. i do not want my script executing in edit mode. i want a function that is in a CS file in the editor folder to be called when someone clicks on my classes name in the "Add Component" list. then i will be able to do things only available in editor mode to setup my assets the way i prefer
     
  8. kipete

    kipete

    Joined:
    Nov 24, 2015
    Posts:
    47
    The reset looks like it could work. However it requires me to have editor code in my classes' CS file.
     
  9. fffMalzbier

    fffMalzbier

    Joined:
    Jun 14, 2011
    Posts:
    3,276
  10. kipete

    kipete

    Joined:
    Nov 24, 2015
    Posts:
    47
    again i need this to be on the editor side. therefore attaching more stuff to the Monobehavior is nice. it does not allow me to get to certain things inside the UnityEditor namespace without numerous #if UNITY_EDITOR across my code. if that is the way that Unity designed it and it can not be worked around, then that is understandable i will work with unclean code.however the editor folders are designed for unity editor specific things of which this should be one. why can i not access this through code only available in the editor folders?
     
  11. fffMalzbier

    fffMalzbier

    Joined:
    Jun 14, 2011
    Posts:
    3,276
    You can hide the normal add component entry via the AddComponentMenu
    atribute.
    Then you can use a editor script that lives inside the editor folder to create a menu entrance for attaching the component.

    (inside the editor script)
    Code (CSharp):
    1.     [MenuItem("Component/Scripts/DisableOnStart")]
    2.     static void DisableOnStartConstructor(MenuCommand command)
    3.     {
    4.         Debug.Log("Do stuff");
    5.         Selection.activeGameObject.AddComponent<DisableOnStart>();
    6.     }
    For that you can use the "MenuItem" Atribute
    https://docs.unity3d.com/ScriptReference/MenuItem.html

    Its not the same as the original addcomponent entry but for strict separation of editor and runtime code this should work.
     
  12. kipete

    kipete

    Joined:
    Nov 24, 2015
    Posts:
    47
    the "" does remove the component from the menu. however since i cant remove standard unity items i guess the best thing to do would to be drop this as there are ways apparently to do it however nothing that is entirely clean.
     
  13. BFS-Kyle

    BFS-Kyle

    Joined:
    Jun 12, 2013
    Posts:
    883
    You can just wrap the entire Reset function within #if UNITY_EDITOR.

    If you want the script to be called to live in the Editor folder instead of in the MonoBehaviour, then you could create a custom inspector for the MonoBehaviour in the Editor folder, and take advantage of that.

    Is there something you dislike about compiler #if defines? They don't instantly mean unclean code - they are essential for cross-platform development in many cases, and make things much simpler and easier to follow than some alternatives.
     
    glucosetong and kodo91 like this.
  14. bloodthirst69

    bloodthirst69

    Joined:
    Oct 1, 2017
    Posts:
    28
    sorry for the necro but i think this wil help futur seekers , i found a solution and i wanted to share it , you can subscribe to this (https://docs.unity3d.com/ScriptReference/ObjectFactory-componentWasAdded.html) event in the editor.
    Here's an example where i use it to disable Raycast/Masking on added UI components

    Code (CSharp):
    1.     [InitializeOnLoad]
    2.     public class EditorOnComponentAdded
    3.     {
    4.         static EditorOnComponentAdded()
    5.         {
    6.             ObjectFactory.componentWasAdded -= HandleComponentAdded;
    7.             ObjectFactory.componentWasAdded += HandleComponentAdded;
    8.  
    9.             EditorApplication.quitting -= OnEditorQuiting;
    10.             EditorApplication.quitting += OnEditorQuiting;
    11.         }
    12.         private static void HandleComponentAdded(UnityEngine.Component obj)
    13.         {
    14.             if (obj is Graphic graphic)
    15.             {
    16.                 graphic.raycastTarget = false;
    17.             }
    18.             if (obj is MaskableGraphic maskable)
    19.             {
    20.                 maskable.maskable = false;
    21.             }
    22.         }
    23.  
    24.         private static void OnEditorQuiting()
    25.         {
    26.             ObjectFactory.componentWasAdded -= HandleComponentAdded;
    27.             EditorApplication.quitting -= OnEditorQuiting;
    28.         }
    29.     }