Skip to content
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

Tilemap collision is not updated right away when changing tile (update done in the next collision resolution step) #48397

Open
Tracked by #45334
jusw85 opened this issue May 3, 2021 · 2 comments

Comments

@jusw85
Copy link

jusw85 commented May 3, 2021

Godot version:
3.3

OS/device including version:
Arch Linux

Issue description:

I need to change a tile then query it's collision status immediately.

This works:

func _physics_process(delta):
	print($RayCast2D.is_colliding())

	if Input.is_action_just_pressed("ui_left"):
		print("Removing tile")
		$TileMap.set_cell(1, 0, -1)
		$TileMap.update_dirty_quadrants()
		$RayCast2D.force_raycast_update()
		print($RayCast2D.is_colliding())
True
True
Removing tile
False
False
False
False

This doesnt:

func _physics_process(delta):
	print($RayCast2D.is_colliding())

	if Input.is_action_just_pressed("ui_right"):
		print("Changing to different tile")
		$TileMap.set_cell(1, 0, 1)
		$TileMap.update_dirty_quadrants()
		$RayCast2D.force_raycast_update()
		print($RayCast2D.is_colliding())
True
True
Changing to different tile
False
True
True
True

Minimal reproduction project:

test2.zip

@groud groud added this to the 3.3 milestone May 24, 2021
@akien-mga akien-mga changed the title Tilemap collision is not updated when changing tile Tilemap collision is not updated right away when changing tile (update done in the next collision resolution step) Oct 26, 2021
@akien-mga akien-mga modified the milestones: 3.3, 3.5 Oct 26, 2021
@akien-mga
Copy link
Member

I think that's an expected limitation from the way collision checks are done. Recalculating collisions right away after each tilemap change could be very costly when doing bulk changes.

There could maybe be a method to force the PhysicsServer to reprocess shapes and collision for situations where it's wanted though.

@jusw85
Copy link
Author

jusw85 commented Apr 22, 2022

Sorry for bumping an old issue, but since I'm moving on past this project and closing the issue for myself, I present my use case and thoughts for future reference for others (why I need to query collision status of tilemap in the same frame it was changed).

Simplified use case

  • Player states are {Idle, Falling}
  • Tiles are {Ground, CrackedGround}, both have collision
  • Tiles can change from Ground => CrackedGround => destroyed
  • Player is standing on Ground / CrackedGround
  • Events can change tiles, which signals player to check for possible transition from Idle to Falling
  • Changing tile from Ground to CrackedGround causes Raycast to report no collision on that frame, causing Player to incorrectly transition to Falling

Workarounds

  • I can directly check against tile id instead of it's collision. But in a more complex example where only some tiles have collision and others don't, Player would be polluted with needing to know the collision state of all tiles
  • I can delay the transition by one frame, after the collision resolution has been updated, but this has noticeable effect on responsiveness. If Ground is destroyed at Frame 10, Player should transition from Idle to Falling at end of Frame 10, and be Falling at start of Frame 11
  • I could re-engineer my state machine transitions to the beginning of frame i.e. check for Idle => Falling transition at start of Frame 11. But... I don't think it really makes sense to perform FSM transitions at start of frame, I'd have to carry over too much state information from previous frame to the next frame

@KoBeWi KoBeWi modified the milestones: 3.5, 3.x Apr 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants