grow-graphics / gd

Go + Godot 4.3
https://learn.grow.graphics/
MIT License
200 stars 10 forks source link

`Area2D` disappearing #54

Open vvh413 opened 1 month ago

vvh413 commented 1 month ago

Hi. I have encountered some strange behavior of Area2D, while trying to handle area intersection with area_entered signal.

Here is some code fragment with connect of OnAreaEntered handler to signal:

func (i *InteractionManager) Ready() {
    // ...
    i.Area.AsObject().Connect(i.Temporary.StringName("area_entered"), i.Temporary.Callable(i.OnAreaEntered), 0)
}

func (i *InteractionManager) OnAreaEntered(o gd.Object) {
    if a, ok := gd.As[*InteractiveArea](i.Temporary, o); ok {
        fmt.Println("area entered: ", a)
    }
}

This code results to this:

https://github.com/user-attachments/assets/30b0beaf-e10e-4600-818d-8374615cd476

So after OnAreaEntered handler, entered InteractiveArea just disappears. InteractiveArea is custom gd.Ared2D

type InteractiveArea struct {
    gd.Class[InteractiveArea, gd.Area2D]
    CollisionShape gd.CollisionShape2D
    Radius         gd.Float `gd:"radius"`
}

This might be related to #44, because if I trying to cast the entered object to *gd.Area2D instead of *InteractiveArea, I'm getting nil, true as a result.

func (i *InteractionManager) OnAreaEntered(o gd.Object) {
    if a, ok := gd.As[*gd.Area2D](i.Temporary, o); ok {
        fmt.Println("area entered: ", a)
    }
}
area entered:  <nil>
area entered:  <nil>

Also this is probably related to #53, because it's actually the same project and I can't take gd.Area2D as handler argument because of panic:

panic: reflect.Value.Convert: value of type gd.Object cannot be converted to type gd.Area2D

I was able to workaround this by using gd.Object as handler argument or by replacing InteractiveArea to a manually created Area2D with CollisionShape2D in editor: image image This also fixed i.Area.GetOverlappingAreas method. But area disappears anyway after OnAreaEntered handler or after taking area from gd.ArrayOf by index.

Initially I was trying to connect two signals area_entered and area_exited like this:

i.Area.AsObject().Connect(i.Temporary.StringName("area_entered"), i.Temporary.Callable(i.OnAreaEntered), 0)
i.Area.AsObject().Connect(i.Temporary.StringName("area_exited"), i.Temporary.Callable(i.OnAreaExited), 0)

But this resulted in an error about trying to remove child from busy node or something. Here is the log file error.log

Splizard commented 1 month ago

Thanks for reporting this, I'll have a look at this over the weekend.

Splizard commented 1 month ago

I notice you are trying to cast the object to a pointer type gd.As[*gd.Area2D]. This needs to be a value type for Godot classes. Do you still run into the problem if you use gd.As[gd.Area2D]?

vvh413 commented 1 month ago

Yes, the same behavior with gd.As[gd.Area2D]. Just checked, this problem appears even without any casts, with just empty handler. If i create Area2D and connect area_entered signal to my handler via editor, everything works fine. So probably it is something about Connect in Go.

Splizard commented 1 month ago

Thanks for the additional information, I think this is an issue with Go Callables that accept class arguments. I suspect gd is incorrectly taking ownership of the arguments and freeing them when it returns.