1

Let me start by saying in kinda a newbie, so keep it simple please lol

I was trying to make a portal to teleport an object in Unity. I couldn't figure it out so I looked up a tutorial and found this bit of code. It works fine, except for one tiny issue. The object going through the portal (I just used a sphere) will go back and forth constantly between the portal, essentially becoming stuck in a loop. Is there a way to set a buffer or "cooldown time" on the function so it wont trigger again immediately? I put this code on both of the portals and set the "spawnPoint"s to the other portal. So the orange portal's spawnPoint was the blue portal and vice versa. Here's the code.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Portal : MonoBehaviour
{

    public Transform spawnPoint;
   
    // Update is called once per frame
    void OnTriggerEnter(Collider other)
    {
        other.gameObject.transform.position = spawnPoint.position;
    }
}

let me know if I wasn't clear enough.

1 Answers1

2

one of many options is to use coroutines https://docs.unity3d.com/Manual/Coroutines.html

Like this.

    bool canBeUsed = true;

    void OnTriggerEnter(Collider other)
    {
        if(canBeUsed)
        {
            canBeUsed = false;

            StartCoroutine(Example());

            other.gameObject.transform.position = spawnPoint.position;
        }
    }

    IEnumerator Example()
    {
        yield return new WaitForSeconds(5);
        canBeUsed = true;
    }

One Variable for more than one portal.

Option 1:

create empty object and rename it. Maybe call it "PortalManager". Then create new script like this below and ad it to our PortalManager object. https://prnt.sc/12rlzny

using UnityEngine;

public class PortalsManager : MonoBehaviour
{
    public static bool CanBeUsed = true;
}

Then the portal script will look like this:

using System.Collections; using UnityEngine;

public class test : MonoBehaviour
{
    void OnTriggerEnter(Collider other)
    {
        if (PortalsManager.CanBeUsed)
        {
            PortalsManager.CanBeUsed = false;

            StartCoroutine(Example());

            Debug.Log("AAAA");

            //  other.gameObject.transform.position = spawnPoint.position;
        }
    }

    IEnumerator Example()
    {
        yield return new WaitForSeconds(5);
        PortalsManager.CanBeUsed = true;
    }
}

Option 2:

Dont create new object. Just create script like this:

public static class PortalsManager
{
    public static bool CanBeUsed = true;
}

The code in portals will be exactly like this from option 1

All this i tested live :)

Goku
  • 86
  • 3
  • That'll work. Thanks! – Bennett O'Neill May 09 '21 at 14:55
  • Oops. Nope. Didnt work. I typed exactly what you did. I definitely did something wrong. Any ideas? the result was still the same as before, constantly going back and forth. – Bennett O'Neill May 09 '21 at 15:03
  • hmm its probably it should be like this 'StartCoroutine("Example");' Example in " " Try it out. Look on this too https://www.youtube.com/watch?v=5L9ksCs6MbE https://www.youtube.com/watch?v=qolMYyq0nX0 – Goku May 09 '21 at 15:08
  • Ok ill check it out. Thank you!!! – Bennett O'Neill May 09 '21 at 15:09
  • Hey, in my project it works exactly like code i wrote above in answer. With `StartCoroutine(Example());` – Goku May 09 '21 at 15:24
  • you said it did work? must be an issue with my colliders then. I fiddled with the code a bit more and got it to work except it teleports back through instantly. I guess it isn't changing "canBeUsed" to be set as "false" fast enough? because the first teleport works then it goes back to the original portal before setting "canBeUsed" to false – Bennett O'Neill May 09 '21 at 19:08
  • what does your code look like exactly. Mine doesn't throw any errors but I'm sure I'm still typing something in wrong. – Bennett O'Neill May 09 '21 at 19:24
  • I see now. You use this on two portals/ two object. So class Portal on first(Orange) is one instance and class Portal on second(Blue) is another instance of class Portal. So you have two `canBeUsed` bool variable. First `canBeUsed` dont know about existence of second `canBeUsed`. You need to use Singleton or implement this on object that you are teleportating. – Goku May 09 '21 at 19:33
  • ok im getting tired of this. Everything is working. The bool is changing from true to false and back at the right times. But the sphere goes through one portal and then right back through to end up right where it was when it touched the first portal. heres a video of what its doing https://imgur.com/a/e3WDznf – Bennett O'Neill May 09 '21 at 19:59
  • just saw your other comment. Imma take a break bc im tired af. thank you for all your help! ill look into it more later. – Bennett O'Neill May 09 '21 at 20:02
  • OMG I DID IT so what i did is make two separate scripts, one for the blue portal and one for the orange portal. These scripts were the same except the bool on one of them was "canBeUsed" and the other one was "isUseable". then i went in both scripts and made a variable for the other one (so in the OrangePortal script there was a variable `public bP = BluePortal` and the opposite for the other script) Then I was able to reference the boolean on the other script and change its value when i changed the other one so theyd both change. doesnt really make sense so https://imgur.com/a/Y2hrrRz – Bennett O'Neill May 09 '21 at 22:52
  • hi @BennettO'Neill the fundamental issue here is extremely simple. you need a preload scene which holds your "general" or "global" systems (such as scoring, AI, networking and in this case the "blocking" system for the balls). Goku mentioned a "singleton" but there are no singletons in Unity (you can't have a "singleton monobehavior"). the basic pattern is dead easy for "singleton-like monobehaviors" you just have a preload scene with DontDetsoryOnLoad on an object and have all your "global" systems there. Here's a famous essay on the issue :) https://stackoverflow.com/a/35891919/294884 – Fattie May 10 '21 at 11:28
  • Hey @Fattie saying singleton i was thinking on something like static class with static variable and its working fine. Or class with only static variable, Im not sure that article you linked is not outdated btw. Il edit answer with that, what i mentioned here. – Goku May 10 '21 at 15:14
  • hi @Goku you're totally 100% correct that you COULD use a static variable here. For sure. (Note though that if you try to squeeze it in to a static you have to duplicate logic everywhere, its a poor pattern). But the simple fact is in 100% of unity projects (unless its just a trivial test) you are going to need a "preload" scene for "singleton-like Monobehaviors"..so simply, your AI, comms, scoring, lap logic or whatever ... you use that. You use it constantly and always in Unity. So you're going to have it anyway so of course you use it for this simple example of "blocking button logic". – Fattie May 10 '21 at 16:06
  • BTW I wrote that article, I can assure it's not out of date :) :) (Unless Unity finally built-in a preload scene like last week and I don't know!!) Cheers @Goku !!! – Fattie May 10 '21 at 16:06
  • hi @Goku .. regarding the edit you just made. You really shouldn't do that (code section 2). it would mean that you have code all over the place which manipulates the "global" bool CanBeUsed. You just can't do that. have an actual function *in the class PortalsManager* which takes care of everything. your code then (everywhere in the app) just looks something like this .. if (lockManager.buttonClickable()) ... blah blah. the function *in the class PortalsManager* takes care of everything – Fattie May 10 '21 at 16:13
  • If i want to do it in my project, il probably do it in way you say it. Cause you are right. But i want only to show one, of a many doors, to accomplish his challenge. "100 programmers 100 solutions" :) – Goku May 10 '21 at 16:23