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

Keeping track and accessing Gameobjects in a game

Discussion in 'Scripting' started by Talthilas, Jan 23, 2017.

  1. Talthilas

    Talthilas

    Joined:
    Apr 1, 2014
    Posts:
    44
    Hi,

    I'm interested in how some of you more experienced game devs are organizing your scenes to track gameobjects. I'm making a 4x (Civ style) game with many, many gameobjects to keep track of.

    A bit of background on how i'm doing things at the moment for the sake of discussion. Each of my objects in the scene are derived from an abstract monobehaviour class which I have called "GameEntity". Each GameEntity has a unique integer ID. All of these GameEntities are added to a global Dictionary<ID, GameEntity> which I call the EntityTable. When it comes to a GameEntity (lets call it 'Transport') that can be a container for other GameEntities (lets call them 'Troopers') as well, there are a few ways I can think of to access my GameEntities with persistence and performance in mind.

    Method 1 - Store a list of trooper IDs on the Transport GameEntity
    This is how I have current set up my code. I find it intuitive, easy to understand, and save/load is simple. When I want to access a GameEnity, I just look it up in the global EntityTable by its unique ID number. When I save the Transport entity I just serialize the list of ids which represent the troopers currently stored in the transport. When I load the game I just deserialize the list. Simple, however I worry about performance with this method.


    Method 2 - Store a list/array of trooper references on the Transport GameEnity
    This is essentially the same as method one, except the list becomes a list of Trooper GameEntity references (i.e. List<GameEntity> troopers = {EntityTable[0], EntityTable[1] etc.} <--pesudo code ;-P I have done some testing with loops of millions of iterations and found that this way is up to 3 times quicker than method 1 in terms of accessing the trooper object directly from the list of references rather than looking up via the entityTable. The difficulty with this method is when it comes to persistence. Saving is easy enough, I just get the uniqueID for each trooper and serialize the ID list like i did in method 1. Loading is harder though. Basically you have to make sure you have already deserialized an entity and placed it in the entity table before you can add a reference to it in the Transport script. So you either have to be very careful about the order in which you deserialize things (objects that cannot contain other objects (Trooper) should be derserialized first, then the container objects (Transport) etc), or you can make two passes at all the entities when you deserialize. One pass to fill the entity table without building the internal reference list in all the 'container' (e.g Transport) entities, then another pass to build the internal reference lists.

    So there's my conundrum. What do you guys think is the best method? Is there an even better way than what I'm thinking above?

    Would be great to hear your thoughts.

    Aaron.
     
    limserhane likes this.
  2. andymads

    andymads

    Joined:
    Jun 16, 2011
    Posts:
    1,614
    Are you trying to optimise something which doesn't need optimising? If method 1 is simple and currently working then why change it. Even though you've determined it's slower than another method does that make any real difference overall?
     
  3. Talthilas

    Talthilas

    Joined:
    Apr 1, 2014
    Posts:
    44
    The problem is that since this is such a fundamental part of the games architecture, I really need to knock this on the head early in the dev process. The game wont truly be taxed hard until much later in development when I have hundreds of units on the screen with multiple players involved making complex AI decisions etc. That's when profiling will show if this is a problem or not. I have already performed tests and found that method 2 was quicker, however whether method 1 would be suitable cannot be determined into much later down the track. Getting to that stage to then find that I may have to go back and completely change a fundamental part of its architecture would be very, very painful.

    I get what your saying, and I do very much subscribe to the 'if it ain't broke, don't fix it' mentality. I would love to leave the current system in place because already it would be a pain to change, but for this type of system, I think its important that I get some feedback from the community before I go too far down one rabbit hole. Perhaps there is a best practice for this sort of thing that would answer my question straight off the bat.