Skip to content

Instantly share code, notes, and snippets.

@beardordie
Created July 4, 2019 23:49
Show Gist options
  • Save beardordie/04c2ba7bd64d76dc52d2112d023ab3cb to your computer and use it in GitHub Desktop.
Save beardordie/04c2ba7bd64d76dc52d2112d023ab3cb to your computer and use it in GitHub Desktop.
Unity - Simple Wander 2D component, significantly upgraded from Unity Playground
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