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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

ExecuteInEditMode seems to not be working. Why?

Discussion in 'Scripting' started by Nanako, Jun 8, 2015.

  1. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    Edit: The original problem in this post has been more or less solved, but i've resurrected this thread for a reason. Read from post #6 onwards

    Here is my code: http://pastebin.com/hNMdsKZy
    the [ExecuteInEditMode] is on line 53, and i've put a debug message in start to indicate if it's working. It seems to not be working.

    I'm not quite clear on whether it's supposed to be inside a class or not, so i also tried this, with it on line 4 outside of any classes: http://pastebin.com/L4eJ9tBt

    Still not working. I'm stumped.
    The debug message fires as soon as i enter play mode and everything functions perfectly then, which is neat but not adequate for my purpose.
     
    Last edited: Jul 21, 2015
  2. tomvds

    tomvds

    Joined:
    Oct 10, 2008
    Posts:
    1,028
    [ExecuteInEditMode] is an attribute (https://msdn.microsoft.com/en-us/library/z0w1kczw.aspx).

    Attributes can attach meta data many different declarations, classes, methods, variables, etc. Whether the meta data does something depends on the context. [ExecuteInEditMode] is only relevant when applied to MonoBehaviour classes. It tells unity that that specific MonoBehaviour needs to run in edit mode. In your first code sample, you attached the attribute to a function (which is meaningless). In your second code sample, you attached it to the ObjectPart class, which is not the class you want to execute in edit mode. Move the [ExecuteInEditMode] line to just before your InteractiveObject class definition and it should execute in edit mode.
     
    Nanako likes this.
  3. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    7,851
    Hi.

    Don't use constructors on MonoBehaviours. You cant instantiate a script that derives from MonoBehaviour using new, you must use AddComponent.
    The ExecuteInEdit mode is not working because your MonoBehaviour scripts are not attached to GameObjects.
    Add the attribute to InteractiveObject instead of ObjectPart.
    Change ObjectPart so it does not inherit from MonoBhevaiour and add the [System.Serializable] attribute to it so you can see it in the inspector.
     
    Kalificus likes this.
  4. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    thank you tomvds <3

    re: constructor, good point. i just removed the monobehaviour inheritance to solve that.
     
  5. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    Ok i could have sworn i got this working, but now it isn't. Maybe i didn't make it work to begin with.

    Here's what i've got: http://www.pasteall.org/59157/c

    OnValidate does run in edit mode, but Start() does not, and thusly all the bootstrapping functions it contains aren't running, and lists aren't getting populated with necessary data

    i have the [ExecuteInEditmode] just before the interactiveObject class, so shouldn't it work?
     
  6. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    7,851
    ExecuteInEditMode will only call Update, OnGUI and OnRenderObject, Start will not be called.
    If you need to do some init maybe do it in the Update and use a flag so its only done once.

    Why does it need to run in edit mode?
     
    BikramKumar likes this.
  7. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    Now just hold on one minute!

    I took your advice, i got it working with Update and a flag like you said, and i called it done a month ago.

    And then i just stumbled upon this script, which i wrote several months ago:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. [ExecuteInEditMode]
    4. public class DropToFloor : MonoBehaviour {
    5.  
    6.     // Use this for initialization
    7.  
    8.     Vector3 MiddleBottom;
    9.     Vector3 GroundPoint;
    10.     Vector3 min;
    11.     Vector3 max;
    12.     LayerMask layerMask;
    13.  
    14.  
    15.     void Awake()
    16.     {
    17.         print("Droptofloor is starting");
    18.         if (FindBottom())
    19.         {
    20.             FindGround();
    21.             Move();
    22.         }
    23.      
    24.     }
    25.     void Start()
    26.     {
    27.         DestroyImmediate(this);
    28.     }
    29.  
    30.     bool FindBottom()
    31.     {
    32.      
    33.         if (GetComponent<Collider>())
    34.         {
    35.             min = GetComponent<Collider>().bounds.min;
    36.             max = GetComponent<Collider>().bounds.max;
    37.         }
    38.         else if (GetComponent<Renderer>())
    39.         {
    40.             min = GetComponent<Renderer>().bounds.min;
    41.             max = GetComponent<Renderer>().bounds.max;
    42.         }
    43.         else
    44.         {
    45.             Collider[] temp = GetComponentsInChildren<Collider>();
    46.             foreach (Collider col in temp)
    47.             {
    48.                 if (min.y > col.bounds.min.y && (min.x > col.bounds.min.x || min.z > col.bounds.min.x))
    49.                 {
    50.                     min = col.bounds.min;
    51.                 }
    52.  
    53.                 if (max.y < col.bounds.max.y && (max.x < col.bounds.max.x || max.z < col.bounds.max.x))
    54.                 {
    55.                     max = col.bounds.max;
    56.                 }
    57.             }
    58.         }
    59.  
    60.         //We find a point that is centred on the X and Z axes, but minimal on the Y axis
    61.         float Xrange = max.x - min.x;
    62.         float Zrange = max.z - min.z;
    63.  
    64.         MiddleBottom = new Vector3((min.x + (0.5f * Xrange)), min.y, (min.z + (0.5f * Zrange)));
    65.         //MiddleBottom += transform.position;
    66.         MiddleBottom.y -= 0.01f;
    67.         return true;
    68.     }
    69.  
    70.     void FindGround()
    71.     {
    72.         layerMask = PhysicsTools.BuildCollisionProfile(gameObject);
    73.         RaycastHit hit;
    74.         Physics.Raycast(MiddleBottom, Vector3.down, out hit, Mathf.Infinity, layerMask);
    75.         print("Hit :" + hit.collider.gameObject.name+"   "+hit.point);
    76.         GroundPoint = hit.point;
    77.     }
    78.  
    79.     void Move()
    80.     {
    81.         Vector3 diff = GroundPoint - MiddleBottom;
    82.         print("Diff: " + diff+"     "+MiddleBottom);
    83.         diff.y += 0.01f;
    84.         transform.position = transform.position + diff;
    85.     }
    86.  
    87. }
    88.  
    Yeah, it uses Awake and Start. It executes in edit mode, and it WORKS!
    I just tested it to be sure, it's fully functional still.

    What's the deal here?

    For anyone wondering what this does: When dropped into an object, it does some stuff to it (positions it touching the ground) and then the script deletes itself when finished. It's an authortime tool i wrote to quickly place things on the floor without fiddling
     
    Last edited: Jul 21, 2015
  8. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    7,851
    My mistake your right they do get called, its Update, OnGUI and OnRenderObject that behave differently when not in play mode.
     
    BaaWolf likes this.