1 using System;
2 using
UnityEngine;
3
4 namespace
UnityStandardAssets.Utility
5 {
6     
public class WaypointProgressTracker : MonoBehaviour
7     {
8         
// This script can be used with any object that is supposed to follow a
9         
// route marked out by waypoints.
10
11         
// This script manages the amount to look ahead along the route,
12         
// and keeps track of progress and laps.
13
14         [SerializeField]
private WaypointCircuit circuit; // A reference to the waypoint-based route we should follow
15
16         [SerializeField]
private float lookAheadForTargetOffset = 5;
17         
// The offset ahead along the route that the we will aim for
18
19         [SerializeField]
private float lookAheadForTargetFactor = .1f;
20         
// A multiplier adding distance ahead along the route to aim for, based on current speed
21
22         [SerializeField]
private float lookAheadForSpeedOffset = 10;
23         
// The offset ahead only the route for speed adjustments (applied as the rotation of the waypoint target transform)
24
25         [SerializeField]
private float lookAheadForSpeedFactor = .2f;
26         
// A multiplier adding distance ahead along the route for speed adjustments
27
28         [SerializeField]
private ProgressStyle progressStyle = ProgressStyle.SmoothAlongRoute;
29         
// whether to update the position smoothly along the route (good for curved paths) or just when we reach each waypoint.
30
31         [SerializeField]
private float pointToPointThreshold = 4;
32         
// proximity to waypoint which must be reached to switch target to next waypoint : only used in PointToPoint mode.
33
34         
public enum ProgressStyle
35         {
36             SmoothAlongRoute,
37             PointToPoint,
38         }
39
40         
// these are public, readable by other objects - i.e. for an AI to know where to head!
41         
public WaypointCircuit.RoutePoint targetPoint { get; private set; }
42         
public WaypointCircuit.RoutePoint speedPoint { get; private set; }
43         
public WaypointCircuit.RoutePoint progressPoint { get; private set; }
44
45         
public Transform target;
46
47         
private float progressDistance; // The progress round the route, used in smooth mode.
48         
private int progressNum; // the current waypoint number, used in point-to-point mode.
49         
private Vector3 lastPosition; // Used to calculate current speed (since we may not have a rigidbody component)
50         
private float speed; // current speed of this object (calculated from delta since last frame)
51
52         
// setup script properties
53         
private void Start()
54         {
55             
// we use a transform to represent the point to aim for, and the point which
56             
// is considered for upcoming changes-of-speed. This allows this component
57             
// to communicate this information to the AI without requiring further dependencies.
58
59             
// You can manually create a transform and assign it to this component *and* the AI,
60             
// then this component will update it, and the AI can read it.
61             
if (target == null)
62             {
63                 target =
new GameObject(name + " Waypoint Target").transform;
64             }
65
66             Reset();
67         }
68
69
70         
// reset the object to sensible values
71         
public void Reset()
72         {
73             progressDistance =
0;
74             progressNum =
0;
75             
if (progressStyle == ProgressStyle.PointToPoint)
76             {
77                 target.position = circuit.Waypoints[progressNum].position;
78                 target.rotation = circuit.Waypoints[progressNum].rotation;
79             }
80         }
81
82
83         
private void Update()
84         {
85             
if (progressStyle == ProgressStyle.SmoothAlongRoute)
86             {
87                 
// determine the position we should currently be aiming for
88                 
// (this is different to the current progress position, it is a a certain amount ahead along the route)
89                 
// we use lerp as a simple way of smoothing out the speed over time.
90                 
if (Time.deltaTime > 0)
91                 {
92                     speed = Mathf.Lerp(speed, (lastPosition - transform.position).magnitude/Time.deltaTime,
93                                        Time.deltaTime);
94                 }
95                 target.position =
96                     circuit.GetRoutePoint(progressDistance + lookAheadForTargetOffset + lookAheadForTargetFactor*speed)
97                            .position;
98                 target.rotation =
99                     Quaternion.LookRotation(
100                         circuit.GetRoutePoint(progressDistance + lookAheadForSpeedOffset + lookAheadForSpeedFactor*speed)
101                                .direction);
102
103
104                 
// get our current progress along the route
105                 progressPoint = circuit.GetRoutePoint(progressDistance);
106                 Vector3 progressDelta = progressPoint.position - transform.position;
107                 
if (Vector3.Dot(progressDelta, progressPoint.direction) < 0)
108                 {
109                     progressDistance += progressDelta.magnitude*
0.5f;
110                 }
111
112                 lastPosition = transform.position;
113             }
114             
else
115             {
116                 
// point to point mode. Just increase the waypoint if we're close enough:
117
118                 Vector3 targetDelta = target.position - transform.position;
119                 
if (targetDelta.magnitude < pointToPointThreshold)
120                 {
121                     progressNum = (progressNum +
1)%circuit.Waypoints.Length;
122                 }
123
124
125                 target.position = circuit.Waypoints[progressNum].position;
126                 target.rotation = circuit.Waypoints[progressNum].rotation;
127
128                 
// get our current progress along the route
129                 progressPoint = circuit.GetRoutePoint(progressDistance);
130                 Vector3 progressDelta = progressPoint.position - transform.position;
131                 
if (Vector3.Dot(progressDelta, progressPoint.direction) < 0)
132                 {
133                     progressDistance += progressDelta.magnitude;
134                 }
135                 lastPosition = transform.position;
136             }
137         }
138
139
140         
private void OnDrawGizmos()
141         {
142             
if (Application.isPlaying)
143             {
144                 Gizmos.color = Color.green;
145                 Gizmos.DrawLine(transform.position, target.position);
146                 Gizmos.DrawWireSphere(circuit.GetRoutePosition(progressDistance),
1);
147                 Gizmos.color = Color.yellow;
148                 Gizmos.DrawLine(target.position, target.position + target.forward);
149             }
150         }
151     }
152 }


This script can be used with any object that is supposed to follow a

route marked out by waypoints.

This script manages the amount to look ahead along the route,

and keeps track of progress and laps.

[SerializeField] private WaypointCircuit circuit; A reference to the waypoint-based route we should follow

The offset ahead along the route that the we will aim for

A multiplier adding distance ahead along the route to aim for, based on current speed

The offset ahead only the route for speed adjustments (applied as the rotation of the waypoint target transform)

A multiplier adding distance ahead along the route for speed adjustments

whether to update the position smoothly along the route (good for curved paths) or just when we reach each waypoint.

proximity to waypoint which must be reached to switch target to next waypoint : only used in PointToPoint mode.

these are public, readable by other objects - i.e. for an AI to know where to head!

private float progressDistance; The progress round the route, used in smooth mode.

private int progressNum; the current waypoint number, used in point-to-point mode.

private Vector3 lastPosition; Used to calculate current speed (since we may not have a rigidbody component)

private float speed; current speed of this object (calculated from delta since last frame)

setup script properties

we use a transform to represent the point to aim for, and the point which

is considered for upcoming changes-of-speed. This allows this component

to communicate this information to the AI without requiring further dependencies.

You can manually create a transform and assign it to this component *and* the AI,

then this component will update it, and the AI can read it.

reset the object to sensible values

determine the position we should currently be aiming for

(this is different to the current progress position, it is a a certain amount ahead along the route)

we use lerp as a simple way of smoothing out the speed over time.

get our current progress along the route

point to point mode. Just increase the waypoint if we're close enough:

get our current progress along the route



Gõ tìm kiếm nhanh...