Created
July 4, 2019 23:49
-
-
Save beardordie/04c2ba7bd64d76dc52d2112d023ab3cb to your computer and use it in GitHub Desktop.
Unity - Simple Wander 2D component, significantly upgraded from Unity Playground
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
[RequireComponent(typeof(Rigidbody2D))] | |
public class Wander2D : MonoBehaviour | |
{ | |
public enum MovementType | |
{ | |
Smooth, | |
ConstantSpeed | |
} | |
public enum FacingType | |
{ | |
DontChange, | |
Smooth, | |
Snap | |
} | |
[Header("Movement")] | |
public bool isWandering = true; | |
public MovementType movementType = MovementType.ConstantSpeed; | |
public float speed = 3f; | |
public float waitAtDestination = 1f; | |
[Header("Distance")] | |
public float maxDistance = 4f; | |
[Header("Orientation")] | |
public FacingType facingType = FacingType.DontChange; | |
public float smoothFaceSpeed = 7f; | |
public Directions lookAxis = Directions.Up; // The direction that the GameObject will be oriented to | |
protected Vector2 direction; | |
protected Vector2 targetPosition; | |
protected bool reachedTarget = false; | |
protected Vector3 startingPoint; | |
protected new Rigidbody2D rigidbody2D; | |
protected Coroutine wanderRoutine; | |
protected virtual void Awake() | |
{ | |
rigidbody2D = GetComponent<Rigidbody2D>(); | |
} | |
// Start is called at the beginning of the game | |
protected virtual void Start() | |
{ | |
// we note down the initial position of the GameObject in case it has to hover around that (see keepNearStartingPoint) | |
startingPoint = transform.position; | |
if (isWandering) | |
{ | |
if (wanderRoutine != null) StopCoroutine(wanderRoutine); | |
wanderRoutine = StartCoroutine(ChangeDirection()); | |
} | |
} | |
[ContextMenu("Start Wandering")] | |
public virtual void StartWandering() | |
{ | |
isWandering = true; | |
if (wanderRoutine != null) StopCoroutine(wanderRoutine); | |
wanderRoutine = StartCoroutine(ChangeDirection()); | |
} | |
// Calculates a new direction | |
protected virtual IEnumerator ChangeDirection() | |
{ | |
while (isWandering) | |
{ | |
direction = Random.insideUnitCircle * maxDistance; //change the direction the player is going | |
targetPosition = (Vector2)startingPoint + direction; | |
// we measure the distance from the starting point | |
float distanceFromStart = Vector2.Distance(startingPoint, transform.position); | |
yield return new WaitUntil(() => ReachedTarget(distanceFromStart)); // if it's too far or we reached the target position | |
reachedTarget = true; | |
yield return new WaitForSeconds(waitAtDestination); | |
reachedTarget = false; | |
} | |
} | |
protected virtual bool ReachedTarget(float distanceFromStart) | |
{ | |
return Vector2.Distance(targetPosition, transform.position) < 0.1f; | |
} | |
// FixedUpdate is called every frame when the physics are calculated | |
protected virtual void FixedUpdate() | |
{ | |
//if the object has to look in the direction of movement | |
if (facingType == FacingType.Snap) | |
{ | |
SetAxisTowards(lookAxis, transform, direction); | |
} | |
else if (facingType == FacingType.Smooth) | |
{ | |
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg; | |
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.AngleAxis(angle, Vector3.forward), Time.deltaTime * smoothFaceSpeed); | |
} | |
if (!isWandering) return; | |
if (!reachedTarget) | |
{ | |
if (movementType == MovementType.Smooth) | |
{ | |
rigidbody2D.MovePosition(Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * speed)); | |
} | |
else if (movementType == MovementType.ConstantSpeed) | |
{ | |
rigidbody2D.MovePosition(Vector3.MoveTowards(transform.position, targetPosition, Time.deltaTime * speed)); | |
} | |
} | |
} | |
protected virtual void OnDrawGizmosSelected() | |
{ | |
Vector3 usePosition = transform.position; | |
if (Application.isPlaying) usePosition = startingPoint; | |
Gizmos.color = Color.green; | |
Gizmos.DrawWireSphere(usePosition, maxDistance); | |
if (!reachedTarget) | |
{ | |
// Draw gizmo at the new wandering target | |
Gizmos.color = Color.yellow; | |
Gizmos.DrawSphere(targetPosition, 0.3f); | |
} | |
} | |
protected virtual void SetAxisTowards(Directions axis, Transform t, Vector2 direction) | |
{ | |
switch (axis) | |
{ | |
case Directions.Up: | |
t.up = direction; | |
break; | |
case Directions.Down: | |
t.up = -direction; | |
break; | |
case Directions.Right: | |
t.right = direction; | |
break; | |
case Directions.Left: | |
t.right = -direction; | |
break; | |
} | |
} | |
public enum Directions | |
{ | |
Up, | |
Right, | |
Down, | |
Left, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment