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

Editor Script Help

Discussion in 'Scripting' started by cranky, Jul 21, 2014.

  1. cranky

    cranky

    Joined:
    Jun 11, 2014
    Posts:
    180
    Editor Scripting is something totally new to me, so a little help would be appreciated!

    I am implementing my own networking for a game. In order to sync GameObjects, I store a unique ID number for each GameObject. This ID is equal on each client for the given GameObject. The idea of this is so each client can relate information to its associated GameObject. I can create new objects during runtime and assign them a unique ID without issue.

    The problem: I need a way to assign a unique ID to GameObjects (only ones containing a certain component) in the editor. The only solution I know without using an editor script is for the designer to assign each GameObject a unique ID manually. This can lead to issues like forgetting to assign a unique ID. I'd like for this to be transparent for the designer. I think writing an Editor Script is the only way to accomplish this.

    I don't need a fully functional script to drag and drop in -- I am an experienced programmer, but somewhat new to Unity. I just need an idea of how this can be done using an Editor script.

    Thank you!
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,738
    I don't think you need an editor script. You could use a static counter and Reset() which gets executed every time you add a component in the Editor.
    Code (csharp):
    1.  
    2. private static int currentObjectID = 0;
    3. public int myID = -1;
    4. void Reset() {
    5. myID = currentObjectID;
    6. currentObjectID++;
    7. }
    8.  
    Put that in your script, then create several objects, and watch the number go up with each new one you make.

    (For any of these components that already exist, you can right-click on the component and Reset them manually. Note that this will probably re-initialize most of your variables.)
     
  3. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    Code (CSharp):
    1. public class ObjectID : MonoBehaviour
    2. {
    3.     [SerializeField]
    4.     private byte[] id = new byte[0];
    5.  
    6.     public Guid ID
    7.     {
    8.         get { return new Guid(id); }
    9.         set { id = value.ToByteArray(); }
    10.     }
    11.  
    12.     private void OnEnable()
    13.     {
    14.         if (id == null || id.Length != 16)
    15.         {
    16.             ID = Guid.NewGuid();
    17.         }
    18.     }
    19. }
    Unique ID created in the editor when you add this script to an object.
     
  4. cranky

    cranky

    Joined:
    Jun 11, 2014
    Posts:
    180
    This is great, but I would need the Guid to be created in the editor, not during runtime, because the IDs need to be the same on their respective GameObjects for each client. If I'm understanding this correctly, OnEnable is only called during runtime and not in the editor, correct? Again, I am new to Unity, so please pardon my mistakes.

    My code for generating IDs during runtime is very similar, so I was able to rework it and get it mostly working correctly! The only problem is that currentObjectID gets reset to 0 when restarting Unity. Is there anyway to save an editor only variable and when the editor loads the scene, it loads that variable into the current ID?

    Thanks a lot for the replies!
     
  5. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    Nope, it's also called in the editor. OnEnable is called as soon as an object is loaded, editor or not.
     
  6. cranky

    cranky

    Joined:
    Jun 11, 2014
    Posts:
    180
    Hmm weird, I can't get it to call it :\. This is the code I am using:

    Code (CSharp):
    1. public class NetworkObject : MonoBehaviour
    2. {
    3.  
    4.     ...
    5.  
    6. #if UNITY_EDITOR
    7.     void Reset()
    8.     {
    9.         NetworkObject.AssignId(this, GetNextId());
    10.         Debug.Log("Test");
    11.     }
    12. #endif
    13. }
    If I change the name to Reset, it works when I create new objects or manually reset them. While using OnEnable, it doesn't call it if I manually disable/enable it in the editor while the game is not running, but it does call it if I disable/enable it in the editor while he game IS running.

    One potential workaround is to use Reset() and have it generate a Guid. Then I won't have to worry about the editor remembering where the last ID left off. However, the main purpose of doing this is for identifying GameObjects over the internet. So for every rigidbody sync packet, I'd have to send a 128bit Guid. I could have the server send an initial mapping (this Guid = 0, this Guid = 1, etc), but I feel there is a much cleaner and elegant solution in assigning the network ID on object creation in the Unity Editor.
     
  7. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    Hmm... Strange. I was sure we put it on OnEnable. Guess I was wrong, but Reset can work too.

    Also, if it's just for identification, doesn't Unity already have a system in place to synch GameObject?
     
  8. mhtraylor

    mhtraylor

    Joined:
    Jan 13, 2013
    Posts:
    33
    GetInstanceID() on prefabs and scene objects returns an unique id that seems to be persistent.
     
  9. cranky

    cranky

    Joined:
    Jun 11, 2014
    Posts:
    180
    Probably, but I am implementing my own networking with the Lidgren library. I have absolutely zero experience with Unity's networking, so I am not sure :\.

    I just found the attribute [ExecuteInEditMode]! This is probably how you got OnEnable to work. I think I should be able to figure it out from here. Thanks a ton for the help!
     
  10. cranky

    cranky

    Joined:
    Jun 11, 2014
    Posts:
    180
    For those who are curious, here was my eventual solution:

    EDIT: Nope, didn't work.

    Code (CSharp):
    1. [UnityEditor.CustomEditor(typeof(NetworkObject))]
    2. public class NetworkObjectEditor : UnityEditor.Editor
    3. {
    4.     public static int nextId = 0;
    5.  
    6.     void OnEnable()
    7.     {
    8.         ReassignIDs();
    9.     }
    10.  
    11.     void OnDestroy()
    12.     {
    13.         ReassignIDs();
    14.     }
    15.  
    16.     private void ReassignIDs()
    17.     {
    18.         nextId = 0;
    19.         NetworkObject[] foundObjects;
    20.         foundObjects = Object.FindObjectsOfType<NetworkObject>();
    21.         for (int i = 0; i < foundObjects.Length; i++)
    22.             foundObjects[i].id = nextId++;
    23.     }
    24. }
     
    Last edited: Jul 22, 2014
  11. cranky

    cranky

    Joined:
    Jun 11, 2014
    Posts:
    180
    - removed -

    EDIT: EditorUtility.SetDirty()..... I solved my issue!
     
    Last edited: Jul 22, 2014