How to spawn units using DOTS?

2k views Asked by At

I am following this talk https://www.youtube.com/watch?v=BNMrevfB6Q0 and try to understand how to spawn units as I click my mouse (for testing purposes).

For this in general, I created a UnitBase etc. which implements IConvertGameObjectToEntity::Convert to make sure all units can be converted to a Entity objects and looks like this:

namespace Units
{
    public abstract class UnitBase : MonoBehaviour, IConvertGameObjectToEntity
    {
        public float health;

        public bool selected;

        public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
        {
            dstManager.AddComponentData(entity, new Translation {Value = transform.position});
            dstManager.AddComponentData(entity, new Rotation {Value = transform.rotation});
            dstManager.AddComponentData(entity, new Selected {Value = selected});
            dstManager.AddComponentData(entity, new Health {Value = health});
        }
    }

    public abstract class MobileUnitBase : UnitBase
    {
        public float speed;

        public new void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
        {
            base.Convert(entity, dstManager, conversionSystem);
            dstManager.AddComponentData(entity, new Speed {Value = speed});
        }
    }
}

These are the main components:

namespace ECS.Components
{
    public class Health : IComponentData
    {
        public float Value;
    }

    public class Speed : IComponentData
    {
        public float Value;
    }

    public class Selected : IComponentData
    {
        public bool Value;
    }
}

Now, in my Test script I have this:

public class Test : MonoBehaviour
{
    public GameObject unitPrefab;

    private EntityManager _entityManager;
    private Entity _unitEntityPrefab;

    // Start is called before the first frame update
    void Start()
    {
        _entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
        _unitEntityPrefab  = GameObjectConversionUtility.ConvertGameObjectHierarchy(unitPrefab, World.Active);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            SpawnUnit(15, 15);
        }
    }

    private void SpawnUnit(float x, float z)
    {
        Debug.Log($"Spawning unit at  x:{x} y:{z}");
        var unitEntity = this._entityManager.Instantiate(this._unitEntityPrefab);
        _entityManager.SetComponentData(unitEntity, new Translation {Value = new Vector3(x, 1, z)});
        _entityManager.SetComponentData(unitEntity, new Rotation {Value = Quaternion.Euler(0, 0, 0)});
        _entityManager.SetComponentData(unitEntity, new Health {Value = 100f});
        _entityManager.SetComponentData(unitEntity, new Selected {Value = false});
    }
}

Where unitPrefab is just a simple GameObject that has a Capsule on it and a, basically empty, script which is empty for now:

public class UnitScript : UnitBase
{
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
}

The thing is, as I click, the entities get created but the unit is not rendered.

Obviously I am missing something but I don't see what it is.

Any help would be much appreciated!

0

There are 0 answers