- Home /
How to keep the last good position when interacting with triggers?
I've got a script that moves around a chicken. If the chicken tries to go someplace it shouldn't I'd like it to change directions and do someplace else. I've got the movement working, the animation states, the triggers, etc. but for some reason I can't figure out where to put the lastGoodposition = transform.position
bit of code. I've tried in Update() and in LateUpdate().
Right now my LateUpdate looks like this... All it's supposed to do is move the chicken around and keep it where is should be.
void LateUpdate() {
// We are someplace we shouldn't be
if (inDoNotEnter || (stayInCoup && !inCoop)) {
// Go to walking
if (state == State.Flying) {
state = State.Walking;
anim.SetTrigger(animHashWalk);
}
// Put back to last known good position and change direction
transform.position = lastGoodposition;
changeDirection();
return;
}
// Keep the last good position
lastGoodposition = transform.position;
// Figure out the direction to go
Vector3 moveDir = new Vector3(0, 0, 0);
switch(direction) {
case 1: // North
moveDir = new Vector3(0, 1, 0);
break;
case 2: // North East
moveDir = new Vector3(1, 1, 0);
break;
case 3: // East
moveDir = new Vector3(1, 0, 0);
break;
case 4: // South East
moveDir = new Vector3(1, -1, 0);
break;
case 5: // South
moveDir = new Vector3(0, -1, 0);
break;
case 6: // South West
moveDir = new Vector3(-1, -1, 0);
break;
case 7: // West
moveDir = new Vector3(-1, 0, 0);
break;
case 8: // North West
moveDir = new Vector3(-1, 1, 0);
break;
default:
moveDir = new Vector3(0, 0, 0);
break;
}
// If not dead or picking then move
if (state != State.Dead && state != State.Picking) {
float speed = speedWalking;
if (state == State.Flying) {
speed = speedFlying;
}
transform.Translate(moveDir * speed * Time.deltaTime);
}
}
I've got my triggers setup like this. They are working, they set/unset the bools as expected.
// Deal with external objects
void OnTriggerStay2D (Collider2D collisionInfo) {
if (collisionInfo.gameObject.GetComponent<ChickenCoopSpawn>() != null) {
stayInCoup = true;
inCoop = true;
}
}
void OnTriggerExit2D (Collider2D collisionInfo) {
if (LayerMask.LayerToName(collisionInfo.gameObject.layer) == "DoNotEnter") {
inDoNotEnter = false;
}
else if (collisionInfo.gameObject.GetComponent<ChickenCoopSpawn>() != null) {
stayInCoup = true;
inCoop = false;
}
}
void OnTriggerEnter2D (Collider2D collisionInfo) {
if (LayerMask.LayerToName(collisionInfo.gameObject.layer) == "DoNotEnter") {
inDoNotEnter = true;
}
else if (collisionInfo.gameObject.GetComponent<ChickenCoopSpawn>() != null) {
stayInCoup = true;
inCoop = true;
}
}
The issue is that when the chick goes someplace it shouldn't, it just stops and endlessly changed directions. The line setting gameObject.position
to the lastGoodPosition
is being executed, so it looks like lastGoodPosition
isn't really good.
The full script:
using UnityEngine;
using System.Collections;
public class ChickenAI : MonoBehaviour {
public float speedWalking = 0.25f;
public float speedFlying = 1;
private Animator anim;
private int animHashDead = Animator.StringToHash("Dead");
private int animHashWalk = Animator.StringToHash("Walk");
private int animHashFly = Animator.StringToHash("Fly");
private int animHashPick = Animator.StringToHash("Pick");
private int animHashDirection = Animator.StringToHash("Direction");
private int animHashJumpTo = Animator.StringToHash("JumpTo");
private enum State {Walking, Flying, Picking, Dead};
private State state;
private float changeDirectionTime;
private float deadTime;
private int direction;
private int jumpToDirection;
private bool stayInCoup;
private bool inCoop;
private Vector3 lastGoodposition;
private bool inDoNotEnter;
void Start () {
anim = GetComponent<Animator>();
jumpToDirection = Random.Range(1, 8);
state = State.Walking;
changeDirectionTime = Time.time;
inDoNotEnter = false;
inCoop = false;
stayInCoup = false;
}
void Update () {
// Update the animation state machine direction
if (jumpToDirection != 0) {
anim.SetInteger(animHashJumpTo, jumpToDirection);
anim.SetInteger(animHashDirection, jumpToDirection);
direction = jumpToDirection;
state = State.Walking;
jumpToDirection = 0;
return;
} else {
anim.SetInteger(animHashJumpTo, 0);
anim.SetInteger(animHashDirection, direction);
}
// Randomly change direction and change states
if (Time.time >= changeDirectionTime + 1 && state != State.Dead) {
changeDirectionTime = Time.time;
if (state == State.Walking || state == State.Flying) {
changeDirection();
}
// 1% change of dieing
if (state == State.Walking && Random.Range(0, 100) > 98) {
// state = State.Dead;
// deadTime = Time.time;
// anim.SetTrigger(animHashDead);
}
// 7% change of walking -> flying
else if (state == State.Walking && Random.Range(0, 100) > 93) {
state = State.Flying;
anim.SetTrigger(animHashFly);
}
// 80% change of flying -> walking
else if (state == State.Flying && Random.Range(0, 100) > 20) {
state = State.Walking;
anim.SetTrigger(animHashWalk);
}
// 50% change of walking -> picking
else if (state == State.Walking && Random.Range(0, 100) > 50) {
state = State.Picking;
anim.SetTrigger(animHashPick);
}
// 80% change of picking -> walking
else if (state == State.Picking && Random.Range(0, 100) > 20) {
state = State.Walking;
anim.SetTrigger(animHashWalk);
}
}
}
void LateUpdate() {
// We are someplace we shouldn't be
if (inDoNotEnter || (stayInCoup && !inCoop)) {
// Go to walking
if (state == State.Flying) {
state = State.Walking;
anim.SetTrigger(animHashWalk);
}
// Put back to last known good position and change direction
transform.position = lastGoodposition;
changeDirection();
return;
}
// Keep the last good position
lastGoodposition = transform.position;
// Figure out the direction to go
Vector3 moveDir = new Vector3(0, 0, 0);
switch(direction) {
case 1: // North
moveDir = new Vector3(0, 1, 0);
break;
case 2: // North East
moveDir = new Vector3(1, 1, 0);
break;
case 3: // East
moveDir = new Vector3(1, 0, 0);
break;
case 4: // South East
moveDir = new Vector3(1, -1, 0);
break;
case 5: // South
moveDir = new Vector3(0, -1, 0);
break;
case 6: // South West
moveDir = new Vector3(-1, -1, 0);
break;
case 7: // West
moveDir = new Vector3(-1, 0, 0);
break;
case 8: // North West
moveDir = new Vector3(-1, 1, 0);
break;
default:
moveDir = new Vector3(0, 0, 0);
break;
}
// If not dead or picking then move
if (state != State.Dead && state != State.Picking) {
float speed = speedWalking;
if (state == State.Flying) {
speed = speedFlying;
}
transform.Translate(moveDir * speed * Time.deltaTime);
}
}
void changeDirection () {
int change = Random.Range(1, 4) - 2;
direction += change;
if (direction == 0) {
direction = 8;
}
else if (direction == 9) {
direction = 1;
}
}
// Deal with external objects
void OnTriggerStay2D (Collider2D collisionInfo) {
if (collisionInfo.gameObject.GetComponent<ChickenCoopSpawn>() != null) {
stayInCoup = true;
inCoop = true;
}
}
void OnTriggerExit2D (Collider2D collisionInfo) {
if (LayerMask.LayerToName(collisionInfo.gameObject.layer) == "DoNotEnter") {
inDoNotEnter = false;
}
else if (collisionInfo.gameObject.GetComponent<ChickenCoopSpawn>() != null) {
stayInCoup = true;
inCoop = false;
}
}
void OnTriggerEnter2D (Collider2D collisionInfo) {
if (LayerMask.LayerToName(collisionInfo.gameObject.layer) == "DoNotEnter") {
inDoNotEnter = true;
}
else if (collisionInfo.gameObject.GetComponent<ChickenCoopSpawn>() != null) {
stayInCoup = true;
inCoop = true;
}
}
}
Answer by Juice-Tin · Jun 29, 2014 at 01:13 AM
Try FixedUpdate: http://docs.unity3d.com/ScriptReference/MonoBehaviour.FixedUpdate.html
I believe fixed updates operate on the same time periods as trigger events.
Your answer
Follow this Question
Related Questions
Damaging Enemies 1 Answer
Simple movement problem. Need units to stop dead on collision. 3 Answers
How can i execute a code when a trigger enter is called 0 Answers
2D Sprite leaves a trail when moving diagonally 1 Answer
How can I make 2D movement less jerky on a controller, with velocity and such? 0 Answers