Level changers
This page uses Vector3, Transform from Unity. The glossary says what each one is.
A level changer is named by an id, a text name for that changer in the scene. You get the ids from Levels.All() and pass them to the other members. Text in brackets at the end of a note is extra detail you can skip on a first read.
Levels list, lock and use level changers
Call All() to list the changers, then SetLocked, Use or ChangeTo to lock a door or move the player. Changing fires just before any level change starts.
public static class Levels
{
public static bool IsAvailable { get; }
public static List<LevelDoorInfo> All();
public static LevelDoorInfo Get(string id);
public static bool SetLocked(string id, bool locked);
public static bool Use(string id);
public static bool ChangeTo(string scene, string entrypoint);
public static event Action<LevelChangeArgs> Changing;
}
| Method | Returns | What it does |
|---|---|---|
All() | List<LevelDoorInfo> | Every level changer in the scene you are in. |
Get(id) | LevelDoorInfo | The changer with this id. null when none has it. |
SetLocked(id, locked) | bool | Locks or unlocks a door. true when it is now in that state. |
Use(id) | bool | Uses a changer for the player. true when it worked or started. |
ChangeTo(scene, entrypoint) | bool | Moves the player to any level. true when the change started. |
| Property | Type | What it means |
|---|---|---|
IsAvailable | bool | false when the Changing event could not be set up. |
| Event | Gives you | When it fires |
|---|---|---|
Changing | LevelChangeArgs | The game is about to change level. |
LevelDoorInfo one level changer
All() and Get(id) give you one of these. OtherLevel and OtherEntrypoint tell you where the changer leads before you use it.
public sealed class LevelDoorInfo
{
public string Id { get; }
public string OtherLevel { get; }
public string OtherEntrypoint { get; }
public bool Locked { get; }
public Vector3 Position { get; }
public Vector3? SpawnPosition { get; }
public Vector3? StandPosition { get; }
}
| Property | Type | What it means |
|---|---|---|
Id | string | The changer’s id. |
OtherLevel | string | The level it leads to. |
OtherEntrypoint | string | The spot in that level where the player arrives. |
Locked | bool | true when the door is locked. Always false for a changer with no lock. |
Position | Vector3 | Where the changer’s object sits in the world when you asked. |
SpawnPosition | Vector3? | Where a player arrives in this level through this changer. null when not set. |
StandPosition | Vector3? | Where characters stop at the door. null when not known. |
LevelChangeArgs the level change that is about to start
Changing gives you one of these just before the game changes level. It tells you where the player is going.
public sealed class LevelChangeArgs
{
public string Id { get; }
public string OtherLevel { get; }
public string OtherEntrypoint { get; }
}
| Property | Type | What it means |
|---|---|---|
Id | string | The id of the changer being used. |
OtherLevel | string | The level the player is going to. |
OtherEntrypoint | string | The spot in that level where the player will arrive. |
Things to know
All()lists the level changers in the scene you are in. That includes locked doors, other use points, and invisible areas that change the level. An object that is switched off in the scene is not listed.Get(id)finds one by its id. (It lists everyChangelevel, includingDoorChangelevelandTriggerChangelevel, usingFindObjectsByType, which skips inactive objects. Whether a changer on an inactive object should appear is still open.)Idis a saved name when the changer has one, and a place in the scene when it does not. The place looks likeSceneName:Root[0]/Child[2]. If you rename or move the object, that id changes. (It is the object’sGUIDwhen it has one, otherwise the scene path.)Positionis where the changer’s object sits, which is not always a good spot to stand. The framework does not check it against the door frame. (It isChangelevel’stransform.positionwhen the list was built, with no offset.)StandPositionis where characters stop while the door opens. It isnullfor a changer that no waypoint is linked to, and for a plain changer or an invisible area, because only a door can be linked. If two waypoints link to the same door, the first one found is used. (It is the position of theWaypoint_LevelChangewhoseLinkedDooris the changer.)SpawnPositionis where the player arrives in this level when they come in through this changer. It is not where the player lands after using this changer, because that is in the other level, which is not loaded, so the framework can’t give it. It isnullwhen the changer has no arrival spot. (It is the position of the changer’sThisEntrypoint.Location. A changer in the other level whoseOtherEntrypointequals thisThisEntrypoint.Namesends the player here. It is null when the entry point or its location is not set.)SetLocked(id, locked)locks or unlocks a door. It returnstruewhen the door is now in the state you asked for. Locking or unlocking also triggers whatever the door is wired to when it is locked or unlocked, and that can include quest steps. (It calls the game’sLock()orUnLock()on aDoorChangelevel, which runs_Lockor_Unlockand fires itsonLockedandonUnlockedrelays.)Use(id)tries to use a changer for the player, with the same rules as the game. It returnsfalseand does nothing when a save is loading or being written, the player is waiting or sleeping, another level change is about to start, or the target level can’t be loaded. (The checks areSaveData.Busy,SaveController.Loading,WaitingControllernotNone,Changelevel.changeLevelDelayActiveand whether the target scene can be streamed. The loading, waiting and streaming checks are the ones inChangelevel.ChangeLevel. The delay check is added by the framework, because the game’s own call does not read it.)- Using any other kind of changer starts the change straight away. It skips the changer’s own delay and ignores whether an invisible area is switched on.
truemeans the change has started. It returnsfalsewhen the game’s save manager is not loaded. (It callsChangeLevel()directly and returnsSaveController.Loadingafter the call.) ChangeTo(scene, entrypoint)moves the player to any level by name, without using a changer. It returnstruewhen the change has started, and the new level loads a moment after the call. It returnsfalseand does nothing when a save is loading or being written, the player is waiting or sleeping, another level change is about to start, the level name is empty, or no level has that name.Changingdoes not fire for it, because no changer is involved. (It callsSaveController.ChangeLeveland returnsSaveController.Loading, which the game sets as the change starts. It also returnsfalsewhen noSaveControlleris loaded or its object is inactive, or whenSaveController.CheckIfLevelExistsis false.)Changingfires just before the game changes level. TheId,OtherLevelandOtherEntrypointit gives you are where the player is going. If the game refuses the change,Changingdoes not fire. AChanginghandler that throws an error does not stop the others. The framework logs the error and still runs the other handlers. (It is raised when the game’sChangeLevelcall passes the same guard asUse. For a door with a delay, that is after the delay, not when the door is first used.)
Limits
SetLockedreturnsfalsefor a plain use point or an invisible area, because only a door has a lock.- A door’s lock is saved, but it is only reliable as far as the game keeps both sides of the door in step. The lock state is saved so that the door at the other end can read it when its level loads. So when a level loads again, the lock state from the other side’s last save can undo what you set. See Global flags. (The lock is saved under the key
<OtherLevel>_<OtherEntrypoint>inGlobalState. When scene A loads,DoorChangelevel.OnLoadingGameoverwrites A’s lock from the A-to-B key that B’s last save wrote.) - A locked door also makes
Usereturnfalse. No key or lockpick is tried. - Using an unlocked door plays the door’s opening, so
truedoes not always mean the level change has started. The door can wait for its delay and open animation first. The game can also refuse silently when the waiting screen is open, andUsestill returnstrue. (It callsUseDoor(), so the door’s delay runs and the change starts later, from a coroutine.) - If you leave
entrypointempty, the player is not placed at any arrival spot. To put the player somewhere sensible, name an arrival spot the target level has, or one you made withTravel.AddEntrypoint(see the Player page). (An emptyentrypointis passed to the game as"NONE".) - You can’t stop the change from a
Changinghandler. Do not change anything the level change is about to read from inside one, because the handler runs before the change starts. Changingdoes not wait for a save load to finish. A handler that should ignore changes made while a save is loading can checkSaveData.Busy, which istruewhile a save is loading or being written.- A door into a level that the game already loaded in advance does not clear some state. If the player walked into a door’s area while that level was still loading ahead of time, it is not a normal level load.
Events.SceneLoadedstill gives the level’s name, but framework features that reset when a level loads normally, such as the casino and contest factors, keep their state through that door. (Such a load is not aSinglescene load.)