Hey there! I am a newbie to Unity and also to game development, but not to programming. I had a mobile shooter project going on and when I tried to manage a lot of NPC enemies, FPS rates was lower than I wanted. So I wanted to give ECS a shot so here I am.
I was instantiating my enemies in the EnemyManager singleton from my enemy prefab. And on the Update method, I was setting their NavMeshAgent destination to my player every once in a while. Now I can’t seem to get the hang of instantiation and using NavMeshAgent component of my enemy prefab using ECS. And it seems that there is no guidance in the internet about the subject.
How can I instantiate entities from my GameObject enemy prefab and store them so I can use them later? How can I access to the components of already created entities? I am not attaching any code because I messed it up a bit I guess.
Please request any further information that you need.
Sorry if there is a typo or a logic error in the question. I am too tired and I will edit after a big meal
Instantiation in hybrid is the same. MonoBehaviour.Instantiate(goPrefab) but you need a GameObjectEntity on the prefab, otherwise it will not be created in the ECS world. You can then either use the new convert workflow or create ComponentDataProxy for every component you’d need on the enemy.
The solution is to decouple enemies from NavMeshAgent. Not every enemy needs one every frame. This is where you save process time.
You can get MonoBehaviours inside a ComponentSystem with EntityManager.GetComponentObject(entity)
But instead of doing the same thing, try to query in a system like: NavMesh.CalculatePath(pathQuery.position, pathQuery.targetPosition, 1 << 0, path) when an enemy is looking for a path.
You can add the corner vectors from the results to a buffer which another system uses to move the enemy around.
I’ve got an ECS project with that approach that does upwards of 10k enemies. Moving is not the expensive part after all if you already got the path.
Where it gets really interesting is when enemies should not collide with another and steer away from each other, like the flocking algorithm which I never came around to implement.
Still, the ECS advanced Boid sample is something you can take a look at but it’s kind of overwhelming at first. The good thing is you could utilize it without thinking about it too much.
Take a look at the files. The WalkPathSystem has been converted to a job but the ComponentSystem version is still commented out at the bottom. This should give you some idea how this works.
The usage then is pretty simple as you only have to
PostUpdateCommands.AddComponent(entity, new FindPath()
{
position = position.Value,
targetPosition = targetComp.targetPosition
});
Thank you! I will try and utilize your ideas about NavMesh and pathfinding. But I still can’t instantiate.
When I try to add GameObjectEntity to my prefab it says “Enemy will be converted due to being in SubScene.” Since I couldn’t understand this error, I tried the code below without a GameObjectEntityComponent:
var prefabECS = GameObjectConversionUtility.ConvertGameObjectHierarchy(prefab, World.Active);
var man = World.Active.EntityManager;
var instance = man.Instantiate(prefabECS);
var position = new Vector3(0, 1.5f, 0);
man.SetComponentData(instance, new Translation { Value = position });
This seems as it creates the entity from what I see in the Entity Debugger but the entity doesn’t appear on the scene. I don’t think this is about MeshRenderer.
I believe I didn’t really understand ECS. What am I missing in this very simple logic?
EDIT: When I ignore the error and instantiate anyways, an entity is being created alongside with a GameObject. Also I can alter this entity’s state in ComponentSystem but there is no component attached to it, all components are attached to the GameObject. Is this what is meant to happen?