You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 02:13:18