x


InvokeRepeating can't be cancelled

Hello,
I'm new to Unity and tried to learn scripting with C# so I decided to start with a Towerdefence game.
Everything worked fine with the project except the turret ai.
I tried to solve it with a projectile, everytime something collides with the turret calls the function InvokeRepeating which should create a projectile which move towards an enemy.
Now my problem is, that the turret doesn't stop the InvokeRepeating command because its always called with OnTriggerEnter();
so I tried to solve it with OnTriggerExit() but this doesn't work if the collider (in this case the mob) gets destroyed while it is in the collision sphere of the tower so the Invoke won't get cancelled.
Another problem is if I set the hp of the mob to a higher value, it will enter and exit the collision sphere,
but if one random mob exits the sphere while other mobs are inside the sphere, the turret stops spawning projectiles because no new mob enters the collision sphere.

I hope you can help me and understood the main problem.

Here's the code: (I tried to solve it with another way(OnTriggerStay) but it doesnt worked)

using UnityEngine;
using System.Collections;

public class Tower1 : MonoBehaviour
{

    public GameObject projectile001;
    public bool already = false;

    void OnTriggerStay (Collider collider) 
    {
       if (collider == null)
         CancelInvoke("Fire001");
    }

    void OnTriggerEnter()
    {
       InvokeRepeating("Fire001",0,1f);
    }
    void OnTriggerExit ()
    {
       CancelInvoke("Fire001");
    }

    void Fire001() 
    {
       already = true;
       if (already == true){
       GameObject newproj001 = (GameObject)Instantiate(projectile001, transform.position,transform.rotation);
       newproj001.name = "projectile001";
       already = false;}
    }
}
more ▼

asked Jan 13 '12 at 09:18 PM

munimu gravatar image

munimu
1 1 1 2

(comments are locked)
10|3000 characters needed characters left

1 answer: sort voted first

Since there's countless possible reasons why the script 'fails', I suggest:

1- slightly change all your trigger function declarations to this:

void OnTriggerEnter(Collider other)
void OnTriggerExit(Collider other)
void OnTriggerStay(Collider other)

2- inside all the functions type

Debug.LogWarning(other.name + " is entering/ staying/ leaving the collider area ", gameObject);

To understand what's going on. Just enter play mode and you'll start to see what happens when a single target enters, stays, and exits.

more ▼

answered Jan 14 '12 at 06:33 AM

roamcel gravatar image

roamcel
1.2k 37 40 44

Oh and remember to remove the "Collider other" parameters if you don't use them, since they require extra calculation power. By the way, I deleted my other reply since it was misleading.

Jan 14 '12 at 06:34 AM roamcel

Your answer was really helpful, now I see that the main problem is, that if the first mob enters the collider area it triggers mod is entering the collider area but if the second mob is entering the collider area it doesn't trigger it again.

Instead of that it triggers mob is staying the same happens with leaving the area, after the first mob leaves the area nothing happens because another mob is in the collider area so is leaving just triggers if the last mob is leaving.

So let me guess, to solve my problem with OnTrigger was a bad idea, so is there a better way to solve the problem?

Jan 14 '12 at 11:42 AM munimu

Use a boolean value and check it in OnTriggerEnter.

Declare inside the class:

public bool alreadyfiring = true;

then inside OnTriggerEnter:

if (alreadyfiring == true)

{ CancelInvoke("Fire001"); alreadyfiring = false; }

if (alreadyfiring == false) {

InvokeRepeating("Fire001",0,1f);

}

With these instructions the turret should 'cancel' its former shooting routine, and start one anew, where you select your new target, etc., whenever a new trigger is raised.

You basically get to use 'alreadyfiring' as a flag to decide what to do in regards to firing and choosing a new target.

Using flags for logic is very useful.

(NOTE: this code is just an approximation to explain the possible solution)

Jan 15 '12 at 06:34 AM roamcel

Wouldn't using a Raycast or using Vector3.Distance be a lot easier than playing with triggers. It is quick to setup. Maybe a quick field of view as well.

Jan 15 '12 at 08:59 AM doomprodigy

A Vector3.Distance may be better but I'm using a Capsule collider because I've set the Vector y to infinity (my map is a bit uneven so I can't use sphere colliders they wouldn't be that accurate).

I solved the problem with your help but the advise with the bool variable still didn't worked but it worked with an int variable which counts to 10 and will be set back to 0 and if its 10 the code will continue.

And as second I didn't used invokerepeating because I had problems with cancelling it instead of this I used WaitForSeconds(1) and used to OnTriggerStay so it will be called 100 times but can just be executed one times a second it don't understand why it works because it should create 6 projectiles per second but it doesn't.. it works fine a friend gave me the hint to try it with the int variable never thought it would work :/

Thank you all :) I would upvote your post if it would be possible for me hehe maybe a bit later

Jan 15 '12 at 10:22 AM munimu
(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x337
x50

asked: Jan 13 '12 at 09:18 PM

Seen: 1456 times

Last Updated: Jan 15 '12 at 10:22 AM