I’m trying to make some level-to-level doorways/portals. basically, a GO that when you enter it, loads a new level and puts you where that portal should take you inside of that level. Each level will have multiple portals to other levels, so I can’t just rely on the player GO’s starting position.
NOTE: I’m NOT talking about seamless portals with no visible transition. I am also not talking about Portals like the Valve game. Just two-way “level exits” that load new levels. The key is that I can’t just use the player GO’s default position in the level.
Basically it comes down to needing one GO dynamically find another GO and move, all before the first frame of the new level is rendered.
There doesn’t seem to be a good way to do this, unless I’m missing something. here’s the different methods I’ve come up with so far:
have a “portal manager singleton” that the player GO registers with (this was my first attempt). But it’s got problems. Player can’t register on Awake(), since the singleton may not exist yet. So it needs to register on Start(). But the portal needs to move the player on Start() as well. So if the portal gets Start() before the player does, it will fail. Switching things around (have the portal move the player) has the same potential problem.
use FindObjectOfType. The docs say it’s really slow, so this seems like something bad to use for mobile games. Haven’t tested it though.
Link all the portals in a level to the player GO in the editor via drag-n-drop. Seems like a pain in the ass, prone to error, and it just seems like there’s gotta be a better way.
Make the player be a singleton. This way the portals know where to find the player. Seems like it would work for what I want to do here. But it doesn’t seem like it would scale for bigger situations where GOs need to dynamically find each other.
Something else I’m not aware of! Which is why I’m writing this!
How would you go about making level-to-level portals? How do you make one GO find another one before the first frame of the level is rendered?
I assume you cannot use loadleveladditive for some reason.
A singleton makes sense. You could yield one more frame, to ensure that things were called in a specific order. A one frame delay will probably not be noticeable to the user unless you are getting a poor frame rate.
Calling FindObjectOfType once at the beginning of every level is not really any sort of performance hinderance. Calling it every frame would start to slow things down, but it is designed to be called occasionally.
Yeah, that would be a pain, and if you are loading new levels, the inspector won’t let you link to objects in other scenes.
Hey, you already said 3 above.
You cannot really find these points between levels without some sort of static variable or DontDestroyOnLoad. I might have the portals send a message to a central manager a message with a tag or a number value when the user enters it. That might not be any better than doing it manually, but just a suggestion. Maybe something like:
void Start () {
DontDestroyOnLoad(this);
}
void PortalToStart (String nextPortal) {
Application.LoadLevel("someLevel");
player.position = GameObject.Find(nextPortal).transform.position;
}
//P.S. wrote this in a few minutes for the general idea. Ignored casts and other important stuff.
So for each portal, you would enter the name of the portal on the next level that you want to link to and it would load it.
I went with # 1 – making the player a persistent singleton that is not destroyed between level loads. Of course, I didn’t realize I needed to solve the exact same problem with the camera GO as well. Ugh.
HOWEVER! It seems to be working for me even without finding the camera. Not sure why but I have a theroy:
I think that Awake() gets called on all GOs, then Start(), then Update() AND THEN the first frame of the game gets rendered. Meaning I can move things around in the world the first time Update() is called, and we still won’t see anything pop around. Not sure if a yield in Start will do the same.
I think. I’m not sure. Can anyone confirm this? I’ve yet to do a true test; it just seems like that’s what’s happening.
(this is why I didn’t want to use a yield originally)