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.