Maintaine spawned objects

Hi there,

I am currently working on an RTS game and have trouble with my class hierarchy. I have a base class NetworkEntity (from my custom networking solution) that looks like that.

public abstract class NetworkEntity : MonoBehaviour
{
    public abstract class DeltaData
    {
        public Vector3 position;
    }
    
    public short NetworkId { get; set; }
    
    public abstract DeltaData GetDeltaData();
    
    public abstract byte[] DeltaCompress(DeltaData newState, DeltaData oldState);
   
    public abstract DeltaData DeltaUncompress(byte[] data);
}

Each unit (basically each gameobject that is synced between client and server) in my game has to derive from that class because they need a unique NetowkId and the abstract method implementation. So I made a base class for all Units (this is just the structure, not the actual code):

public abstract class Unit : NetworkEntity
{
    public abstract class DeltaDataArcher : DeltaData
    {
        public short health;
    }
    
    public short Health { get; set; }
    public short MovementSpeed { get; set; }
}

From this, I want to derive all my other units e.g. Archer, Swordsman

public class Archer : Unit
{
        public class DeltaDataArcher : DeltaDataUnit
        {
            // Archer specific Synced Vars
        }
  
        public override DeltaData GetDeltaData()
        {
            return new DeltaDataArcher();
        }

        public override byte[] DeltaCompress(DeltaData newState, DeltaData oldState)
        {
            return new byte[0];
        }

        public override DeltaData DeltaUncompress(byte[] data)
        {
            return new DeltaDataArcher();
        }
    }
   
    public class Swordman : Unit
    {
       
        public class DeltaDataSwordman : DeltaDataUnit
        {
            // Sowrdman specific Synced Vars
        }
       
        public override DeltaData GetDeltaData()
        {
            return new DeltaDataSwordman();
        }

        public override byte[] DeltaCompress(DeltaData newState, DeltaData oldState)
        {
            return new byte[0];
        }

        public override DeltaData DeltaUncompress(byte[] data)
        {
            return new DeltaDataSwordman();
        }
 }

I have to store each Unit in a collection on the server and on the client. Retrieving a specific Unit is pretty hard that way. Although I can iterate over a specific subtype using LINQ (which at least avoids casting) this would mean I have to iterate over all Unit subtypes (maybe hundreds) to find the Unit I am looking for. Since I am using a Dictionary to store my Units retrieving them with an ID is not the problem but rather casting to the correct subclass. Which leads to the same problem → try to cast to hundreds of subtypes? I don’t know a solution for this. This is a sample of accessing and storing Units.

    public class Test : MonoBehaviour
    {
        private Dictionary<short, NetworkEntity> _entities;

        void Start()
        {
            _entities = new Dictionary<short, NetworkEntity>();

            var a1 = gameObject.AddComponent<Archer>();
            a1.NetworkId = 1;
            var a2 = gameObject.AddComponent<Archer>();
            a2.NetworkId = 2;
            var s1 = gameObject.AddComponent<Swordman>();
            s1.NetworkId = 3;
            _entities.Add(1,a1);
            _entities.Add(2,a2);
            _entities.Add(3,s1);
        }

        private void Update()
        {
            // iterate over archers
            foreach(var archer in _entities.OfType<Archer>())
            {
                // Do Stuff
            }
           
            // access specific unit
            var unit = _entities[1];

            if (unit is Archer)
            {
                // Do Stuff
            }else if (unit is Swordman)
            {
                // Do Stuff
            }    
           
        }
    }

There has to be a more generic solution to this. Any help is very appreciated.

Make an abstract or virtual .DoUpdate() method (e.g. in Unit class). Then call it on all entitity types as long as they’re Units.

Alternatively, make a separate lookups if you really need a class specific functionality.

#1 Is not possible since I have to pass the correct message from the server to the correspondig unit.

#2 Well thatsthe same issue as I have now. If I have 100 different units I need to check 100 collections.

#3
Or you could make a .DoUpdate() method for all NetworkEntities and pass each entity their own data.
It’s up to the entities what would they do with the data afterwards.

In general its good to separate networking layer from the game logic layer, so this is probably best choice.

#4 Abstract messaging layer, same way as Unet did it.