public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { NativeArray <Entity> entityArray = chunk.GetNativeArray(entityType); NativeArray <Translation> translArray = chunk.GetNativeArray(translType); NativeArray <Rotation> rotArray = chunk.GetNativeArray(rotType); NativeArray <FormationLocation> formLocArray = chunk.GetNativeArray(formLocType); NativeArray <FormationRotation> formRotArray = chunk.GetNativeArray(formRotType); NativeArray <PoliceUnitOfPoliceOfficer> unitArray = chunk.GetNativeArray(unitType); NativeArray <PoliceOfficerAtFormationLocation> atLocationArray = chunk.GetNativeArray(atLocationType); for (int i = 0; i < chunk.Count; i++) { Entity entity = entityArray[i]; Translation transl = translArray[i]; Rotation rot = rotArray[i]; FormationLocation formLoc = formLocArray[i]; FormationRotation formRot = formRotArray[i]; PoliceUnitOfPoliceOfficer policeUnit = unitArray[i]; PoliceOfficerAtFormationLocation officerRotPerTick = atLocationArray[i]; float finalAngleDiff = math.degrees(AngleBetweenQuaternions(rot.Value, formRot.Value)); if (math.distance(transl.Value, formLoc.Value) > moveTolerance) // if the officer was knocked away from their formation location { commandBuffer.RemoveComponent <PoliceOfficerAtFormationLocation>(chunkIndex, entity); //signify that the officer should move back into position } else if (finalAngleDiff > rotTolerance && finalAngleDiff < 360 - rotTolerance) // rotate towards the correct rotation (Step 2) { quaternion newRot = math.mul(rot.Value, officerRotPerTick.RotationPerTick); //math.mul(math.mul(officerRotPerTick.RotationPerTick,rot.Value),math.inverse(officerRotPerTick.RotationPerTick)); rotArray[i] = new Rotation { Value = newRot }; } else // the officer is now in the proper formation { commandBuffer.RemoveComponent <PoliceOfficerAtFormationLocation>(chunkIndex, entity); // we no longer need to label the officer as being in formation commandBuffer.RemoveComponent <PoliceOfficerOutOfFormation>(chunkIndex, entity); // signify that the officer is no longer out of formation commandBuffer.AppendToBuffer <OfficerInFormation>(chunkIndex, policeUnit.Value, new OfficerInFormation { }); // signify to the police unit that one more officer is in formation } } }
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { NativeArray <Entity> entityArray = chunk.GetNativeArray(entityType); NativeArray <Translation> translArray = chunk.GetNativeArray(translType); NativeArray <Rotation> rotArray = chunk.GetNativeArray(rotType); NativeArray <FormationLocation> formLocArray = chunk.GetNativeArray(formLocType); NativeArray <FormationRotation> formRotArray = chunk.GetNativeArray(formRotType); NativeArray <PoliceOfficerMaxSpeed> speedArray = chunk.GetNativeArray(speedType); NativeArray <PoliceOfficerRotationSpeed> rotSpeedArray = chunk.GetNativeArray(rotSpeedType); for (int i = 0; i < chunk.Count; i++) { Entity entity = entityArray[i]; Translation transl = translArray[i]; Rotation rot = rotArray[i]; FormationLocation formLoc = formLocArray[i]; FormationRotation formRot = formRotArray[i]; PoliceOfficerMaxSpeed speed = speedArray[i]; PoliceOfficerRotationSpeed rotSpeed = rotSpeedArray[i]; float3 direction = math.normalize((formLoc.Value - transl.Value)); quaternion turn = quaternion.LookRotationSafe(direction, new float3(0f, 1f, 0f)); float angleToDestination = math.degrees(AngleBetweenQuaternions(rot.Value, turn)); //Debug.Log("Angle: " + angle); if (math.distance(transl.Value, formLoc.Value) > moveTolerance) // move towards the correct location (Step 1) { float3 result = (formLoc.Value - transl.Value) * deltaTime; // the direction of movement if (math.distance(result, float3.zero) > speed.Value) // if the movement is faster than the max speed, cull the movement to match the max speed { result = math.normalize(result) * speed.Value; } float3 newTransl = result + transl.Value; translArray[i] = new Translation { Value = newTransl }; rotArray[i] = new Rotation { Value = RotateTowards(rot.Value, transl.Value, formLoc.Value, rotSpeed.Value * deltaTime) }; } else // the officer is now in the correct position //find how much the officer should rotate per tick { float angle = AngleBetweenQuaternions(rot.Value, formRot.Value); //Debug.Log("Angle: " + math.degrees(angle)); float percent; if (angle == 0 || angle != angle) { percent = 1; } else { percent = math.radians(rotSpeed.Value * rotSpeedDegreeValue) / angle; } float numberOfTicks = math.ceil(1 / percent); percent = 1 / numberOfTicks; //Debug.Log("Percent: " + percent); if (percent > 1f) { percent = 1f; } //Debug.Log("Number of ticks: " + (numberOfTicks)); quaternion rotPerTick = math.slerp(rot.Value, formRot.Value, percent); quaternion inverse = math.inverse(rot.Value); // find out how much to rotate by to get back to forward from the current rotation rotPerTick = math.mul(rotPerTick, inverse); // get the relative rotation per tick commandBuffer.AddComponent <PoliceOfficerAtFormationLocation>(chunkIndex, entity, new PoliceOfficerAtFormationLocation { RotationPerTick = rotPerTick }); // signify that the officer is at the correct position } } }