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
                }
            }
        }