0 votes

Hi all,

I am working on a peer-to-peer Pong game.

My issue now is on Windows when the host closes the game window.

I am using the following function to capture when the game window is closed:

func _notification(what):
    if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST:
        if get_tree().network_peer != null:
            rpc_id(0, "stop_game", get_instance_id())

        get_tree().quit()

I tell the connected client to stop their execution of the game physics and load the initial screen again.

remote func stop_game(_requester) -> void:
    get_tree().network_peer = null
    get_tree().call_group_flags(SceneTree.GROUP_CALL_REALTIME, "player", "stop_network_tickrate")
    get_tree().call_group_flags(SceneTree.GROUP_CALL_REALTIME, "player", "stop_physics")
    get_tree().call_group_flags(SceneTree.GROUP_CALL_REALTIME, "BallGroup", "stop_physics")
    get_tree().change_scene_to(network_setup_scene)

This code works as expected when playing the game on Linux or macOS but not on Windows.

I have those "helper" functions on my player and ball scenes that will stop the physics execution and also a timer that I use.

For the player:

func stop_network_tickrate() -> void:
    print("player stop_network_tickrate")
    $NetworkTickRate.stop()

func stop_physics() -> void:
    print("player stop_physics")
    set_physics_process(false)

For the ball:

func stop_physics() -> void:
    print("ball stop_physics")
    set_physics_process(false)

I have added those print statements to make sure those functions were being called. I can see those on my output console:

player stop_network_tickrate
player stop_network_tickrate
player stop_physics
player stop_physics
ball stop_physics

The need to stop the physics process is because I am calling is_network_master, which fails when there is no peer connected to the network.

func _physics_process(delta) -> void:
    if is_network_master():
        rset_unreliable("puppet_velocity", velocity)
    else:
        velocity = puppet_velocity

The error message was like this:

get_unique_id: The multiplayer instance isn't currently active.   <C++ Error>   Condition "!active" is true. Returned: 0   <C++ Source>  modules/enet/networked_multiplayer_enet.cpp:658 @ get_unique_id()   <Stack Trace> player.gd:42 @ _on_NetworkTickRate_timeout()

But when I close the game windows on Windows, it doesn't even call the stop_game function.

Any suggestions on what is happening? Also, do you have any suggestions on a different way of managing that?

Thank you.

Godot version v3.5.stable.official [991bb6ac7]
in Engine by (24 points)

1 Answer

+1 vote
Best answer

After some testing my guess is, that the game quits too fast for the message to be sent. Why this is only a problem on windows I have no idea though.

With my crude test setup I was able to get it to work by first disabling the auto quit function of the scene tree (get_tree().auto_accept_quit = false). This way, pressing close won't actually close the window until you call get_tree().quit() from the notification.

Then inserting a small delay between the RPC and the quit invocation made the rpc go through:

rpc_id(0, ....)
yield(get_tree().create_timer(1), "timeout")
get_tree.quit()
by (1,517 points)
selected by

Thank you, I'll give it a try.

I have added the timer as you did but not auto_accept_quit. It was quitting without waiting for the timeout.

I'll let you know if it works.

This was the answer my friend, hats off to you!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.