Last active
August 28, 2021 15:27
-
-
Save beardordie/38444475d51b16b4e5f885cc245af060 to your computer and use it in GitHub Desktop.
Unity - simple 2D auto movement component with nice Gizmo, separated from Unity Playground, added two movement types, follows Open/Closed principle
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; | |
[RequireComponent(typeof(Rigidbody2D))] | |
public class AutoMover2D : MonoBehaviour | |
{ | |
public enum AutoMovementType | |
{ | |
AddForceEveryFrame, | |
AddImpulseForce, | |
Translate | |
} | |
public AutoMovementType movementType = AutoMovementType.AddForceEveryFrame; | |
// These are the forces that will push the object every frame | |
// don't forget they can be negative too! | |
public Vector2 forceDirection = new Vector2(1f, 0f); | |
public float forceMultiplier = 2f; | |
[Tooltip("Clamp the velocity, only enforced for AddForceEveryFrame")] public float maxVelocity = 20f; | |
//is the push relative or absolute to the world? | |
public bool relativeToRotation = true; | |
//mesh to use as the Gizmo arrow, should be a mesh with an arrow pointed straight upwards | |
public Mesh gizmoMoveArrowMesh; // use this: https://github.com/Unity-Technologies/UnityPlayground/blob/master/Assets/_INTERNAL_/Resources/Meshes/MoveArrow.fbx | |
protected new Rigidbody2D rigidbody2D; | |
protected virtual void Awake() | |
{ | |
rigidbody2D = GetComponent<Rigidbody2D>(); | |
} | |
protected virtual void Start() | |
{ | |
if (movementType == AutoMovementType.AddImpulseForce) | |
{ | |
AddImpulseForce(); | |
} | |
} | |
protected virtual void Update() | |
{ | |
if (movementType == AutoMovementType.Translate) | |
{ | |
TranslateTick(); | |
} | |
} | |
protected virtual void FixedUpdate() | |
{ | |
if (movementType == AutoMovementType.AddForceEveryFrame) | |
{ | |
AddForceTick(); | |
} | |
} | |
public virtual void TranslateTick() | |
{ | |
if (relativeToRotation) | |
{ | |
transform.Translate(forceDirection * forceMultiplier, Space.Self); | |
} | |
else | |
{ | |
transform.Translate(forceDirection * forceMultiplier, Space.World); | |
} | |
} | |
public virtual void AddForceTick() | |
{ | |
if (!ExceedingMaxVelocity()) | |
{ | |
if (relativeToRotation) | |
{ | |
rigidbody2D.AddRelativeForce(forceDirection * forceMultiplier); | |
} | |
else | |
{ | |
rigidbody2D.AddForce(forceDirection * forceMultiplier); | |
} | |
} | |
ClampVelocity(); | |
} | |
public virtual void AddImpulseForce() | |
{ | |
if (relativeToRotation) | |
{ | |
rigidbody2D.AddRelativeForce(forceDirection * forceMultiplier, ForceMode2D.Impulse); | |
} | |
else | |
{ | |
rigidbody2D.AddForce(forceDirection * forceMultiplier, ForceMode2D.Impulse); | |
} | |
ClampVelocity(); | |
} | |
protected virtual bool ExceedingMaxVelocity() | |
{ | |
if (rigidbody2D.velocity.x >= maxVelocity || rigidbody2D.velocity.y >= maxVelocity) return true; | |
return false; | |
} | |
protected virtual void ClampVelocity() | |
{ | |
rigidbody2D.velocity = new Vector2(Mathf.Clamp(rigidbody2D.velocity.x, -maxVelocity, maxVelocity), | |
Mathf.Clamp(rigidbody2D.velocity.y, -maxVelocity, maxVelocity)); | |
} | |
//Draw an arrow to show the direction in which the object will move | |
protected virtual void OnDrawGizmosSelected() | |
{ | |
if (enabled) | |
{ | |
float extraAngle = (relativeToRotation) ? transform.rotation.eulerAngles.z : 0f; | |
DrawMoveArrowGizmo(transform.position, forceDirection, extraAngle); | |
} | |
} | |
protected virtual void DrawMoveArrowGizmo(Vector3 position, Vector2 direction, float extraAngle = 0f, float scale = 0f) | |
{ | |
DrawGizmo(gizmoMoveArrowMesh, position, direction, extraAngle, scale); | |
} | |
//Draws a gizmo in a certain direction, with support for an extraAngle (to make it relative to the GameObject's rotation) and a specific scale | |
protected virtual void DrawGizmo(Mesh meshToDraw, Vector3 position, Vector2 direction, float extraAngle, float scale) | |
{ | |
Gizmos.color = Color.green; | |
float arrowAngle = Angle(direction); | |
if (scale == 0f) | |
{ | |
//calculate it from the direction | |
scale = direction.magnitude; | |
} | |
Gizmos.DrawMesh(meshToDraw, position, Quaternion.AngleAxis(arrowAngle + extraAngle, Vector3.forward), Vector3.one * scale); | |
} | |
protected virtual float Angle(Vector2 inputVector) | |
{ | |
if (inputVector.x < 0) return (Mathf.Atan2(inputVector.x, inputVector.y) * Mathf.Rad2Deg * -1) - 360; | |
else return -Mathf.Atan2(inputVector.x, inputVector.y) * Mathf.Rad2Deg; | |
} | |
} |
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; | |
public class ManualMover2D : AutoMover2D | |
{ | |
private bool hasStarted = false; | |
protected override void Start() | |
{ | |
} | |
protected override void Update() | |
{ | |
if(hasStarted) | |
base.Update(); | |
} | |
protected override void FixedUpdate() | |
{ | |
if(hasStarted) | |
base.FixedUpdate(); | |
} | |
// Call this from outside the class, which makes this a manual Mover2D, not an AutoMover2D | |
[ContextMenu("Begin Movement")] | |
public void BeginMovement() | |
{ | |
if(movementType == AutoMovementType.AddForceEveryFrame || movementType == AutoMovementType.Translate) | |
{ | |
hasStarted = true; | |
} | |
else if(movementType == AutoMovementType.AddImpulseForce) | |
{ | |
AddImpulseForce(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment