Editor Script Help

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!

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.

private static int currentObjectID = 0;
public int myID = -1;
void Reset() {
myID = currentObjectID;
currentObjectID++;
}

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.)

public class ObjectID : MonoBehaviour
{
    [SerializeField]
    private byte[] id = new byte[0];

    public Guid ID
    {
        get { return new Guid(id); }
        set { id = value.ToByteArray(); }
    }

    private void OnEnable()
    {
        if (id == null || id.Length != 16)
        {
            ID = Guid.NewGuid();
        }
    }
}

Unique ID created in the editor when you add this script to an object.

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!

Nope, it’s also called in the editor. OnEnable is called as soon as an object is loaded, editor or not.

Hmm weird, I can’t get it to call it :. This is the code I am using:

public class NetworkObject : MonoBehaviour
{

    ...

#if UNITY_EDITOR
    void Reset()
    {
        NetworkObject.AssignId(this, GetNextId());
        Debug.Log("Test");
    }
#endif
}

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.

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?

GetInstanceID() on prefabs and scene objects returns an unique id that seems to be persistent.

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!

For those who are curious, here was my eventual solution:

EDIT: Nope, didn’t work.

[UnityEditor.CustomEditor(typeof(NetworkObject))]
public class NetworkObjectEditor : UnityEditor.Editor
{
    public static int nextId = 0;

    void OnEnable()
    {
        ReassignIDs();
    }

    void OnDestroy()
    {
        ReassignIDs();
    }

    private void ReassignIDs()
    {
        nextId = 0;
        NetworkObject[] foundObjects;
        foundObjects = Object.FindObjectsOfType<NetworkObject>();
        for (int i = 0; i < foundObjects.Length; i++)
            foundObjects[i].id = nextId++;
    }
}
  • removed -

EDIT: EditorUtility.SetDirty()… I solved my issue!