Hey guys, so I am wanting to add like a “modding API” to a “node” gameobject where the player can add additional functionality during runtime. Things like making the node move, giving the node custom data, add light / mesh components, etc etc.
I was thinking I would just use interfaces.
public interface IMovable
{
public float speed { get; set; }
public float3 direction { get; set; }
void Move() {}
void MoveToSpot() {}
}
public interface IAttackable { }
// etc
But interfaces are not serializable so I thought I would create a “generic” struct to hold whatever data the component might need.
public struct Component
{
public int ID;
public bool[] bools;
public int[] ints;
public float[] floats;
public string[] strings;
public int3[] int3s;
public float3[] float3s;
}
This way I can save it in a dictionary indexed by node ID or something. I would then assign them to each node on map load and let the node handle what to do with each component.
public class Node
{
public Component[] components;
}
I believe this would work but I’m curious if there is a better way? How would you all tackle this?
Also, I realize this is very similar to ECS but I would like to hear everyones opinion on not using it first. I tried learning it for a few days but tutorials were sparse and out of date and it just seems like its over my head. But if you all recommend it then I’ll try and take another whack at it.
Thanks for reply spiney199. That looks like what I am trying to do.
I thought of another problem though. What if I wanted to use these components in burst? I would have to keep them as structs with no lists so I would probably have to create a separate hashmap for each component type right?
public NativeParallelHashMap<int, MovableData> movableInterfaces;
public NativeParallelHashMap<int, AttackableData> attackableInterfaces;
public struct MovableData
{
public float speed;
public float3 direction;
}
I think how I should do it is just create separate lists for each component in the map indexed by node ID.
// NODES: a list of all nodes in the map indexed by ID
[NonSerialized] public NativeParallelHashMap<int, Node> nodes;
// COMPONENTS: we have to save maps of all our various component data for the node objects
[NonSerialized] public NativeParallelHashMap<int, Root.Data.Component.Position> position;
[NonSerialized] public NativeParallelHashMap<int, Root.Data.Component.Transform> transform;
[NonSerialized] public NativeParallelHashMap<int, Root.Data.Component.Shape> shape;
And then my node will only hold an ID and a tag list.
//
// Node: a struct that contains the essential data for a node. a node is the base for
// every type of "object" in a map.. a shape, item, player, etc etc
//
// whenever a node needs more data or functionality it gets tagged with a "component"
//
namespace Root.Data
{
[Serializable]
public struct Node
{
// ID: a unique identifier for each node
public int ID;
// TAGS: a bitmask for tagging a node with components
public int tags;
}
}
I could then check the nodes tags to see if it has a specific component, etc etc.
//
// Transform: if a node has the "transform" tag then this lets us know
// that the node needs a dedicated gameobject in the scene
//
namespace Root.Data.Component
{
[Serializable]
public struct Transform
{
// POSITION: this is separate from the "mapped" component which is a grid position
public float3 position;
// ROTATION: the transforms rotation
public float3 rotation;
// SCALE: the transforms scale
public float3 scale;
}
}