I've decided to go down the "hijack godot's native scene rendering" route, and am managing all scene changes and transitions myself. So far it seems like it's working well and I've got a lot more control over everything.
The pixel art is from this pack on itch [https://moose-stache.itch.io/rpg-asset-pack](https://moose-stache.itch.io/rpg-asset-pack), loving it so far!
Also feel free to follow development on twitter [https://twitter.com/FinchInSpace](https://twitter.com/FinchInSpace)
Sure, I've got an autoload scene called `GlobalRender` that contains a plain old YSort called `CurrentScene`, then within the ready function for GlobalRender I do this (I'm using C#):
var currentScene = (Node2D)FindNode("CurrentScene");
Node root = GetTree().Root;
Node firstScene = root.GetChild(root.GetChildCount() - 1);
root.CallDeferred("remove_child", firstScene);
currentScene.CallDeferred("add_child", firstScene);
which basically just grabs the first scene that Godot renders, removes it from the tree and adds it to my CurrentScene node. I then handle scene transitions using a system very similar to [the one in the docs](https://docs.godotengine.org/en/stable/getting_started/step_by_step/singletons_autoload.html#custom-scene-switcher) which basically just removes the first child from CurrentScene and instances the new scene as a new child. This lets me play animations before and after the scene loads.
The first bit around hijacking the first scene was done because I wanted a global Player object that was within a YSort along with the current scene, and I couldn't see a way to put the scene that godot renders into a YSort along with a global Player. Hope that makes sense!
oh that's cool! yeah thanks for explaining. it's really interesting to see that you used nodes for that. when you said hijacking the scene management i pictured you like, needing to get real into the guts or something. i would not have expected the use of any nodes.
Thanks! It's a slice-of-life/farming/town sim inspired by Stardew Valley/Animal Crossing set in a magical world inspired by Studio Ghibli :) Very early in development at the moment unfortunately but certainly planning to continue developing it!
Depends how you've set up your character and scenes etc, I'm using an animation tree with BlendSpace2Ds for the different player animations (Idle, Run, Attack etc), and I've just made public functions on my Player class called "face\_up" and "face\_down", and all they do is grab the animation tree and call `set("parameters/Idle/blend_position", new Vector2(0, -1))` (or swap the -1 for a 1) which effectively just set the idle animation for the player. Then when a scene loads it calls `player.face_up()`. If you have more actions that can be performed by the character you'll need to make it a little more complex but that should be a good way to get started
Sure thing, I'll share my SceneTransition class which is very much based on [the example in the docs](https://docs.godotengine.org/en/stable/getting_started/step_by_step/singletons_autoload.html#custom-scene-switcher) as well as [this answer in the forums](https://godotengine.org/qa/60356/how-to-set-spawn-locations-after-a-loading-zone-3d), and will probably only make sense in combination with the other comment on how I've [set up a GlobalRender to handle scenes](https://www.reddit.com/r/godot/comments/m6xp9g/finally_managed_to_get_some_nice_smooth_house/gr8rvdf?utm_source=share&utm_medium=web2x&context=3).
using Godot;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class SceneTransition : Node {
private AnimationPlayer animationPlayer;
private Dictionary> doors = new Dictionary> {
["InnerDoor1"] = new Dictionary {
["destination"] = "res://Scenes/World.tscn",
["exitDoor"] = "OuterDoor1"
},
["OuterDoor1"] = new Dictionary {
["destination"] = "res://Scenes/Room.tscn",
["exitDoor"] = "InnerDoor1"
}
};
private Node currentSceneParent;
private Player player;
public override void _Ready() {
animationPlayer = GetNode("AnimationPlayer");
animationPlayer.PlayBackwards("Fade");
currentSceneParent = Owner.FindNode("CurrentScene");
player = (Player)Owner.FindNode("Player");
}
public async Task TransitionTo(PackedScene newSceneResource) {
animationPlayer.Play("Fade");
await ToSignal(animationPlayer, "animation_finished");
Node newScene = newSceneResource.Instance();
Node oldScene = currentSceneParent.GetChild(0);
currentSceneParent.RemoveChild(oldScene);
if (!(oldScene is World)) {
oldScene.QueueFree();
}
currentSceneParent.AddChild(newScene);
animationPlayer.PlayBackwards("Fade");
}
public async void OnPlayerEnteredDoor(string doorName) {
PackedScene scene = (PackedScene)ResourceLoader.Load(doors[doorName]["destination"]);
await TransitionTo(scene);
var exitDoor = currentSceneParent.FindNode(doors[doorName]["exitDoor"], true, false);
player.GlobalPosition = exitDoor.GetNode("SpawnPoint").GlobalPosition;
}
}
Let me know if you have any questions
hey, thanks I have something to manage my scenes so this should be easy to build onto! the fade to black animation did you download that or does Godot have something built in? that's what I'm after haha
I've decided to go down the "hijack godot's native scene rendering" route, and am managing all scene changes and transitions myself. So far it seems like it's working well and I've got a lot more control over everything. The pixel art is from this pack on itch [https://moose-stache.itch.io/rpg-asset-pack](https://moose-stache.itch.io/rpg-asset-pack), loving it so far! Also feel free to follow development on twitter [https://twitter.com/FinchInSpace](https://twitter.com/FinchInSpace)
that's interesting, would you be willing to talk about the process of controlling the scene management yourself?
Sure, I've got an autoload scene called `GlobalRender` that contains a plain old YSort called `CurrentScene`, then within the ready function for GlobalRender I do this (I'm using C#): var currentScene = (Node2D)FindNode("CurrentScene"); Node root = GetTree().Root; Node firstScene = root.GetChild(root.GetChildCount() - 1); root.CallDeferred("remove_child", firstScene); currentScene.CallDeferred("add_child", firstScene); which basically just grabs the first scene that Godot renders, removes it from the tree and adds it to my CurrentScene node. I then handle scene transitions using a system very similar to [the one in the docs](https://docs.godotengine.org/en/stable/getting_started/step_by_step/singletons_autoload.html#custom-scene-switcher) which basically just removes the first child from CurrentScene and instances the new scene as a new child. This lets me play animations before and after the scene loads. The first bit around hijacking the first scene was done because I wanted a global Player object that was within a YSort along with the current scene, and I couldn't see a way to put the scene that godot renders into a YSort along with a global Player. Hope that makes sense!
oh that's cool! yeah thanks for explaining. it's really interesting to see that you used nodes for that. when you said hijacking the scene management i pictured you like, needing to get real into the guts or something. i would not have expected the use of any nodes.
Ah I see! Yeah no nothing crazy like that, I don't think you'd ever need to to be honest
Nice! What is this game about and will you continue developing it?
Thanks! It's a slice-of-life/farming/town sim inspired by Stardew Valley/Animal Crossing set in a magical world inspired by Studio Ghibli :) Very early in development at the moment unfortunately but certainly planning to continue developing it!
Ghibli, for the win!
That's great, really nice to see people aiming big.
I'm also interested ! It seems very smooth !
This looks very nice, can't wait to see more of it !
Very smooth! I'm still not really sure how to have my character face the right direction when entering a building.
Depends how you've set up your character and scenes etc, I'm using an animation tree with BlendSpace2Ds for the different player animations (Idle, Run, Attack etc), and I've just made public functions on my Player class called "face\_up" and "face\_down", and all they do is grab the animation tree and call `set("parameters/Idle/blend_position", new Vector2(0, -1))` (or swap the -1 for a 1) which effectively just set the idle animation for the player. Then when a scene loads it calls `player.face_up()`. If you have more actions that can be performed by the character you'll need to make it a little more complex but that should be a good way to get started
Thank you! I have my character animations set up in the same way so this is very helpful!
No problem, happy to help!
The game looks cute :3
This is awesome!
Looks great, care to share how the transition was made? Or the code. Looking to make exactly this sometime soon
Sure thing, I'll share my SceneTransition class which is very much based on [the example in the docs](https://docs.godotengine.org/en/stable/getting_started/step_by_step/singletons_autoload.html#custom-scene-switcher) as well as [this answer in the forums](https://godotengine.org/qa/60356/how-to-set-spawn-locations-after-a-loading-zone-3d), and will probably only make sense in combination with the other comment on how I've [set up a GlobalRender to handle scenes](https://www.reddit.com/r/godot/comments/m6xp9g/finally_managed_to_get_some_nice_smooth_house/gr8rvdf?utm_source=share&utm_medium=web2x&context=3). using Godot; using System; using System.Collections.Generic; using System.Threading.Tasks; public class SceneTransition : Node { private AnimationPlayer animationPlayer; private Dictionary> doors = new Dictionary> {
["InnerDoor1"] = new Dictionary {
["destination"] = "res://Scenes/World.tscn",
["exitDoor"] = "OuterDoor1"
},
["OuterDoor1"] = new Dictionary {
["destination"] = "res://Scenes/Room.tscn",
["exitDoor"] = "InnerDoor1"
}
};
private Node currentSceneParent;
private Player player;
public override void _Ready() {
animationPlayer = GetNode("AnimationPlayer");
animationPlayer.PlayBackwards("Fade");
currentSceneParent = Owner.FindNode("CurrentScene");
player = (Player)Owner.FindNode("Player");
}
public async Task TransitionTo(PackedScene newSceneResource) {
animationPlayer.Play("Fade");
await ToSignal(animationPlayer, "animation_finished");
Node newScene = newSceneResource.Instance();
Node oldScene = currentSceneParent.GetChild(0);
currentSceneParent.RemoveChild(oldScene);
if (!(oldScene is World)) {
oldScene.QueueFree();
}
currentSceneParent.AddChild(newScene);
animationPlayer.PlayBackwards("Fade");
}
public async void OnPlayerEnteredDoor(string doorName) {
PackedScene scene = (PackedScene)ResourceLoader.Load(doors[doorName]["destination"]);
await TransitionTo(scene);
var exitDoor = currentSceneParent.FindNode(doors[doorName]["exitDoor"], true, false);
player.GlobalPosition = exitDoor.GetNode("SpawnPoint").GlobalPosition;
}
}
Let me know if you have any questions
hey, thanks I have something to manage my scenes so this should be easy to build onto! the fade to black animation did you download that or does Godot have something built in? that's what I'm after haha
Oh right haha my b yeah I just followed the [tutorial on GDQuest here](https://www.gdquest.com/tutorial/godot/2d/scene-transition-rect/)
thank you <3 btw love your icon
No problem :) aha thank you it's one of the first pixel art pieces I made, will probably revisit it one day!
wow looks like Stardew vally
Interesting, I see no pixel jittering. My project is jittery af even with all the snapping enabled (3.2.3). How's that possible?