The goal I want is as follows.
- Implement the ‘Attack system’ using IJobEntityBatch.
- Create a projectile prefab when inputting the attack.
- Bring the projectile’s ‘Projectile’ component(IComponentData).
However, there was a problem with the part where the Projectile component data was imported.
The errors are as follows.
ArgumentException: All entities created using EntityCommandBuffer.CreateEntity must be realized via playback(). One of the entities is still deferred (Index: -1).
- Importing EntityManager into IJobEntityBatch also results in errors.
By inference, it seems that I lack knowledge of EntityCommandBuffer.
I ask for your help.
This is my Code.
public partial class AttackSystem : SystemBase
{
private EntityQuery _attackQuery;
private EndSimulationEntityCommandBufferSystem _endSimulationEntityCommandBufferSystem;
private partial struct AttackJob : IJobEntityBatch
{
public float DeltaTime;
public EntityCommandBuffer Ecb;
[ReadOnly]
public EntityTypeHandle EntityType;
public ComponentTypeHandle<Attacker> AttackerType;
[ReadOnly]
public ComponentTypeHandle<Equipment> EquipmentType;
public ComponentDataFromEntity<Projectile> ProjectileFromEntity;
public ComponentDataFromEntity<LocalToWorld> LocalToWorldFromEntity;
[BurstCompile]
public void Execute(ArchetypeChunk batchInChunk, int batchIndex)
{
var attackers = batchInChunk.GetNativeArray(AttackerType);
var equipments = batchInChunk.GetNativeArray(EquipmentType);
var entities = batchInChunk.GetNativeArray(EntityType);
for (int i = 0; i < batchInChunk.Count; i++)
{
var entity = entities[i];
var attacker = attackers[i];
var equipment = equipments[i];
var weapon = equipment.EquippedWeapon;
if (attacker.AttackRequested && attacker.AttackDelayTimer <= 0)
{
//var handLocalToWorld = EntityManager.GetComponentData<LocalToWorld>(equipment.WeaponSpawnPoint);
LocalToWorldFromEntity.TryGetComponent(equipment.WeaponSpawnPoint, out var handLocalToWorld);
if (attacker.CurrentClip > 0 || !attacker.IsReloading)
{
UnityEngine.Debug.Log($"Attacker : {entity}");
var projectileEntity = Ecb.Instantiate(weapon.ProjectileEntity);
{
// Error
ProjectileFromEntity.TryGetComponent(projectileEntity, out var projectile);
Ecb.SetComponent(projectileEntity, projectile);
Ecb.SetComponent(projectileEntity, new Translation { Value = handLocalToWorld.Position });
}
attacker.CurrentClip--;
attacker.AttackDelayTimer = weapon.AttackDelay;
if (attacker.CurrentClip == 0)
{
attacker.ReloadTimer = weapon.ReloadTime;
attacker.IsReloading = true;
}
}
}
if (attacker.IsReloading && attacker.ReloadTimer <= 0)
{
attacker.CurrentClip = weapon.ClipSize;
attacker.IsReloading = false;
}
attacker.ReloadTimer -= DeltaTime;
attacker.AttackDelayTimer -= DeltaTime;
attackers[i] = attacker;
}
}
}
protected override void OnCreate()
{
_endSimulationEntityCommandBufferSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
var description = new EntityQueryDesc
{
All = new ComponentType[]
{
ComponentType.ReadWrite<Attacker>(),
ComponentType.ReadOnly<Equipment>(),
},
};
_attackQuery = GetEntityQuery(description);
}
protected override void OnUpdate()
{
float deltaTime = Time.DeltaTime;
var ecb = _endSimulationEntityCommandBufferSystem.CreateCommandBuffer();
Dependency = new AttackJob
{
EntityType = GetEntityTypeHandle(),
DeltaTime = deltaTime,
Ecb = ecb,
AttackerType = GetComponentTypeHandle<Attacker>(false),
EquipmentType = GetComponentTypeHandle<Equipment>(true),
ProjectileFromEntity = GetComponentDataFromEntity<Projectile>(),
LocalToWorldFromEntity = GetComponentDataFromEntity<LocalToWorld>()
}.Schedule(_attackQuery, Dependency);
_endSimulationEntityCommandBufferSystem.AddJobHandleForProducer(Dependency);
}