Skip to content

Instantly share code, notes, and snippets.

@codeimpossible
Created November 25, 2017 01:58
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save codeimpossible/2704498b7b78240ccb08e5234b6a557c to your computer and use it in GitHub Desktop.
Save codeimpossible/2704498b7b78240ccb08e5234b6a557c to your computer and use it in GitHub Desktop.
Really simple path follower script for unity

A pretty basic script to make an object follow a path. Give the behaviour a speed and tell it which game object contains the path points (just empty game objects in the scene) and it will begin traversing them in order.

using UnityEngine;
public enum PathMovementStyle
{
Continuous,
Slerp,
Lerp,
}
public class PathController : MonoBehaviour
{
public float MovementSpeed;
public Transform PathContainer;
public PathMovementStyle MovementStyle;
public bool LoopThroughPoints;
public bool StartAtFirstPointOnAwake;
private Transform[] _points;
private int _currentTargetIdx;
private void Awake()
{
_points = PathContainer.GetComponentsInChildren<Transform>();
if (StartAtFirstPointOnAwake)
{
transform.position = _points[0].position;
}
}
private void Update()
{
if (_points == null || _points.Length == 0) return;
var distance = Vector3.Distance(transform.position, _points[_currentTargetIdx].position);
if (Mathf.Abs(distance) < 0.1f)
{
_currentTargetIdx++;
if (_currentTargetIdx >= _points.Length)
{
_currentTargetIdx = LoopThroughPoints ? 0 : _points.Length - 1;
}
}
switch (MovementStyle) {
default:
case PathMovementStyle.Continuous:
transform.position = Vector3.MoveTowards(transform.position, _points[_currentTargetIdx].position, MovementSpeed * Time.deltaTime);
break;
case PathMovementStyle.Lerp:
transform.position = Vector3.Lerp(transform.position, _points[_currentTargetIdx].position, MovementSpeed * Time.deltaTime);
break;
case PathMovementStyle.Slerp:
transform.position = Vector3.Slerp(transform.position, _points[_currentTargetIdx].position, MovementSpeed * Time.deltaTime);
break;
}
}
private void OnDrawGizmosSelected()
{
if (_points == null || _points.Length == 0) return;
var idx = 0;
foreach(var point in _points)
{
Gizmos.color = Color.yellow;
if (idx < _currentTargetIdx)
{
Gizmos.color = Color.red;
}
if (idx > _currentTargetIdx)
{
Gizmos.color = Color.green;
}
Gizmos.DrawWireSphere(point.position, 1f);
idx++;
}
Gizmos.color = Color.yellow;
Gizmos.DrawLine(transform.position, _points[_currentTargetIdx].position);
}
}
@fhgaha
Copy link

fhgaha commented Sep 19, 2023

Instead of that foreach loop you could just

for (int i = 0; i < _points.Length; i++)
{
    Gizmos.color = Color.yellow;
    if (i < _currentTargetIdx) Gizmos.color = Color.red;
    if (i > _currentTargetIdx) Gizmos.color = Color.green;
    Gizmos.DrawWireSphere(_points[i].position, 1f);
}

Also Math.Abs considered as heavy function, for comparing purposes people recommend use if (distance * distance < 0.1f) instead.
Also how do I like this post lol?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment