【Creator 3.8.2】PhysicsSystem2D射线检测不到,有代码,必现

  1. PhysicsSystem2D射线检测不到,不知道是我的代码不对还是引擎的BUG,必现。
  2. 如果不填mask参数,或者mask参数设置为0xffffffff,则没问题。
  3. PhysicsSystem2D.instance.raycast(p1, p2, ERaycast2DType.All, mask)这行代码的返回值是:p1-p2这条线段上的所有符合mask的物体。我的理解对不对?如果这个api的意思不是这样的,那么我的问题就不是问题了。
    image
    项目文件如下:
    RaycastTest.zip (26.5 KB)
    不想看项目的也可以直接看下面的代码:
import { _decorator, BoxCollider2D, Component, ERaycast2DType, Input, input, Label, Node, PhysicsSystem2D, Vec3 } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('Main')
export class Main extends Component {

    start() {
        input.on(Input.EventType.MOUSE_DOWN, this.onMouseDown, this);
    }

    onMouseDown() {
        // P1 和 P2 是两个点,用于发射射线
        const p1 = this.findNode('P1').worldPosition;
        const p2 = this.findNode('P2').worldPosition;

        // 获得 A B C D 的碰撞组
        const ga = this.findNode('A').getComponent(BoxCollider2D).group;
        const gb = this.findNode('B').getComponent(BoxCollider2D).group;
        const gc = this.findNode('C').getComponent(BoxCollider2D).group;
        const gd = this.findNode('D').getComponent(BoxCollider2D).group;

        // 发射射线, 只与D发生碰撞
        // const mask = 0xffffffff;
        // const mask = ga | gd;
        const mask = gd;
        const result = PhysicsSystem2D.instance.raycast(p1, p2, ERaycast2DType.All, mask);
        
        // 保存射线碰到的节点名称
        let names = [];
        for (let i = 0; i < result.length; i++) {
            names.push(result[i].collider.node.name);
        }

        // label 用于显示测试信息
        const label = this.findNode('Label').getComponent(Label);
        const posA = this.findNode('A').worldPosition;
        const posB = this.findNode('B').worldPosition;
        const posC = this.findNode('C').worldPosition;
        const posD = this.findNode('D').worldPosition;

        label.string = `世界坐标 A${this.posString(posA)} B${this.posString(posB)} C${this.posString(posC)} D${this.posString(posD)}\n`;
        label.string += `碰撞组 A:${ga} B:${gb} C:${gc} D:${gd}\n`;
        label.string += `射线掩码 ${mask} ${(mask >>> 0).toString(2)}\n`;
        label.string += `射线从 ${this.posString(p1)} 到 ${this.posString(p2)}\n`;
        label.string += `碰撞到的节点: ${names.join(', ')}`
    }

    // 通过名称查找节点
    findNode(name: string): Node {
        return this.node.getChildByPath(name);
    }

    // 将坐标转换为字符串
    posString(pos: Vec3): string {
        return `(${pos.x.toFixed()}, ${pos.y.toFixed()}, ${pos.z.toFixed()})`;
    }
}

大家可以帮我看看么,我太难了,感谢一亿!

1赞

image

image

所以说,只要遇到一个与mask不匹配的,就结束了。而且射线检测的顺序是不固定的,不是越近就先检测,跟物体的距离无关。所以射线有时候能穿透不需检测的物体,有时不能穿透不需检测的物体。不知道我的分析对不对。
大家帮我看看可以么,感谢一亿!

image
谁懂啊,家人们

@boyue 你能帮帮我么,我不认识你,但是我看见cocos中文社区中你非常活跃,想必你是乐于助人的

是的,bug来的。3.6.2 box2d 的射线 带Mask 返回空数组 - Creator 3.x - Cocos中文社区

1赞

好的,感谢!那就不设置mask,然后自己过滤

解决方案:发射射线不要填mask,获取到射线的结果后,自己通过collider的group来过滤掉不相关的物体