鼠标节点事件中同级节点归属有问题

  • Creator 版本: 3.6.1、3.5.2

  • 目标平台: Edge 浏览器预览

  • 重现方式:使用 setSiblingIndex 改变同级节点的引索后,鼠标节点点击事件没有按照正常效果执行。

  • 首个报错:

  • 之前哪个版本是正常的: 2.4.10

  • 手机型号:

  • 手机浏览器:

  • 编辑器操作系统:

  • 重现概率: 100%

首先描述一下遇到的问题

根据 同级节点间的触点归属问题 中的解释如下:

同级节点间,触点归属于处于顶层的节点。假设上图中 B、C 为同级节点,C 节点部分覆盖在 B 节点之上。这时候如果 C 节点接收到触摸事件,那么表示触点归属于 C 节点,这意味着同级节点 B 就不会再接收到触摸事件了,即使触点同时也在 B 节点内。

而我的需求是,在同级节点中,点击任意一个节点,将其置顶到顶层,节点关系如下:

SpriteSplash_ASpriteSplash_B 节点上都挂上了一个相同的脚本,代码如下:

import { _decorator, Component, Node, Event, EventMouse } from 'cc';
const { ccclass, property } = _decorator;

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

    onLoad() {
        this.node.on(Node.EventType.MOUSE_DOWN, this.onMouseDown, this);
    }

    start() {

    }

    onMouseDown(event: EventMouse) {
        let nodesLength = this.node.parent.children.length;
        if (this.node.getSiblingIndex() < nodesLength - 1) {
            this.node.setSiblingIndex(nodesLength - 1);
        }
    }

    update(deltaTime: number) {
        
    }
}

但是预览的效果是这样的:

ClickBug_1

按照上面 同级节点间的触点归属问题 的解释,当点击 A节点 后,A节点 被设置在了顶层,而此时再点击 A 与 B 重叠的地方 时,触点归属于 A节点B 节点 就不会再接收到触摸事件了。

但是预览效果是 B节点 仍然接受到了点击事件,而且按道理说,如果只是点击事件穿透了,那么 A节点 也应该接受到了一次点击事件,但经过打印日志发现,这时只有 B节点 接受到了,A节点 并没有打印任何信息。

所以我想知道这是一个 BUG,还是说我方法用错了?

补充说明

上面这个问题在 Cocos Creator 3.5.2 版本中也能复现,而在 Cocos Creator 2.4.10 版本中使用相同的代码,运行效果是层顶节点和下层节点都会触发一次点击事件,当设置 event.stopPropagation() 阻止冒泡后,就能实现我需要的效果,但是在 3.6.1 和 3.5.2 中设置 event.propagationStopped = true 没有起到任何作用。

3.6.1 版本复现项目:ClickBug.zip (2.7 MB)

那就看这个SiblingIndex各自怎么变化了。假设A为0,B为1,先点A,A变为1,那么这时B会不会受影响呢?

屏幕截图 2022-10-23 222413

你看这个打印内容,一共点了三次:

  1. 默认的时候 B 在顶层,点击了 B 的任何一个位置,他都不需要改变层级。
  2. 这次点了 A(不是被遮住的位置),因为 A 在下层,所以 A 要改变层级引索,然后 A 就变成顶层了。
  3. 这次点击了 A 和 B 重叠的位置,按道理是点在了 A 上面,但是只触发了 B 的点击事件,从打印内容就能看见,这个时候 A 确实是在顶层的,但是 A 并没有触发点击事件。

不知道上述打印代码语句在哪些位置?从打印内容不能断定A没有触发点击事件。会不会出现 1<1的判断?

    onMouseDown(event: EventMouse) {
        let selfName = this.node.children[0].getComponent(Label).string;
        console.log(selfName + " 的点击事件被触发---------");
        console.log(this.node.parent.children[1].children[0].getComponent(Label).string + "在顶层, 它的 SiblingIndex 为:" + this.node.parent.children[1].getSiblingIndex());
        console.log(this.node.parent.children[0].children[0].getComponent(Label).string + "在下层, 它的 SiblingIndex 为:" + this.node.parent.children[0].getSiblingIndex());
        let nodesLength = this.node.parent.children.length;
        if (this.node.getSiblingIndex() < nodesLength - 1) {
            console.log(selfName + "需要改变 SiblingIndex 为:" + (nodesLength - 1));
            this.node.setSiblingIndex(nodesLength - 1);
        }
        else {
            console.log("不需要改变 SiblingIndex");
        }
        console.log("-------------");
    }

我觉得光看代码来 Debug 应该挺难的吧,我在上面提交了复现的项目文件,您可以下载下来试试。

感谢,解决了,但是好奇问一下,这个问题从 3.5 开始就有了,现在都还没修复,是因为这个月才发现有这个问题的吗?

试了试你提供的测试项目,感觉就是最初后添加的节点B一直在顶部(触发事件层面),即使渲染次序变化了

对的,就是改变渲染层级后,父节点的事件层级没有重新排序