x


Other function that is similar to OnTriggerStay

Hello,

I need something to detect like "OnTriggerStay" does, but that I could call whenever I want.

I need to detect objects in a specific zone, but not every frame because it consume too much CPU.

Any Ideas?

Thank You.

more ▼

asked Nov 29 '10 at 10:57 PM

Oninji gravatar image

Oninji
332 43 47 50

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

3 answers: sort voted first

Try this code on. It will call the method < callbackName > with a callback of your choosing. framesToSkip is the number of frames that should be skipped until the next callback is raised.

public class TriggerFrameSkip : MonoBehaviour
{
    public string callbackName = "OnTriggerFrameSkip";
    public int framesToSkip = 1;

    int elapsedFrames;    
    List<Collider> colliders = new List<Collider>();

    void Update()
    {
        if (elapsedFrames++ < framesToSkip) return;
        elapsedFrames = 0;
        RaiseCallback();
    }

    void RaiseCallback()
    {
        foreach (var collider in colliders)
            SendMessage(callbackName, collider, 
                SendMessageOptions.DontRequireReceiver);
    }

    void OnTriggerEnter(Collider collider)
    {
        colliders.Add(collider);
    }

    void OnTriggerExit(Collider collider)
    {
        colliders.Remove(collider);
    }
}

Or if you'd rather have it time based:

public class TriggerTimeSkip : MonoBehaviour
{
    public string callbackName = "OnTriggerTimeSkip";
    public float interval = 5.0f;

    List<Collider> colliders = new List<Collider>();

    void Start()
    {
        InvokeRepeating("RaiseCallback", float.Epsilon, interval);
    }

    void RaiseCallback()
    {
        foreach (var collider in colliders)
            SendMessage(callbackName, collider, 
                SendMessageOptions.DontRequireReceiver);
    }

    void OnTriggerEnter(Collider collider)
    {
        colliders.Add(collider);
    }

    void OnTriggerExit(Collider collider)
    {
        colliders.Remove(collider);
    }
}

Then your others scripts can be implemented such as:

function OnTriggerTimeSkip(collider : Collider)
{
    // called like OnTriggerStay but only every x seconds.
}

Note that you can rename the callback you want to use. Don't use OnTriggerStay, OnTriggerEnter or OnTriggerExit since the latter two will produce errors and the first will cause unwanted behaviour.

In case you want to control when to send the event yourself, you could use this base class:

public class TriggerBase : MonoBehaviour
{
    List<Collider> colliders = new List<Collider>();

    protected sealed void RaiseCallback(string callbackName)
    {
        foreach (var collider in colliders)
            SendMessage(callbackName, collider, 
                SendMessageOptions.DontRequireReceiver);
    }

    protected virtual void OnTriggerEnter(Collider collider)
    {
        colliders.Add(collider);
    }

    protected virtual void OnTriggerExit(Collider collider)
    {
        colliders.Remove(collider);
    }
}

I think you need to override OnTriggerEnter and OnTriggerExit to call base.OnTriggerEnter and base.OnTriggerExit in your script. I am too lazy to check this now. I marked RaiseCallback sealed because there isn't really any intention for you to change its behaviour. Your code should instead just call RaiseCallback("OnTriggerWhatever"); whenever you find it fitting.

more ▼

answered Dec 22 '10 at 06:56 PM

Statement gravatar image

Statement ♦♦
20.2k 35 71 176

Caveat: Make sure you clean out colliders of any null values if objects are deleted while in the area. I am not certain if they send OnTriggerExit before they are destroyed.

Dec 22 '10 at 07:04 PM Statement ♦♦

Another Caveat: This will cause your callbacks to arrive in another order than the usual "triggers first-update later". Now you can't tell which will come first. It probably doesn't do you any harm though, it all depends on what you want to do in the callback.

Dec 22 '10 at 07:16 PM Statement ♦♦
(comments are locked)
10|3000 characters needed characters left

you could turn it around and make the zone a trigger and not the objects

more ▼

answered Nov 30 '10 at 01:02 AM

Jan Helleman gravatar image

Jan Helleman
56 2 2 6

The zone is a Trigger, which check the presence of objects within if they meet some condition. The problem, OnTriggerStay is called every frame, which is very CPU intensive. So I need the exact same functionality, but called every 5 second or so.

Nov 30 '10 at 01:29 AM Oninji
(comments are locked)
10|3000 characters needed characters left

You could assign it to a variable and turn the gameObject having the trigger on once every 5 seconds.

more ▼

answered Dec 22 '10 at 05:51 PM

BitMiller gravatar image

BitMiller
197 15 15 24

(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:

x5270
x1765
x1018

asked: Nov 29 '10 at 10:57 PM

Seen: 1343 times

Last Updated: Nov 29 '10 at 10:57 PM