- Home /
How to stop coroutines or functions
I've been working on this script for about 12 hours now and I haven't made any progress. It's for a whack-a-mole style game.
I have 3 movement types defined in 3 functions. They each reference the MoveObject script. MoleRetreat needs to be able to interrupt MoleAscend and MoleDescend when the script recognizes a hit on the mole. Any ideas?
var moveSpeed:int = 1; var waitTime:float = 2.0; var moleVisible:boolean = false; var moleHit:boolean = false;
function OnBecameVisible() { moleVisible = true; print(gameObject.name + "is visible"); StartCoroutine("AscendMole"); yield WaitForSeconds (waitTime); StartCoroutine("DescendMole"); }
function AscendMole() { yield MoveObject.use.Translation(transform, Vector3.up, moveSpeed, MoveType.Time); }
function DescendMole() { yield MoveObject.use.Translation(transform, -Vector3.up, moveSpeed, MoveType.Time); bMoleVisible = false;
// Adjust stats
GameStats.moleKillsInARow = 0;
print("Moles killed in a row: " + GameStats.moleKillsInARow);
Destroy (gameObject);
}
function MoleRetreat() { yield MoveObject.use.Translation(transform, -Vector3.up, .25, MoveType.Time); bMoleVisible = false;
// Adjust stats
GameStats.moleKillTotal = GameStats.moleKillTotal + 1;
GameStats.moleKillsInARow = GameStats.moleKillsInARow +1;
print("Moles killed: " + GameStats.moleKillTotal);
print("Moles killed in a row: " + GameStats.moleKillsInARow);
Destroy (gameObject);
}
function Update () { if (Input.GetKeyDown(KeyCode.KeypadEnter) && !moleHit) { // Recognize hit moleHit = true;
// Adjust movement
StopAllCoroutines();
StartCoroutine("MoleRetreat");
}
}
Answer by azzogat · Dec 18, 2011 at 04:57 AM
You're going about it the wrong way 'methinks' . Whack-a-mole is the classic example for a really small State Machine. I've got a 90% completed whack-a-something project over here. I'll try and strip it a bit
enum state_ { resting, movingUp, movingDown, knocked, coolDown }; state_ state;
IEnumerator MoveUp() { state = state_.movingUp;
float t = 0;
while(t < 1&&state == state_.movingUp)
{
yield return null;
t += Time.deltaTime / moveUpTime;
TR.position = Vector3.Lerp(start, topPosition, t);
}
if(state == state_.movingUp)
SetState(4);//coolDown
}
So our moving up coroutine only does things if it's in that state while(t < 1&&state == state_.movingUp). When you click it for example, the GameManager just calls SetState(3) and that does something like:
IEnumerator Knocked()
{
state = state_.knocked;
// insert various logic bits here
float t = 0;
while(t < 1)
{
yield return null;
t += Time.deltaTime / 0.55f;
TR.position = Vector3.Lerp(start, bottomPosition, t);
}
SetState(0);//rest
}
Notice this doesn't have a state condition, since we want the mole to not be interupted while going back into it's hole.
Ofcourse you'll be checking for specific states and things within the state switcher (SetState) itself, before starting a coroutine. For example:
if(state == state_.resting) // make sure the mole is not doing anything important
StartCoroutine(MoveUp()); // start moving
else // if mole busy
GM.GetMole() // get another random mole from the array
Answer by Bendezium · Dec 18, 2011 at 06:08 PM
Eureka! Thanks azzogat! I was doing some experimenting with while loops yesterday but Unity kept crashing. I think I found something that works well.
I'm not sold on the state machine. I haven't had any experience with enums yet, but after checking out your game, which is really cool, my plans are quite different. The code I have below is very different from what I was using (MoveObject script). If I keep going back to change things, I never get to move forward and learn from my mistakes. What I have now seems to work well so I'm going to stick with it.
var waitTime:float = 2.0; var moleVisible:boolean = false; var moleHit:boolean = false; var moleKilledSpeed = 5; var moleAliveSpeed = 1;
function OnBecameVisible() {
moleVisible = true;
StartCoroutine("MolePresents");
}
function MolePresents() {
// Mole ascends
while (transform.position.y < 1){
transform.Translate(Vector3.up * Time.deltaTime * moleAliveSpeed);
yield;
}
// Mole waits
yield WaitForSeconds (waitTime);
// Mole descends
while (transform.position.y > 0) {
transform.Translate(Vector3.down * Time.deltaTime * moleAliveSpeed);
yield;
}
Destroy (gameObject);
}
function MoleKilled() {
while (transform.position.y > 0) {
transform.Translate(Vector3.down * Time.deltaTime * moleKilledSpeed);
yield;
}
// Remove object
bMoleVisible = false;
Destroy (gameObject);
}
function Update () {
if (Input.GetKeyDown(KeyCode.KeypadEnter) && !moleHit) {
// Recognize hit
moleHit = true;
// Adjust movement
StopCoroutine("MolePresents");
StartCoroutine("MoleKilled");
}
}
Whatever works is usually the thing you should stick to. Glad it works for you :D
Your answer
Follow this Question
Related Questions
Moving multiple transforms from an array in a single script 0 Answers
translate 2 Answers
how to check movement ended? 1 Answer
Stop Object From Moving After Key Release 2 Answers
Slowly move a GameObject on 1 axis, then destroy it. 1 Answer