Hi,
I am trying to make the Animator and CharacterController work with ECS but unfortunately I was not able to do so. I am following the Prefab workflow which means my CharacterController component and Animator component are in the prefab that I am instantiating with a spawning system. I tried to use the AddComponentObject() to add the components to the entity but this does not work. Also PostUpdateCommands does not have a SetComponentObject method and since we are have to use ForEach I am stuck.
What should I do?
[RequiresEntityConversion]
public class PlayerProxy : MonoBehaviour, IDeclareReferencedPrefabs, IConvertGameObjectToEntity
{
public GameObject Prefab;
public void DeclareReferencedPrefabs(List<GameObject> gameObjects)
{
gameObjects.Add(Prefab);
}
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
var spawnerData = new PlayerSpawner
{
Prefab = conversionSystem.GetPrimaryEntity(Prefab)
};
dstManager.AddComponentData(entity, spawnerData);
dstManager.AddComponentObject(entity, Prefab.GetComponent<CharacterController>());
}
}
public class PlayerSpawnerSystem : ComponentSystem
{
protected override void OnUpdate()
{
Entities.ForEach((Entity entity, ref PlayerSpawner spawner) => {
Entity instance = PostUpdateCommands.Instantiate(spawner.Prefab);
// ??? :(
//CharacterController characterController = World.Active.EntityManager.GetComponentObject<CharacterController>(entity);
//PostUpdateCommands.SetComponent(instance, characterController);
PostUpdateCommands.DestroyEntity(entity);
});
}
}
Thank you
Here’s how I was able to tie hybrid components to entities:
-
Add a GameObject to the scene with a SpawnableAnchoredPrefabs script and a ConvertToEntity in ConvertAndInjectGameObject mode. Add the prefab with the CharacterController to the array in SpawnableAnchoredPrefabs.
-
Add a GameObject to the scene with a CreateAnchoredPrefabProxy and a ConvertToEntity in ConvertAndDestroy mode. Make sure PrefabIndex is 0 and CopyFromTransfrom is set to True.
-
Enter play mode. You should have an entity with SpawnableAnchoredPrefabs and an entity with a CharacterController.
Here are my scripts:
My Implementation
[DisallowMultipleComponent, RequiresEntityConversion]
public class SpawnableAnchoredPrefabs : MonoBehaviour
{
public GameObject[] Prefabs;
}
[DisallowMultipleComponent, RequiresEntityConversion]
public class CreateAnchoredPrefabProxy : MonoBehaviour, IConvertGameObjectToEntity
{
public int PrefabIndex = 0;
public bool CopyFromTransform = false;
public bool CopyToTransform = false;
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
dstManager.AddComponentData(entity, new CreateAnchoredPrefabIndex { Value = PrefabIndex });
if (CopyFromTransform)
dstManager.AddComponentData<CopyTransformFromGameObject>(entity, default);
if (CopyToTransform)
dstManager.AddComponentData<CopyTransformToGameObject>(entity, default);
}
}
public struct CreateAnchoredPrefabIndex : IComponentData
{
public int Value;
}
[UpdateInGroup(typeof(InitializationSystemGroup))]
public class AnchorPairingSystem : ComponentSystem
{
private NativeList<Entity> anchorEntities;
private NativeList<CreateAnchoredPrefabIndex> createAnchoredPrefabIndicies;
protected override void OnCreate()
{
anchorEntities = new NativeList<Entity>(Allocator.Persistent);
createAnchoredPrefabIndicies = new NativeList<CreateAnchoredPrefabIndex>(Allocator.Persistent);
RequireForUpdate(GetEntityQuery(ComponentType.ReadWrite<SpawnableAnchoredPrefabs>()));
RequireForUpdate(GetEntityQuery(ComponentType.ReadWrite<CreateAnchoredPrefabIndex>()));
}
protected override void OnDestroy()
{
anchorEntities.Dispose();
createAnchoredPrefabIndicies.Dispose();
}
protected override void OnUpdate()
{
SpawnableAnchoredPrefabs singleton = null;
Entities.ForEach((SpawnableAnchoredPrefabs spawnableAnchoredPrefabs) =>
{
singleton = spawnableAnchoredPrefabs;
});
Entities.ForEach((Entity entity, ref CreateAnchoredPrefabIndex createAnchoredPrefab) =>
{
anchorEntities.Add(entity);
createAnchoredPrefabIndicies.Add(createAnchoredPrefab);
PostUpdateCommands.RemoveComponent<CreateAnchoredPrefabIndex>(entity);
});
for (int i = 0; i < anchorEntities.Length; i++)
{
GameObject prefab = singleton.Prefabs[createAnchoredPrefabIndicies[i].Value];
Component[] components = Object.Instantiate(prefab).GetComponents<Component>();
foreach (var component in components)
{
EntityManager.AddComponentObject(anchorEntities[i], component);
}
}
anchorEntities.Clear();
createAnchoredPrefabIndicies.Clear();
}
}
1 Like