Skip to content

Emit signals async #1120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ValorZard opened this issue Apr 9, 2025 · 9 comments
Closed

Emit signals async #1120

ValorZard opened this issue Apr 9, 2025 · 9 comments
Labels
c: async Everything related to async tasks/signals feature Adds functionality to the library

Comments

@ValorZard
Copy link

ValorZard commented Apr 9, 2025

Signals in Godot-rust are like 90% perfect to being perfect.
There’s already been lots of prior work done on async signals, but they are all around connecting them and receiving them.
There doesn’t seem to be much work done on EMITTING signals async.

The biggest problem I can think of is that usually &self is not send/sync, since Gd isn’t suited for multi threading. As such, there’s basically no way to spawn an async task within a function that emits a signal.

For example, this does not work (assume I am using https://github.com/2-3-5-41/godot_tokio )

impl Monster {
    // Can be invoked by other game systems.
    pub fn deal_damage(&mut self, amount: i32) {
        self.hitpoints -= amount;
        AsyncRuntime::spawn( async {
self.signals().damage_taken().emit(amount);
});
    }
}

I’ll be honest - not totally sure how to fix this. Maybe allow to clone a signal?

For the record: the current way to do this is to run your async tasks in the background, and poll on process() using channels. Once you receive something in the channel, you can emit a signal to let the other nodes that something happened. This is FINE, but it’s unwieldy and doesn’t feel very Godot.

@Bromeon Bromeon added feature Adds functionality to the library c: async Everything related to async tasks/signals labels Apr 9, 2025
@ColinWttt
Copy link
Contributor

ColinWttt commented Apr 9, 2025

I haven’t used godot_tokio, but it’s possible to do this with godot.

        let mut self_gd = self.to_gd();

        let _task_handle = godot::task::spawn(async move {
             self_gd.signals().damage_taken().emit(amount);
        });

@Houtamelo
Copy link
Contributor

If you're just looking for a solution:

https://github.com/Houtamelo/gdext_coroutines

node.start_async_task(
		async {
			smol::Timer::after(Duration::from_secs(10)).await;
			some_node.signals().damage_taken().emit(amount);
		});

@TitanNano
Copy link
Contributor

@ValorZard to clarify, you want to spawn an async task and then emit a signal inside that task?

If yes, then the solution @ColinWttt wrote should work. (Note: godot::task is currently on master but unreleased)

@ValorZard
Copy link
Author

The main problem is that these solutions only work with godot tasks. I'm doing stuff with tokio, and i can't do that inside of tokio::spawn()

@TitanNano
Copy link
Contributor

I see. This stems from the fact that godot_tokio::AsyncRuntime::spawn requires a Send future and Gd<T> is not Send. So what you want is Gd<T> to be Send. This won't be possible anytime soon. Maybe #18 will help at some point.

godot::task was among other things designed to solve issues like this by allowing non Send futures. What does godot_tokio provide that you can't do with godot::task? Or is it just a matter of migrating from one to the other?

@Bromeon
Copy link
Member

Bromeon commented Apr 9, 2025

You might be interested in tokio::task::spawn_local().

Not sure if godot_tokio supports it, but given that most classes in Godot are not thread-safe, it might be a good idea.

@ValorZard
Copy link
Author

ValorZard commented Apr 10, 2025

(For context this is what I've been up to: https://github.com/ValorZard/godot-iroh-gossip-example )
The library I'm trying to integrate with godot is pretty heavily tokio based. I'm not TOTALLY sure if all of that will work with godot task? I guess I can try...

Basically, I've been trying to integrate this into godot: https://www.iroh.computer/docs/examples/gossip-chat

@TitanNano
Copy link
Contributor

I don't think there is anything actionable in this issue.

@ValorZard
Copy link
Author

yeah seems pretty clear signals can never be send sync cuz the gd smart pointer cant be (for now anyways)
closing issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: async Everything related to async tasks/signals feature Adds functionality to the library
Projects
None yet
Development

No branches or pull requests

5 participants