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.

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.

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

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