Пример #1
0
    public void SetFollowWaypoints(List <DriveWaypoint> waypoints, bool loop, WaypointsPathType pathType)
    {
        InitPos = transform.position;
        InitRot = transform.rotation;

        WaypointLoop = loop;
        PathType     = pathType;

        // Process waypoints according to the selected waypoint path
        switch (PathType)
        {
        case WaypointsPathType.Linear:
            break;

        case WaypointsPathType.BezierSpline:
            // Disable BezierSpline if timestamps are set
            if (waypoints[0].TimeStamp >= 0.0f)
            {
                Debug.LogError("Bezier Spline path is not supported if the timestamps are set in the waypoints.");
                PathType = WaypointsPathType.Linear;
                break;
            }

            // Add the initial position for Bezier Spline calculations
            var initWaypoint = ((IWaypoint)waypoints[0]).Clone();
            initWaypoint.Position = InitPos;
            waypoints.Insert(0, (DriveWaypoint)initWaypoint);
            var bezier = new BezierSpline <DriveWaypoint>(waypoints.ToArray(), 0.01f);
            waypoints = bezier.GetBezierWaypoints();

            // Remove first waypoint as it will be added by another function
            waypoints.RemoveAt(0);
            break;

        default:
            throw new ArgumentOutOfRangeException(nameof(PathType), PathType, null);
        }

        LaneData            = waypoints.Select(wp => wp.Position).ToList();
        LaneSpeed           = waypoints.Select(wp => wp.Speed).ToList();
        LaneAcceleration    = waypoints.Select(wp => wp.Acceleration).ToList();
        LaneAngle           = waypoints.Select(wp => Quaternion.Euler(wp.Angle)).ToList();
        LaneIdle            = waypoints.Select(wp => wp.Idle).ToList();
        LaneDeactivate      = waypoints.Select(wp => wp.Deactivate).ToList();
        LaneTriggerDistance = waypoints.Select(wp => wp.TriggerDistance).ToList();
        LaneTime            = waypoints.Select(wp => wp.TimeStamp).ToList();
        LaneTriggers        = waypoints.Select(wp => wp.Trigger).ToList();

        InitNPC();
        AddPoseToFirstWaypoint();

        // Check if the timestamps should be replaced by calculations
        if (LaneTime[1] < 0.0f)
        {
            Debug.LogWarning("Waypoint timestamps absent or invalid, calculating timestamps based on speed and acceleration.");

            // Calculate acceleration data only if there are no timestamps
            for (int i = 0; i < LaneData.Count - 1; i++)
            {
                var   initialPosition  = LaneData[i];
                var   destination      = LaneData[i + 1];
                var   initialSpeed     = LaneSpeed[i];
                var   destinationSpeed = LaneSpeed[i + 1];
                var   distance         = Vector3.Distance(initialPosition, destination);
                float duration;
                if (LaneAcceleration[i + 1] > 0)
                {
                    // If max speed is lower than the initial speed convert acceleration to deceleration
                    if (destinationSpeed < initialSpeed)
                    {
                        LaneAcceleration[i + 1] *= -1;
                    }

                    if (!UniformlyAcceleratedMotion.CalculateDuration(LaneAcceleration[i + 1], initialSpeed,
                                                                      distance, ref destinationSpeed, out var accelerationDuration, out var accelerationDistance))
                    {
                        // Max speed will not be reached with current acceleration
                        AccelerationDestination.Add(destination);
                        LaneSpeed[i + 1] = destinationSpeed;
                        duration         = accelerationDuration;
                        AccelerationDuration.Add(accelerationDuration);
                    }
                    else
                    {
                        // Calculate mixed duration of accelerated and linear movements
                        var accelerationDestination = initialPosition +
                                                      (destination - initialPosition).normalized * accelerationDistance;
                        AccelerationDestination.Add(accelerationDestination);
                        var linearDistance = distance - accelerationDistance;
                        AccelerationDuration.Add(accelerationDuration);
                        duration = accelerationDuration + linearDistance / destinationSpeed;
                    }
                }
                else
                {
                    // There is no acceleration - apply max speed for uniform linear movement
                    AccelerationDuration.Add(0.0f);
                    AccelerationDestination.Add(initialPosition);
                    duration = distance / destinationSpeed;
                }

                // Set waypoint time base on speed.
                LaneTime[i + 1] = LaneTime[i] + duration;
            }
    public void SetFollowWaypoints(List <WalkWaypoint> waypoints, bool loop, WaypointsPathType pathType)
    {
        InitPos = transform.position;
        InitRot = transform.rotation;

        WaypointLoop = loop;
        PathType     = pathType;

        // Process waypoints according to the selected waypoint path
        switch (PathType)
        {
        case WaypointsPathType.Linear:
            break;

        case WaypointsPathType.BezierSpline:
            // Add the initial position for Bezier Spline calculations
            var initWaypoint = ((IWaypoint)waypoints[0]).Clone();
            initWaypoint.Position = InitPos;
            waypoints.Insert(0, (WalkWaypoint)initWaypoint);
            var bezier = new BezierSpline <WalkWaypoint>(waypoints.ToArray(), 0.01f);
            waypoints = bezier.GetBezierWaypoints();

            // Remove first waypoint as it will be added by another function
            waypoints.RemoveAt(0);
            break;

        default:
            throw new ArgumentOutOfRangeException(nameof(PathType), PathType, null);
        }

        LaneData            = waypoints.Select(wp => wp.Position).ToList();
        LaneSpeed           = waypoints.Select(wp => wp.Speed).ToList();
        LaneAcceleration    = waypoints.Select(wp => wp.Acceleration).ToList();
        LaneAngle           = waypoints.Select(wp => Quaternion.Euler(wp.Angle)).ToList();
        LaneIdle            = waypoints.Select(wp => wp.Idle).ToList();
        LaneTriggerDistance = waypoints.Select(wp => wp.TriggerDistance).ToList();
        LaneTriggers        = waypoints.Select(wp => wp.Trigger).ToList();
        LaneTime            = new List <float>();

        InitPedestrian();
        AddPoseToFirstWaypoint();

        // Calculate acceleration data only if there are no timestamps
        for (int i = 0; i < LaneData.Count - 1; i++)
        {
            var   initialPosition  = LaneData[i];
            var   destination      = LaneData[i + 1];
            var   initialSpeed     = LaneSpeed[i];
            var   destinationSpeed = LaneSpeed[i + 1];
            var   distance         = Vector3.Distance(initialPosition, destination);
            float duration;
            if (LaneAcceleration[i + 1] > 0)
            {
                // If max speed is lower than the initial speed convert acceleration to deceleration
                if (destinationSpeed < initialSpeed)
                {
                    LaneAcceleration[i + 1] *= -1;
                }

                if (!UniformlyAcceleratedMotion.CalculateDuration(LaneAcceleration[i + 1], initialSpeed,
                                                                  distance, ref destinationSpeed, out var accelerationDuration, out var accelerationDistance))
                {
                    // Max speed will not be reached with current acceleration
                    AccelerationDestination.Add(destination);
                    LaneSpeed[i + 1] = destinationSpeed;
                    duration         = accelerationDuration;
                    AccelerationDuration.Add(accelerationDuration);
                }
                else
                {
                    // Calculate mixed duration of accelerated and linear movements
                    var accelerationDestination = initialPosition +
                                                  (destination - initialPosition).normalized * accelerationDistance;
                    AccelerationDestination.Add(accelerationDestination);
                    var linearDistance = distance - accelerationDistance;
                    AccelerationDuration.Add(accelerationDuration);
                    duration = accelerationDuration + linearDistance / destinationSpeed;
                }
            }