Search code examples
game-developmentgodotgdscript

How to toggle visibility and collision of multiple objects simultaneously?


I would like to be able to simultaneously toggle the visibility and collision of multiple objects. I would assume the best way to do this has something to do with either layers or groups, but I have been unable to find any sort of resources describing how this would be executed.

Currently, there is an if statement for every possible value of lens which sets the visibility and collision on for the desired object and off for all others individually (for reference Lens0, Lens1, etc. are all MeshInstance3D).

func lens_toggle(lens):
    if lens == 0:
        $Lens0.show()
        $Lens0/StaticBody3D/CollisionShape3D.disabled = false
        $Lens1.hide()
        $Lens1/StaticBody3D/CollisionShape3D.disabled = true
        $Lens2.hide()
        $Lens2/StaticBody3D/CollisionShape3D.disabled = true
        $Lens3.hide()
        $Lens3/StaticBody3D/CollisionShape3D.disabled = true
        $Lens4.hide()
        $Lens4/StaticBody3D/CollisionShape3D.disabled = true

I'm sure there's some way to achieve this that's more efficient than manually changing the properties of every single object individually, but I am inexpereinced and don't know where to start.


Solution

  • I want to point out that You are doing something odd, you disable collision for what you are showing, and enable it for what you are not. I'll assume that is correct.

    First of all you can do this:

    $Lens0.visible = lens == 0
    $Lens0/StaticBody3D/CollisionShape3D.disabled = lens != 0
    $Lens1.visible = lens == 1
    $Lens1/StaticBody3D/CollisionShape3D.disabled = lens != 1
    $Lens2.visible = lens == 2
    $Lens2/StaticBody3D/CollisionShape3D.disabled = lens != 2
    $Lens3.visible = lens == 3
    $Lens3/StaticBody3D/CollisionShape3D.disabled = lens != 3
    $Lens4.visible = lens == 3
    $Lens4/StaticBody3D/CollisionShape3D.disabled = lens != 3
    

    Alright, as it turns out, this notation $ notation is a shorthand. So this:

    $Lens0.visible = lens == 0
    $Lens0/StaticBody3D/CollisionShape3D.disabled = lens != 0
    

    Is actually this:

    get_node("Lens0").visible = lens == 0
    get_node("Lens0/StaticBody3D/CollisionShape3D").disabled = lens != 0
    

    Does that gives you ideas? Yup:

    for index in 5:
       get_node("Lens" + str(index)).visible = lens == index
       get_node("Lens" + str(index) + "/StaticBody3D/CollisionShape3D").disabled = lens != index
    

    Perhaps a little different:

    for index in 5:
       var node:Node = get_node("Lens" + str(index))
       node.visible = lens == index
       node.get_node("StaticBody3D/CollisionShape3D").disabled = lens != index
    

    Sure, layers or groups could accomplish this. Using groups isn't really more efficient this.

    However, layers could be more efficient, however they are probably better reserved for other uses, as they are a limited resource.

    The idea would be to set different visual layers, so you can change which are rendered in the camera. Although I can't think how you would set the physic layers.