Search code examples
c#algorithmunity-game-engineoptimization

Optimizing GameObject unique ID assigner Unity


Recently I was working on the door system for my multiplayer game, and I had a problem with door ID (that specifies which door to interact with). I wanted to avoid assigning IDs manually, due to my game has a lot of doors, so I have found a solution - instead of unreliable FindObjectsOfType, I have build following scene looper:

void IterateThroughScene(Scene scene)
        {
            SortedList<string, NetworkedObject> sortedObjects = new SortedList<string, NetworkedObject>();
            
            foreach (GameObject sceneRootObject in scene.GetRootGameObjects())
            {
                foreach (NetworkedObject netObj in sceneRootObject.GetComponentsInChildren<NetworkedObject>())
                {
                    Vector3 position = netObj.transform.position;
                    string transformHash = position.x.ToString("0.00") + position.y.ToString("0.00") + position.z.ToString("0.00");
                    transformHash = Hashing.MD5(transformHash);
                    
                    sortedObjects.Add(transformHash, netObj);
                }
            }

            
            Dictionary<ushort, NetworkedObject> preparedObjects = new Dictionary<ushort, NetworkedObject>();
            ushort lastId = _ids[scene.name];
            
            foreach (var part in sortedObjects)
            {
                NetworkedObject preparedObject = part.Value;
                preparedObject.GetObjectData().id = lastId;
                preparedObjects[lastId] = preparedObject;
                lastId++;
            }

            _ids[scene.name] = lastId;
            _registeredObjects[scene.name] = preparedObjects;
        }

Here I list step-by-step what this method is doing:

  • SortedList is instantiated to hold objects
  • 2 foreach's are getting all objects in the scene
    • here script generates MD5 of position and adds it to SortedList
  • After that, Dictionary instance is created to hold final data
  • Next foreach is done, to loop through SortedList and assign NetworkedObject IDs in a reliable way.

This was doing a great job in small/medium scenes, but I started having serious problems with big scenes - I have a good PC & itaration takes 12 seconds, and my game's target are medium PCs.

So, Do you have any idea how can I optimize this algorithm?


Solution

  • As I do not know the internals of FindObjectsOfType it is hard to compare the method to your snippet. You did however mention that order matters, and as FindObjectsOfType is not guaranteed to return objects in any particular order, it would not work for your use case.

    To optimize the snippet you would need to prune your search in some way. As you are looking at all root gameObjects, you can mark each root object with the number of doors that it has as children, and keep a counter for each root. That way, once you reach the number needed sent from the children, it can stop searching that root object.

    However, as it seems you would just like to assign ordered ids to objects in a scene for referencing, I would advise to use an editor tool to handle the assignment. The code would be near identical but with the advantage of not needing to care about overhead during runtime as it is computed outside of the game. When implementing any editor tool that alters your scene, make sure to mark the scene as dirty to assure Unity will save the changes.