How to access TileSet data directly?

Godot Version

4.3

Question

How do I select TileData for specific Atlas coords on a TileSet with a script?

My intention is to have a TIleMapLayer called HeightMask that uses a TileSet called HeightMap on every scene. My player script should be able to disable the physics collision on the specified tile when called to do so (based on the height value of the character at the time)

I can select it indirectly by getting cell tile data from a TileMapLayer and then change the physics shape as desired, but I don’t think this is a good final solution.

I think every function I need is in the documentation for TileSet, TileSetAtlasSource, TileSetSource and TileData, but it is confusing. I found a lot of documentation on how to do this for Godot 3 as it seemed simpler then, though I couldn’t reverese engineer this to Godot 4.

Scenario:
I am working with a 2.5d concept. To achieve this, I have a TileSet called HeightMap and I paint numbered tiles that have collision on them. I then use the players calculated current height to determine which collision shapes to turn off so I know which ledges I can jump over etc. I have no idea what I am doing, but I chose this way to prevent having to use too many collision layers

Current Setup

I have it “working”, but I have to select a tile painted with the heighmap to get the tile data and then I can remove and restore it’s physics shape as I want.
Every ledge has it’s own collision shape on physics layer 4 (Ledge). When I jump it disables collision with layer 4, but I don’t want to be able to use this to jump up a 2 high zone.
So I have the HeightMask with collision on physics layer 5. The player never turns off this collision layer, instead I determine the characters height and remove the physics objects on the specific tile. So if I am standing at height 1, and my jump height is one, when I jump it disables collision for HeightMask 1 and 2. This allows me to get up on height 2 from height of 1, but not from height of 0.
onready var current_tilemapheightmask = get_node(“…/…/HeightMask”) #Standard HeightMask tileset
tiledata_heightmask = current_tilemapheightmask.get_cell_tile_data(current_tilemapheightmask.local_to_map(player_node.get_position()))
On a jump:
tileddata_heightmask.set_collision_polygons_count(0, 0)

On landing:
tiledata_heightmask.set_collision_polygons_count(0,4)
tiledata_heightmask.set_collision_polygon_points(0, 0, PackedVector2Array([Vector2(-8,-8),Vector2(-8,8),Vector2(8,8),Vector2(8,-8)]))

set_physics_layer_collision?
also try altering the players collision layer instead of the heightmap.

1 Like

Thanks for the help.

Yes I think its probably easier to disable a specific collision layer on the specific TileMapLayer. I can’t get this to work though, fundamentally I don’t understand something correctly in how TileMapLayers and TileSets work.

I pull the TileSet for the TIleMapLayer and get “TileSet#-9223371976087696410”. I then set it’s physics mask and layer but it does not work. Also If I get them it does not pull the correct value as to what I have set in the TileSet.

func _on_animation_state_jumpsprint():
player_node.set_collision_mask_value(4,0)

#current_tilemap2.collision_enabled = false (this works well but I don’t want to disable all collision on the TileMapLayer, only a certain mask)

    var tileset2 = current_tilemap2.get_tile_set()
tileset2.set_physics_layer_collision_mask(4,0)
tileset2.set_physics_layer_collision_layer(4,0)
print (tileset2)
print(tileset2.get_physics_layer_collision_mask(4))
print(tileset2.get_physics_layer_collision_layer(4))

Even if I set 4 to 1, when it gets the value and prints it, it will show 0.

In the end I can’t just use the player collision mask because i would need to use a different collision mask for each height layer. If I start a jump from level 2, I need collision to be removed for level 2 and 1. If I start at height 0, i only want collision removed for layer one when I jump to make sure I can’t jump straight to level 2 from the ground.

I figured out how to set physics_layer_collision for a specific collision layer on a sheet.

tileset2.set_physics_layer_collision_mask(0,8)

The first number is the physics layer, not the collision or mask number. So usually 0.

The second number is not the actual collision layer or collision mask, but a single integer code to determine which layers / masks to enable. In short you don’t pick a collision layer to turn on or off, you use one number to determine every layer that is enabled.

In the case of activating collision layer 4 on physicslayer 0, we use the code:
tileset2.set_physics_layer_collision_mask(0,8)

image

The ID of each layer is double the last layer. So layer 1 is 1, layer 2 is 2, layer 3 is 4, layer 4 is 8.

If you want to enable multiple layers you take the individual layer IDs and add them. So to enable layer 1&4 the number would be 9.

tileset2.set_physics_layer_collision_mask(0,9)

image