Godot 4中使用opaque_to_polygons()创建可破坏环境的碰撞问题求助
解决Godot中PNG地图碰撞忽略内部封闭空白的问题
问题出在哪
你现在的代码把opaque_to_polygons生成的每个多边形都单独做成CollisionPolygon2D,但这个方法返回的数组里其实包含两种多边形:地图的外轮廓,还有内部洞的反向轮廓(缠绕方向和外轮廓相反)。分开做碰撞的话,Godot会把所有多边形都当成实心区域,导致原本应该是空的洞也有碰撞,相当于没识别出内部空白。
怎么改
把所有生成的多边形(外轮廓+内洞)放到同一个CollisionPolygon2D里,用它的**polygons属性**(注意是复数,不是单个polygon)。Godot会根据多边形的缠绕方向自动区分外轮廓和内洞,实现正确的镂空碰撞。显示用的Polygon2D也可以一次性设置所有多边形,代码更简洁。
修改后的完整代码
extends StaticBody2D var levelBM = BitMap.new() var arr var display_polygon: Polygon2D var collision_polygon: CollisionPolygon2D func _ready(): levelBM.create_from_image_alpha($Sprite.texture.get_image(), 0.1) var offsetX = 0 var offsetY = 0 if $Sprite.texture.get_width() % 2 != 0: offsetX = 1 if $Sprite.texture.get_height() % 2 != 0: offsetY = 1 update_bitmap(offsetX, offsetY) $Sprite.visible = false func update_bitmap(offsetX, offsetY): # 生成包含外轮廓和内部洞的多边形数组 arr = levelBM.opaque_to_polygons(Rect2( -$Sprite.texture.get_image().get_width()/2, -$Sprite.texture.get_image().get_height()/2, $Sprite.texture.get_image().get_width()*2, $Sprite.texture.get_image().get_height()*2 )) # 清理旧的多边形对象 if display_polygon: display_polygon.queue_free() if collision_polygon: collision_polygon.queue_free() # 创建单个显示多边形,一次性设置所有轮廓 display_polygon = Polygon2D.new() display_polygon.polygons = arr display_polygon.texture = $Sprite.texture display_polygon.position -= Vector2( ($Sprite.texture.get_width() / 2) + offsetX, ($Sprite.texture.get_height() / 2) + offsetY ) * scale.x add_child(display_polygon) # 创建单个碰撞多边形,一次性设置所有轮廓(含内洞) collision_polygon = CollisionPolygon2D.new() collision_polygon.polygons = arr collision_polygon.position -= Vector2( ($Sprite.texture.get_width() / 2) + offsetX, ($Sprite.texture.get_height() / 2) + offsetY ) * scale.x add_child(collision_polygon) queue_redraw()
补充说明
opaque_to_polygons生成的外轮廓是逆时针绕的,内洞是顺时针绕的,Godot会自动把反向的多边形当成镂空区域。- 以后做可破坏环境时,只要修改
BitMap的像素,再调用update_bitmap就能动态更新碰撞和显示效果。
内容的提问来源于stack exchange,提问作者toolier
相关产品推荐
相关产品推荐

