Last active
July 1, 2018 10:18
-
-
Save Ratstail91/d19e155b784985e94ff404dfffbf79af to your computer and use it in GitHub Desktop.
Reimplemented the corn monster using state machines; the goal is to have a usable state machine, not to redo the corn. This won't compile because of reasons I can't be assed to figure out.
This file contains 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 States; | |
class Monster : MonoBehaviour { | |
//AI states | |
public UnityStateMachine<Monster> stateMachine; | |
//components | |
public Animator animator; | |
public Rigidbody2D rigidBody; | |
//movement | |
public Vector2 deltaForce; | |
public Vector2 lastDirection; | |
public float speed; | |
//behavior | |
public GameObject player; | |
public const float walkSpeed = 0.18f; | |
public const float runSpeed = 1.2f; | |
public float walkTimer = float.NegativeInfinity; | |
public void Awake() { | |
stateMachine = new StateMachine<Monster>(this, WanderState.Instance); | |
animator = GetComponent<Animator>(); | |
rigidBody = GetComponent<Rigidbody2D>(); | |
} | |
public void Start() { | |
//cache the player reference | |
player = GameObject.Find("player"); | |
} | |
public override void Update() { | |
stateMachine.UpdateState(); | |
SendAnimationInfo(); | |
} | |
public void FixedUpdate() { | |
//HandleMove() was cargo code | |
rigidBody.velocity = Vector2.zero; | |
Vector2 impulse = deltaForce.normalized * speed; | |
rigidBody.AddForce (impulse, ForceMode2D.Impulse); | |
} | |
public override void OnCollisionEnter2D(Collision2D collision) { | |
stateMachine.OnCollisionEnter2D(collision); | |
} | |
public override void OnCollisionStay2D(Collision2D collision) { | |
stateMachine.OnCollisionStay2D(collision); | |
} | |
public override void OnTriggerEnter2D(Collider2D collider) { | |
stateMachine.OnTriggerEnter2D(collider); | |
} | |
public override void OnTriggerStay2D(Collider2D collider) { | |
stateMachine.OnTriggerStay2D(collider); | |
} | |
public void SendAnimationInfo() { | |
animator.SetFloat ("xSpeed", rigidBody.velocity.x); | |
animator.SetFloat ("ySpeed", rigidBody.velocity.y); | |
animator.SetFloat ("lastXSpeed", lastDirection.x); | |
animator.SetFloat ("lastYSpeed", lastDirection.y); | |
} | |
//utility, utilizing Coroutines | |
public void SwitchToStateAfter(UnityState<Monster> state, float delay) { | |
StartCoroutine(SwitchToStateAfterCoroutine(state, delay)); | |
} | |
public IEnumerator SwitchToStateAfterCoroutine(UnityState<Monster> state, float delay) { | |
yield return new WaitForSeconds(delay); | |
stateMachine.ChangeState(state); | |
} | |
} | |
class WanderState : UnityState<Monster> { | |
//singleton | |
private static WanderState _instance = null; | |
public static WanderState Instance { | |
get { | |
if (_instance == null) { | |
_instance = new WanderState(); | |
} | |
return _instance; | |
} | |
} | |
private WanderState() { | |
//EMPTY | |
} | |
//state machine | |
public override void Update(Monster _owner) { | |
if (Vector3.Distance(_owner.player.transform.position, _owner.transform.position) < 0.4f) { | |
//attack the player if they're too close | |
_owner.stateMachine.ChangeState(BuildupState.Instance); | |
} else { | |
//meander about | |
_owner.speed = Monster.walkSpeed; | |
if (Time.time - _owner.walkTimer > 2f) { | |
_owner.walkTimer = Time.time; | |
if (Random.Range (0, 2) == 0 || _owner.deltaForce == Vector2.zero) {//tend toward straight lines | |
_owner.deltaForce.x = Random.Range (-2, 3); | |
_owner.deltaForce.y = Random.Range (-2, 3); | |
_owner.deltaForce.Normalize (); | |
} | |
} | |
} | |
} | |
public override void OnTriggerEnter2D(Monster _owner, Collider2D collider) { | |
FireDamager fire = collider.gameObject.GetComponent<FireDamager> (); | |
IceDamager ice = collider.gameObject.GetComponent<IceDamager> (); | |
WindDamager wind = collider.gameObject.GetComponent<WindDamager> (); | |
if (fire != null || ice != null || wind != null) { | |
_owner.stateMachine.ChangeState(BuildupState.Instance); | |
return; | |
} | |
//HACK: fence | |
_owner.deltaForce = Rotate (_owner.deltaForce, 180); | |
} | |
//utilities | |
Vector3 Rotate(Vector3 normalisedDirection, float angle) { | |
return Quaternion.AngleAxis(angle, Vector3.forward) * normalisedDirection; | |
} | |
} | |
class BuildupState : UnityState<Monster> { | |
//singleton | |
private static BuildupState _instance = null; | |
public static BuildupState Instance { | |
get { | |
if (_instance == null) { | |
_instance = new BuildupState(); | |
} | |
return _instance; | |
} | |
} | |
private BuildupState() { | |
//EMPTY | |
} | |
//state machine | |
public override void EnterState(Monster _owner) { | |
_owner.deltaForce.x = _owner.player.transform.position.x - _owner.transform.position.x; | |
_owner.deltaForce.y = _owner.player.transform.position.y - _owner.transform.position.y; | |
_owner.deltaForce.Normalize (); | |
_owner.speed = 0; | |
_owner.animator.SetTrigger ("charge"); | |
_owner.walkTimer = float.NegativeInfinity; | |
_owner.SwitchToStateAfter(ChargingState.Instance, 0.6f); | |
} | |
} | |
class ChargingState : UnityState<Monster> { | |
//singleton | |
private static ChargingState _instance = null; | |
public static ChargingState Instance { | |
get { | |
if (_instance == null) { | |
_instance = new ChargingState(); | |
} | |
return _instance; | |
} | |
} | |
private ChargingState() { | |
//EMPTY | |
} | |
//state machine | |
public override void OnCollisionStay2D(Monster _owner, Collision2D collision) { | |
_owner.deltaForce = Vector2.zero; | |
_owner.animator.SetTrigger ("crash"); | |
_owner.SwitchToStateAfter(StunnedState.Instance, 0.6f); | |
} | |
} | |
class StunnedState : UnityState<Monster> { | |
//singleton | |
private static StunnedState _instance = null; | |
public static StunnedState Instance { | |
get { | |
if (_instance == null) { | |
_instance = new StunnedState(); | |
} | |
return _instance; | |
} | |
} | |
private StunnedState() { | |
//EMPTY | |
} | |
//state machine | |
public override void Update(Monster _owner) { | |
if (Vector3.Distance (_owner.player.transform.position, _owner.transform.position) > 0.4f) { | |
_owner.stateMachine.ChangeState(WanderState.Instance); | |
} | |
} | |
} |
This file contains 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; | |
namespace States { | |
class UnityStateMachine<T> { | |
T owner; | |
UnityState<T> currentState = null; | |
public UnityStateMachine(T _owner, UnityState<T> _firstState) { | |
owner = _owner; | |
currentState = _firstState; | |
} | |
public void ChangeState(UnityState<T> newState) { | |
if (currentState != null) { | |
currentState.ExitState(owner); | |
} | |
if (newState != null) { | |
currentState = newState; | |
} | |
currentState.EnterState(owner); | |
} | |
//state interfaces | |
public void UpdateState() { | |
currentState.Update(owner); | |
} | |
public void OnCollisionEnter2D(Collision2D _collision) { | |
currentState.OnCollisionEnter2D(owner, _collision); | |
} | |
public void OnCollisionStay2D(Collision2D _collision) { | |
currentState.OnCollisionStay2D(owner, _collision); | |
} | |
public void OnTriggerEnter2D(Collider2D _collider) { | |
currentState.OnTriggerEnter2D(owner, _collider); | |
} | |
public void OnTriggerStay2D(Collider2D _collider) { | |
currentState.OnTriggerStay2D(owner, _collider); | |
} | |
} | |
class UnityState<T> { | |
public virtual void EnterState(T _owner) {} | |
public virtual void ExitState(T _owner) {} | |
public virtual void Update(T _owner) {} | |
public virtual void OnCollisionEnter2D(T _owner, Collision2D _collision) {} | |
public virtual void OnCollisionStay2D(T _owner, Collision2D _collision) {} | |
public virtual void OnTriggerEnter2D(T _owner, Collider2D _collision) {} | |
public virtual void OnTriggerStay2D(T _owner, Collider2D _collision) {} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment