godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.87k stars 21.01k forks source link

Adding a collision shapes to Tileset with GDScript not working #67148

Open feendrache opened 1 year ago

feendrache commented 1 year ago

Godot version

4.0 Beta 2

System information

Windows 10

Issue description

I'm importing Tilesets from Tiled. I create the tileset Data with gdscript.

i can add a physics layer to a tilset but then i'm not able to add collision polygons or the data for it beacuse godot says:

scene/resources/tile_set.cpp:5189 - Index p_layer_id = 0 is out of bounds (physics.size() = 0).

i can count the physics layers of the tileset and it says there is one but somehow the layer index doesn't count and it's not working

Steps to reproduce

create a tileset through code add a physics layer and try to change the tiledata of a tile with adding a polygon to the physics layer

Minimal reproduction project

No response

feendrache commented 1 year ago

i looked into the tile_set.cpp code when you add a physics layer it adds to a member variable physics_layers but when you want to add a collision polygon it checks a member variable physics NOT physics_layers... maybe this is the problem?

Calinou commented 1 year ago

@feendrache Please upload a minimal reproduction project to make this easier to troubleshoot.

feendrache commented 1 year ago

Here is my addon with an example minimal tileset in the example folder. example.zip

feendrache commented 1 year ago

in the file tileset_creator.gd at line 81 starts the objectgroup import where you need to uncomment line 90 and 91... sorry, forgot that to uncomment

afk-mario commented 1 year ago

Had the same error when I tried to create LDtk importer plugin. The error message disappeared if I added the TileSetAtlasSource to the Tileset before I added polygons to the TileData.

Probably this is needed as you declare the PhysicsLayers on the Tileset and not in the TileSetAtlasSource, none of the modified TileData seem's to be saved though not sure if something is missing, some of my code

var tileset := TileSet.new()
tileset.add_physics_layer()
var tileset_source := TileSetAtlasSource.new()
tileset_source.texture = texture
# Make sure the source is added before modifing TileData
tileset.add_source(tileset_source)

# Generate all tiles
for y in range(0, grid_height):
    for x in range(0, grid_with):
        var grid_coords := Vector2i(x,y)

        tileset_source.create_tile(grid_coords)
        var tile_data := tileset_source.get_tile_data(grid_coords, alternative_tile)
        # Not saved in the tileset
        tile_data.add_collision_polygon(layer_id)
        tile_data.set_constant_angular_velocity(layer_id, 2)

Edit: Managed to fix it by manually setting up the polygon points:

var tileset := TileSet.new()
tileset.add_physics_layer()
var tileset_source := TileSetAtlasSource.new()
tileset_source.texture = texture
# Make sure the source is added before modifing TileData
tileset.add_source(tileset_source)
var tile_extents := Vector2(tile_size.x/2, tile_size.y/2)

# Generate all tiles
for y in range(0, grid_height):
    for x in range(0, grid_with):
        var grid_coords := Vector2i(x,y)

        tileset_source.create_tile(grid_coords)
        var tile_data :TileData = tileset_source.get_tile_data(grid_coords, alternative_tile)
        tile_data.add_collision_polygon(layer_id)
        tile_data.set_collision_polygon_points(
            layer_id, 
            0, 
            PackedVector2Array(
                [
                    Vector2(-tile_extents.x, -tile_extents.y), 
                    Vector2(-tile_extents.x, tile_extents.y), 
                    Vector2(tile_extents.x, tile_extents.y),  
                    Vector2(tile_extents.x, -tile_extents.y)
                ]
            )
        )
afk-mario commented 1 year ago

So the API work's it's just clunky to use and probably would be a good idea to update the Docs so that people make sure to add the TileSetAtlasSource to the TileSet before editing the physics collision polygons.

moski commented 9 months ago

@afk-mario if you allow me, I have a question on the example shared above:

For example, assuming the tile is 16x16, the polygon points will be

[(-8, -8), (-8, 8), (8, 8), (8, -8)]

How does that work? it will only work if 0,0 is the center of the tile no the top left corner. Is that the case ? can't seem to find this in the docs.

afk-mario commented 8 months ago

@moski

How does that work? it will only work if 0,0 is the center of the tile no the top left corner. Is that the case ? can't seem to find this in the docs.

I was confused by it as well, if I understand correctly Godot is using thee AABB representation of a box/volume where you store the center point and the half width and height, you can tell by the use of the word extents

image from https://gdbooks.gitbooks.io/3dcollisions/content/Chapter1/aabb.html

Calinou commented 8 months ago

I was confused by it as well, if I understand correctly Godot is using thee AABB representation of a box/volume where you store the center point and the half width and height, you can tell by the use of the word extents

AABB in Godot has an origin and size, but size extends from the top-left corner as opposed to the center:

https://github.com/godotengine/godot/assets/180032/8799b1bd-dafd-490b-909b-0bc55c2fb0be

moski commented 8 months ago

@afk-mario Interesting, thank you. Will investigate more.