scene-loader
scene-loader copied to clipboard
Request: Callback/Event/Boolean for Transition delayed end
Summary
LoadingBehaviour can have a delayed end, but there is no way to know when the delay actually ended
Problem or Use Case
If you want to animate the newly open scene and you do it on Start you will start animating while a transition is still on screen.
Having a way to check with the manager if the transition scene is completely gone is nice.
I usually call this method a "DelayedStart"
Proposed Solution
We have the timing here: https://github.com/mygamedevtools/scene-loader/blob/42399361fef4bcf891826e6333716ea19efaef43/Packages/com.mygamedevtools.scene-loader/Runtime/CoreSceneManager.cs#L278
The idea would be a TransitionSceneEnded that if no transition (empty, without delayed start Behaviour or without behaviour) triggers right after ActiveSceneChanged but if a Delayed End TransitionBehaviour is used then the call happens after await progress.TransitionOutTask.Task;
I am not sure if a TransitionSceneStarted for delayed Starts would be useful, but could be added for symmetry 🤷♀
Workarround:
public class DelayedStartBehaviourMB : MonoBehaviour
{
private void Start()
{
LoadingBehavior loadingBehavior = UnityEngine.Object.FindObjectsByType<LoadingBehavior>(FindObjectsSortMode.None)
.FirstOrDefault(l => l.gameObject.scene != this.gameObject.scene); //If the scene is not my scene, it must be a loading scene
if (loadingBehavior == null || !loadingBehavior.waitForScriptedEnd)
{
// Immediate start
this.DelayedStart();
}
else
{
// Wait for the Progress Transition Out Task start
loadingBehavior.Progress.TransitionOutTask.Task.ContinueWith((_) => this.DelayedStart());
}
}
private void DelayedStart()
{
// Do fancy animations here. We are cool.
}
}
Acknowledgement
- [x] I have searched the existing issues to ensure this feature hasn't been requested already
Looking at it again, I could send a PR for something like this if it's something that you feel it's worth adding 🤔
Hi @miltoncandelero, thank you for opening this issue.
Do you have multiple objects that would need this behavior? I'm asking because maybe the way to go would be when calling the LoadAsync/TransitionAsync method:
await MySceneManager.TransitionAsync(targetScene);
// Call your delayed start script
But if you have too many objects, this wouldn't be ideal.
I think this solution should not rely on the LoadingBehavior, as it's only a listener of the real thing. Maybe we should have a way to get this info directly from the scene manager. Or, just like the LoadingBehavior receives calls from the scene manager, we could have another structure that also receives this information, but on the loaded scene.
What would be the ideal usability for you? Here are some of my ideas:
1- Implement a class deriving from MonoBehaviour you can inherit and override the DelayedStart method
2- Implement a component that exposes an event you can subscribe to execute your own DelayedStart methods
3- Expose an event on the LoadingBehavior itself to support this feature
4- Have a way to track current transitions on the scene manager and use it to trigger the DelayedStart methods
Do you have multiple objects that would need this behavior? It's not really a matter of multiple but a matter of "far from each other". Usually the button that fires the
MySceneManager.TransitionAsync(targetScene);is on the old scene and the new scene objects are the ones that need to wait until the transition is over to animate. Trying to hook the "dying" object that fired the transition with the new objects that want to know is not a good idea.
I think this solution should not rely on the LoadingBehavior, as it's only a listener of the real thing. Maybe we should have a way to get this info directly from the scene manager. Or, just like the LoadingBehavior receives calls from the scene manager, we could have another structure that also receives this information, but on the loaded scene.
Oh, I agree. My workarround is the only way I found without spinning my own static class 😅
My idea was to add an public event Action<Scene> TransitionEnded to the CoreSceneManager (and to the MySceneManager) so any behaviour that needs to know, can listen to that.
My ideal approach would be to add 2 (maybe 3?) fields to CoreSceneManager (and mirror them in MySceneManager)
bool IsTransitioning;
Action<Scene> TransitionEnded;
// Optionally
Action<Scene> TransitionStarted;
With the boolean you can ask if a transition is in progress and with the events you can ask if the transition ended/started
This looks like a good approach. I'm thinking also of a new SceneTransition (temporary name) struct to coordinate this transition information. Then you could later in your code get the active scene transition from the scene manager and get a total report of it: progress, which scene it's coming from, if it has a loading scene, the target scene, etc.
I believe we could use this opportunity to expand the transition aspect of the package, offering more transparency for the user to develop custom behavior. What do you think?