Skip to content

Instantly share code, notes, and snippets.

@juliomarcos
Created July 3, 2018 19:10
Show Gist options
  • Save juliomarcos/68b8d7922f2a11192122dd2df1215ac5 to your computer and use it in GitHub Desktop.
Save juliomarcos/68b8d7922f2a11192122dd2df1215ac5 to your computer and use it in GitHub Desktop.
Character grid movement using 1 movement input buffering and input filtering delay
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum PlayerState {
Idle,
Moving,
Hit,
Attack,
AttackMove
}
public struct Move {
public float h, v;
public Move(float h, float v)
{
this.h = h;
this.v = v;
}
}
public class PlayerController : MonoBehaviour {
public float speed;
public float pressFilterDelay;
private PlayerState state;
private float timeOfLastPress;
private Move? queuedMove;
// Use this for initialization
void Start () {
state = PlayerState.Idle;
queuedMove = null;
}
// Update is called once per frame
void Update () {
var hor = Input.GetAxis("Horizontal");
var ver = Input.GetAxis("Vertical");
if (ver < 0) transform.rotation = Quaternion.Euler(0, 0, -180);
else if (ver > 0) transform.rotation = Quaternion.Euler(0, 0, 0);
else if (hor < 0) transform.rotation = Quaternion.Euler(0, 0, 90);
else if (hor > 0) transform.rotation = Quaternion.Euler(0, 0, -90);
//transform.position += transform.up * speed * Time.deltaTime;
var move = MoveFromInputAxes();
if (move.h == 0 && move.v == 0) return;
if (Time.time - timeOfLastPress < pressFilterDelay) return;
if (state == PlayerState.Idle) {
print ("from idle to move");
MoveTo(move);
}
else if (state == PlayerState.Moving) {
// queue up to one movement
print ("queuing one move");
queuedMove = move;
}
timeOfLastPress = Time.time;
}
private Move MoveFromInputAxes()
{
return new Move((int)Input.GetAxisRaw("Horizontal"), (int)Input.GetAxisRaw("Vertical"));
}
void MoveTo(Move move) {
var xDir = move.h;
var yDir = move.v;
if (xDir == 0 && yDir == 0) return;
// no diagonals
if (yDir != 0) xDir = 0;
xDir *= 2;
yDir *= 2;
state = PlayerState.Moving;
Vector2 start = transform.position;
Vector2 end = start + new Vector2(xDir, yDir);
StartCoroutine(SmoothMove(end));
}
IEnumerator SmoothMove(Vector3 end) {
print ("SmoothMove from: " + transform.position + " to: " + end);
float startTime = Time.time;
float sqrRemainingDistance;
do {
sqrRemainingDistance = (transform.position - end).sqrMagnitude;
float distCovered = (Time.time - startTime) * speed; // betweens [0, 1]
transform.position = Vector3.Lerp(transform.position, end, distCovered);
yield return null;
} while (sqrRemainingDistance > 0.01f);
print ("End of SmoothMove");
transform.position = end; // do not accumulate error
print("queue " + queuedMove);
if (queuedMove != null) {
MoveTo(queuedMove.GetValueOrDefault());
queuedMove = null;
} else {
state = PlayerState.Idle;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment