Skip to content

Instantly share code, notes, and snippets.

@kurtdekker
Last active May 24, 2023 03:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kurtdekker/c2246d3780b93fe4e023695eb947e85d to your computer and use it in GitHub Desktop.
Save kurtdekker/c2246d3780b93fe4e023695eb947e85d to your computer and use it in GitHub Desktop.
Waypoint gizmo and waypoint manager
using UnityEngine;
using UnityEditor;
// @kurtdekker
// Make sure this is in an Editor folder!
public static class DuplicationHelpers
{
// duplicates the current object and puts it back right after the original.
[MenuItem( "Assets/Dupe Here FFS")]
static void DupeSelectedItemHereFFS()
{
foreach( var item in Selection.gameObjects)
{
int siblingOrder = item.transform.GetSiblingIndex();
var originalName = item.name;
var copy = GameObject.Instantiate<GameObject>( item, item.transform.parent);
// TODO: do anything clever you want with the name, such as suffix it with +1, etc.
copy.name = originalName;
copy.transform.SetSiblingIndex( siblingOrder + 1);
}
}
}
using UnityEngine;
using System.Collections;
// @kurtdekker - place this on the parent of a set of ordered waypoints
public class WaypointGizmo : MonoBehaviour
{
[Tooltip( "Enable duplication of this path in reverse.")]
public bool CloneToInversePath = true;
void Start()
{
WaypointListManager.Instance ().AvailablePaths.Add (transform);
if (CloneToInversePath)
{
GameObject clone = new GameObject ("CloneToInversePath:" + name);
// parent as our peer, position where our endpoint is
clone.transform.SetParent (transform.parent);
clone.transform.position = transform.GetChild( transform.childCount - 1).position;
clone.transform.rotation =
Quaternion.Euler ( 0, 180, 0) * transform.GetChild( transform.childCount - 1).rotation;
// copy the path in reverse order, spinning the transforms just in case
for (int i = 0; i < transform.childCount; i++)
{
int j = (transform.childCount - 1) - i;
GameObject child = new GameObject( "cloned waypoint #" + i);
child.transform.SetParent( clone.transform);
child.transform.position = transform.GetChild ( j).position;
child.transform.rotation =
Quaternion.Euler ( 0, 180, 0) * transform.GetChild ( j).rotation;
}
WaypointGizmo wg = clone.AddComponent<WaypointGizmo>();
wg.CloneToInversePath = false;
}
}
void OnDrawGizmos()
{
if (transform.childCount > 0)
{
Vector3 offset = Vector3.up * 1.0f;
Vector3 last = Vector3.zero;
for (int i = 0; i < transform.childCount; i++)
{
Vector3 curr = transform.GetChild(i).position;
Gizmos.color = Color.yellow;
Gizmos.DrawLine( curr, curr + offset * 2);
if (i > 0)
{
Gizmos.color = Color.white;
Gizmos.DrawLine ( last + offset, curr + offset);
Gizmos.color = Color.black;
Gizmos.DrawLine ( last, curr);
}
last = curr;
}
}
}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
// @kurtdekker - waypoint manager pseudo-singleton
public class WaypointListManager : MonoBehaviour
{
// this is NOT a singleton... it is a scene singleton!
public static WaypointListManager Instance()
{
WaypointListManager wlm = FindObjectOfType<WaypointListManager>();
if (!wlm)
{
wlm = new GameObject( "WaypointListManager.Instance();").
AddComponent<WaypointListManager>();
wlm.AvailablePaths = new List<Transform>();
}
return wlm;
}
public List<Transform> AvailablePaths;
public Transform FindRandom()
{
AvailablePaths.RemoveAll (x => !x);
if (AvailablePaths.Count < 1)
{
Debug.Log ("WaypointListManager: no AvailablePaths!");
return null;
}
return AvailablePaths[Random.Range (0, AvailablePaths.Count)];
}
int NextCursor = -1;
public void Shuffle()
{
if (AvailablePaths.Count > 1)
{
for (int i = 0; i < AvailablePaths.Count; i++)
{
int j = Random.Range ( i, AvailablePaths.Count);
if (i != j)
{
var t = AvailablePaths[i];
AvailablePaths[i] = AvailablePaths[j];
AvailablePaths[j] = t;
}
}
}
}
public Transform FindNext()
{
if (NextCursor < 0 || NextCursor >= AvailablePaths.Count)
{
NextCursor = 0;
Shuffle ();
}
Transform found = AvailablePaths [NextCursor];
NextCursor++;
return found;
}
}
@kurtdekker
Copy link
Author

kurtdekker commented May 26, 2021

Use:

  • Put a WaypointGizmo script on the parent transform of the list of waypoints for a path
  • Put all the waypoints in as GameObject children of the above gizmo, ordered appropriately
  • Optionally check the duplicate reverse boolean (causes it to report the list twice, once in reverse)

Upon running it will report itself to the WaypointListManager singleton.

When you want a new path, call the WaypointListManager's FindNext() method and you will get a top-level Transform.

You could also make a "Find me the path named XXXX" method to find a specific named path (use the .name field in the editor).

You can also decorate each sub-waypoint by putting other scripts on it that contain additional relevant information for your game needs.

NOTE: None of the above code actually traverses the waypoints. These scripts are purely for managing the definition of the waypoints within your game level, and giving them back on demand to other parts of your game.

@kurtdekker
Copy link
Author

Added the DuplicationHelpers because it's so helpful when inserting waypoints in this system.

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