예제 #1
0
            public void Execute(Entity entity, int index, [ReadOnly] ref Target target, ref DeployToPosition deployToPosition, [ReadOnly] ref Translation translation, [ReadOnly] ref CombatMovement combatMovement, [ReadOnly] ref PursueTarget pursueTarget, [ReadOnly] ref MovementStats movementStats)
            {
                if (TranslationData.Exists(target.TargetEntity) &&
                    VelocityData.Exists(target.TargetEntity))
                {
                    var targetPosition = TranslationData[target.TargetEntity];
                    var targetVelocity = VelocityData[target.TargetEntity];
                    var distanceSq     = math.distancesq(targetPosition.Value, translation.Value);
                    if (distanceSq > combatMovement.OptimalRangeSq)
                    {
                        if (combatMovement.OptimalRangeSq != 0f)
                        {
                            var direction = targetPosition.Value - translation.Value;
                            direction = math.normalizesafe(direction);
                            var optimalPosition = translation.Value + (direction * math.sqrt(combatMovement.OptimalRangeSq));

                            NaNDebugger.IsNan(targetPosition.Value.x, "target nan");

                            deployToPosition.Position = optimalPosition;
                        }
                        else
                        {
                            // This version ignores the timestep and uses relative distance instead.
                            var t = math.length(math.sqrt(distanceSq)) * movementStats.TopSpeed;
                            var desiredPosition = targetPosition.Value + targetVelocity.Value * t * DeltaTime;

                            //var desiredPosition = targetPosition.Value + targetVelocity.Value * LookAheadTimeStep * DeltaTime;
                            deployToPosition.Position = desiredPosition;
                        }
                    }
                    else
                    {
                        deployToPosition.Position = translation.Value;
                    }
                }
            }
예제 #2
0
            public void Execute(Entity entity,
                                int jobIndex,
                                [ReadOnly] ref DeployToPosition deployment,
                                [ReadOnly] ref MovementStats stats,
                                [ReadOnly] ref Rotation rotation,
                                ref Translation translation,
                                ref Velocity velocity,
                                ref AngularVelocity angularVelocity)
            {
                NaNDebugger.IsNan(deployment.Position.x, $"[{jobIndex}, {entity.Index}] deployment.Position");
                NaNDebugger.IsNan(translation.Value.x, $"[{jobIndex}, {entity.Index}] translation");

                float3 toTarget = deployment.Position - translation.Value;
                float  distance = math.length(toTarget);

                if (deployment.ShouldStop && distance <= k_DistanceTolerance)
                {
                    velocity.Value           = float3.zero;
                    angularVelocity.Velocity = 0f;
                    translation.Value        = deployment.Position;

                    //CompletedDeployments.Enqueue(new CompletedDeployment() { Entity = entity, JobIndex = jobIndex });

                    return;                     // we're there, stop.
                }

                float speed = math.length(velocity.Value);

                float3 forward           = math.normalize(math.forward(rotation.Value));
                float3 velocityDirection = speed == 0f ? forward : math.normalize(velocity.Value);

                toTarget = toTarget / distance;                 // normalize
                float costheta = distance == 0f ? 1 : math.dot(toTarget, forward);



                // Rotation
                if (distance != 0f)
                {
                    float3 rotationAxis      = costheta == -1 || costheta == 1 ? math.up() : math.normalize(math.cross(forward, toTarget));
                    float  rotationDirection = math.saturate(math.sign(math.dot(rotationAxis, math.up())) + 1) * 2 - 1;                     // -1 or 1
                    float  rotationSpeed     = math.radians(stats.RotationSpeed) * rotationDirection;
                    rotationAxis = rotationAxis * rotationDirection;

                    if (costheta >= stats.ThrustTolerance)                      // have we turned enough to begin moving forward?
                    {
                        velocityDirection = forward;
                    }
                    else
                    {
                        rotationSpeed *= math.step(speed, /* < */ stats.MaxSpeedToTurn);                            // only turn if we've slowed down enough
                    }

                    if (costheta >= k_AngleTolerance)
                    {
                        float angleRadians = math.acos(costheta);
                        rotationSpeed = (float.IsNaN(angleRadians) ? 0f : angleRadians) * rotationDirection / DeltaTime;                            // take us directly there this frame.
                    }

                    velocityDirection = math.rotate(quaternion.AxisAngle(rotationAxis, rotationSpeed * DeltaTime), velocityDirection);

                    angularVelocity.Axis     = rotationAxis;
                    angularVelocity.Velocity = rotationSpeed;
                }

                NaNDebugger.IsNan(angularVelocity.Axis.x, $"[{jobIndex}, {entity.Index}] rotationAxis");
                NaNDebugger.IsNan(angularVelocity.Axis.x, $"[{jobIndex}, {entity.Index}] rotationSpeed");
                NaNDebugger.IsNan(velocityDirection.x, $"[{jobIndex}, {entity.Index}] velocityDirection");

                // Translation
                {
                    if (costheta >= stats.ThrustTolerance)                      // have we turned enough to begin moving forward?
                    {
                        if (deployment.ShouldStop)
                        {
                            // https://math.stackexchange.com/questions/233107/finding-minimum-distance-traveled-with-specified-deceleration-from-starting-spee
                            float speedInDirection = math.dot(toTarget, velocityDirection * speed);
                            float distanceTravelledIfDecelerating = (speedInDirection * speedInDirection) / (2 * stats.Deceleration);

                            if (distanceTravelledIfDecelerating >= distance)
                            {
                                speed = math.clamp(speed - 0.5f * stats.Deceleration * DeltaTime, 0f, stats.TopSpeed);                                   // t(v - at/2)
                            }
                            else
                            {
                                speed = math.clamp(speed + 0.5f * stats.Acceleration * DeltaTime, 0f, stats.TopSpeed);                                   // t(v - at/2)
                            }

                            speedInDirection = math.dot(toTarget, velocityDirection * speed);

                            float distanceThisFrame = distance - speedInDirection * DeltaTime;
                            if (distanceThisFrame < k_DistanceTolerance)
                            {
                                speed = distance / DeltaTime;                                 // take us right there this frame.
                            }
                        }
                        else
                        {
                            // don't stop, just keep accelerating.
                            speed = math.clamp(speed + 0.5f * stats.Acceleration * DeltaTime, 0f, stats.TopSpeed);                               // t(v - at/2)
                        }
                    }
                    else
                    {
                        // decelerate
                        speed = math.clamp(speed - 0.5f * stats.Deceleration * DeltaTime, 0f, stats.TopSpeed);                           // t(v - at/2)
                    }

                    velocity.Value = velocityDirection * speed;
                }

                NaNDebugger.IsNan(velocity.Value.x, $"[{jobIndex}, {entity.Index}] velocity");
            }