cocos-engine icon indicating copy to clipboard operation
cocos-engine copied to clipboard

UIOpacity 里的 `_uiProps.localOpacity` 逻辑存在矛盾, 导致父节点的 opacity < 255 时, 存在一些诡异的bug.

Open finscn opened this issue 7 months ago • 1 comments

Cocos Creator version

3.8.6

System information

android

Issue description

UIOpacity 组件中 node._uiProps.localOpacity 在有些地方 只与 _opacity 有关. 有的地方 又与 _parentOpacity 相关.

opacity 的 setter 中, 只与 this._opacity 有关

    set opacity (value) {
        if (this._opacity === value) {
            return;
        }
        value = clamp(value, 0, 255);

        //  localOpacity 只与  _opacity 有关
        this._opacity = value;
        this.node._uiProps.localOpacity = value / 255;   

        if (JSB) {
            setEntityLocalOpacityDirtyRecursively(this.node, true, this._parentOpacity, false);
        }

        if (EDITOR_NOT_IN_PREVIEW) {
            setTimeout(() => {
                EditorExtends.Node.emit('change', this.node.uuid, this.node);
            }, 200);
        }
    }

但是 在 onEnable 中, localOpacity 又与 _parentOpacity 有关.

    public onEnable (): void {
        this.node.on(NodeEventType.PARENT_CHANGED, this._parentChanged, this);
        // localOpacity 与 _parentOpacity 和 _opacity 有关
        this.node._uiProps.localOpacity = this._parentOpacity * this._opacity / 255;
        if (this._parentOpacityResetFlag) {
            this._parentChanged();
            this._parentOpacityResetFlag = false;
        } else {
            this._setEntityLocalOpacityRecursively(this.node._uiProps.localOpacity);
        }
    }

于是产生一个非常奇怪的现象: 当父节点的 opacity < 255 时, 执行下面的代码

uiCmp.opacity = 100;
uiCmp.enabled = false;
uiCmp.enabled = true;

开发者并没有改变 uiCmp.opacity , 始终是100 , 只是改变 enabled ,

this.node._uiProps.localOpacity 的值却变了

Relevant error log output

No response

Steps to reproduce

.

Minimal reproduction project

No response

finscn avatar Apr 16 '25 11:04 finscn

我修改了自定义引擎的 UIOpacity 的 onEnable 方法.

    public onEnable (): void {
        this.node.on(NodeEventType.PARENT_CHANGED, this._parentChanged, this);
        const opacity = this._opacity / 255;
        this.node._uiProps.localOpacity = opacity;
        if (this._parentOpacityResetFlag) {
            this._parentChanged();
            this._parentOpacityResetFlag = false;
        } else {
            this._setEntityLocalOpacityRecursively(this._parentOpacity * opacity);
        }
    }

目前测试下来没什么问题.

finscn avatar Apr 16 '25 13:04 finscn