Skip to content

Reverse Usage Lookup

C. Plug edited this page Apr 26, 2023 · 15 revisions

First thing first, follow the quickstart; The quickstart gets you ready to use UniSwitcher.
If you have trouble, check if you have followed everything in the instructions.

This page assumes you have done that, and your IScene implementation is called Scene in your project.

➑️ Change the Scene to another

Call PerformSceneTransition on ChangeScene. You need to add your scene definition to your BaseScene implementation:

 PerformSceneTransition(ChangeScene(Scene.FirstScene));

βž• Additively load a scene

Call PerformSceneTransition on AddScene. You need to add your scene definition to your BaseScene implementation:

PerformSceneTransition(AddScene(Scene.SecondScene));

πŸ”’ Pass a value to the destination scene

Put your data in the second argument - it will be available as an [Inject] variable for the scripts in the next Scene.

PerformSceneTransition(AddScene(Scene.NextScene, new YourRandomData(12345)));

// In the scripts on the next Scene, your data will appear in the property `_data` if you write this.
[Inject] private YourRandomData _data;

πŸ›‘ I want to enter Play Mode directly, but the Scene crashes b/c it is missing the required data from another Scene!

If you directly enter Play Mode into a Scene that requires data from another Scene, you may experience an immediate crash.
The crash is because of the [Inject] attribute.
If you want to test a scene directly, use the [InjectOptional] attribute instead.

// This will prevent your Scene from crashing if playtested directly, but the `_data` will be `null.`
// You'll want to provide your test data somewhere instead.
[InjectOptional] private YourRandomData _data;

πŸ›‘ I want to playtest the Scene directly, but it cannot run my scene initialization code!

Some scenes may depend on the previous scene calling PerformSceneTransition into them and triggering ISceneEntryPoint.Fire(). However, it is impossible to enter Play Mode into such Scenes directly while expecting Fire() to run. To force the initialization code to run, create a property with the type of marker class StartedFromAnotherSceneMarker to check if you are trying to playtest the Scene directly. This property does NOT have to be defined in the Switcher class to function; it can be in other MonoBehaviours.

// MUST be [InjectOptional]
[InjectOptional] StartedFromAnotherSceneMarker _marker;

Check this value of the member:

_marker.HasStartedByAnotherScene()

false from this method means that this is the first Scene in that Play Mode session. If you get false, you should manually run the initialization code for that Scene, should there be any.


✏️ How do I add scene definitions to my BaseScene implementation?

Add static members to it.

public Scene: BaseScene {
  public static Scene Scene1 => new Scene("Assets/path/to/scene.unity");
  ...

If you want to specify the scene path in full, add a Create method; we made the BaseScene's constructor protected for a reason (the static property approach is more straightforward.)

  public static Scene Create(string path) {
     return new Scene(path);
  }

✨ Transition to the next Scene with a transition effect

For this to work, you must have a transition effect installed.
If you use the default UniSwitcherInstaller, you will automatically use the sample implementation of the UniSwitcher transition effect Assets/Plugins/UniSwitcher/Sample/Prefab/Transition Background.prefab.

You can even implement your own!!

After that, call WithTransitionEffect() on ChangeScene.

PerformSceneTransition(
    AddScene(Scene.DestinationScene)
        .WithTransitionEffect()
);

πŸ”„ Show a Progress Bar

For this to work, you must implement a progress bar using ProgressDisplayController,
which must be referenced from the Switcher's sceneProgressBarController.

As long as it is referenced from the Switcher, the progress bar will automatically appear for all the transitions.


πŸ›‘ My progress bar is showing even on Additive scene load, and I don't want it

Call HideProgressBar().

PerformSceneTransition(
    AddScene(Scene.DialogScene)
        .HideProgressBar()
);

⌚ I want to delay the transition after triggering it

Use After on ChangeScene.

PerformSceneTransition(
    AddScene(Scene.DelayedScene)
        .After(5) // after 5 seconds
);

[NOTE]
The interval you specify is the one between the time of triggering PerformSceneTransition
and the start of your transition effect, not the actual scene switch.


⌚ I want the animation/process or whatever to wait for the scene transition to end!

You can try implementing your initialization code in Switcher as an async function and await WaitForTransitionReady().
It will pause the execution of your method until the transition is complete. Unfortunately, this must be done in your Switcher class implementation.

public class Controller: Switcher {
    // Suppose this is called during ISceneEntryPoint.Fire()
    public async UniTask EntryPoint() {
        // DO call WaitForTransitionReady() _outside_ of the entry point call chain. See note below.
        Animate().Forget();
    }
    
    public async UniTask Animate() {
        await WaitForTransitionReady();
        // Place animation code and whatnot - it won't be run until the transition is ready.
    }
}

⚠️ WARNING
Do NOT use this method under the call chain of ISceneEntryPoint.Fire() as it would cause a deadlock!!!
You probably want to create another async function and then call it with the .Forget() method, just like the example above.


⚠️ I want to suppress warnings on PerformSceneTransition!

Append .Forget(Debug.LogException) to the call. These warnings are because PerformSceneTransition is an async, UniTask method. Also, adding it is recommended since you can safely log exceptions should one get thrown.

PerformSceneTransition(Scene.SampleScene).Forget(Debug.LogException);

More reverse usage lookup is TODO.

Clone this wiki locally