Godot Version
v4.5.1.stable.arch_linux
Question
I have a mobile phone style ui element in my pause menu. One of the menu items you can choose from is a minigame. I add the scene for the minigame in a SubViewport as a child like this:
func _on_game_button_pressed() → void:
var scene = load("res://elements/cellphone/games/doodle_jump/doodle_jump.tscn").instantiate()
%GameContainer/SubViewport.add_child(scene)
%GameContainer.visible = true
The tree in this scenario is set to paused, because I’m still in the pause menu.
The pause menu’s process mode is set to “When Paused”, I also tried “Always”.
All child nodes of the pause menu have their mode set to “Inherit”.
When I load the game into the SubViewport, I can move left and right. I do this by setting the velocity to a fixed value and calling move_and_slide. So at least that part seems to be working.
But the gravity is not applied to the character.
While writing this post I worked out that get_gravity, which I use like this in the _physics_process:
if not is_on_floor():
velocity.y += get_gravity().y * delta
seems to be a Vector2(0, 0).
I can’t find any settings on the SubViewport or anywhere else that I could tick to enable gravity in the SubViewport. If that’s even what’s going on here lol
How do you pause the tree?
I have a PauseMenuHandler node that has its process_mode set to Always and just calls get_tree.paused = true, like this:
func _input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel"):
if get_tree().paused:
%PauseMenuBackground.hide()
await %MobilePhone.hide_self()
get_tree().paused = false
else:
get_tree().paused = true
%PauseMenuBackground.show()
%MobilePhone.show_self()
The minigame runs fine when not paused. It’s the pausing of the tree that seems to set the resulting gravity from the get_gravity call to a 0 vector.
Let the minigame scene run for at least one frame before pausing the tree.
2 Likes
Wow, Thanks!
That (sadly) works! I’d rather have a different solution, but if it works like that, it works for now 
If I can manage to find a solution that feels less hacky, I’ll add that here 
You can just use a custom global variable to store gravity.
I just had another issue actually. Area collisions are also not working, since the whole tree is paused. I think I’ll try to pause the main part of the game in a different way, since we don’t have sub-tree pausing yet, because otherwise the minigame just doesn’t work correctly.
I’m now tracking the pause state of the game via a global variable Game.is_paused that when set emits the signals was_paused and was_unpaused.
I’m setting the global variable from the PauseMenuHandler and I’m also connecting to those signals from there. Then I set the process_mode of the main scene to “Disabled”. (and of all the tweens I’m using by calling their paused() function. might vary for each use-case if you have more things that need individual pausing. would have loved to avoid that, but oh well)
I’m also setting the process_mode of the menu to “Always”.
When unpausing I re-enable the process_mode of the main scene and disable the menu again.
(and play() the paused tweens again, if is_valid() is true, ofc)
EDIT:
Pausing the individual tweens I had to do because I’m creating them via get_tree().create_tween(). If I’m creating them not tying it to the global tree, but my main scene from where I create them via just create_tween(), then they pause without me having to interfere manually. Makes perfect sense. Didn’t think of that at first.