Skip to content

修正 UIOpacity 组件 在处理 localOpacity 和 _parentOpacity 时的若干错误 #18623

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: v3.8.7
Choose a base branch
from

Conversation

finscn
Copy link
Contributor

@finscn finscn commented Apr 16, 2025

当 onDisable 时, _parentOpacity 需要还原为 1 .
当 触发_parentChanged() 时, 如果父节点不存在 , _parentOpacity 也需要还原为 1 .

否则 下次执行 UIOpacity 的 onEnable() 时, 还是用的之前的 _parentOpacity .

    public onEnable (): void {
        this.node.on(NodeEventType.PARENT_CHANGED, this._parentChanged, this);

        // 这里用的还是 之前的 this._parentOpacity . _parentOpacityResetFlag 并没有发挥什么作用.
        this.node._uiProps.localOpacity = this._parentOpacity * this._opacity / 255;

        if (this._parentOpacityResetFlag) {
            this._parentChanged();
            this._parentOpacityResetFlag = false;
        } else {
            this._setEntityLocalOpacityRecursively(this.node._uiProps.localOpacity);
        }
    }

另外 , onEnable 中, this.node._uiProps.localOpacity = this._parentOpacity * this._opacity / 255 这行本身就存在错误.
#18624 在这里有讨论.

这个 PR 用来解决下列 BUG (原生平台):

父节点A  opacity = 100
父节点 B opacity = 255.
父节点A下包含一个正在播放的 Spine 动画节点.
此时 将 Spine 动画节点移动到 父节点B 下,  这个动画仍然会呈现半透明状 (会受到父节点 A的 opacity = 100 的影响).

此 bug 并非必现,取决于 spine 动画的某些特质 和 移动节点的时机 以及整个节点树的层级影响.
我实际项目中结构比上面的描述要复杂一些. 而且用到的节点池.

将某些spine 动画用完了,放到池子里, 下次从池子里取出并使用时 ,我发现某些动画会呈现半透明.
于是研究了一下, 当spine 动画节点放回到池子里时,它的父节点是半透明的, 即使放到池子里时, 我已经设置了spine 节点的 parent=null, 仍然会出现下次使用时, 透明度不正确的情况,
于是顺着这个线索研究了一下, 得到了此 PR里的结论.

根本原因还是 localOpacity 和 _parentOpacity 的错乱造成的.

Re: #

Changelog


Continuous Integration

This pull request:

  • needs automatic test cases check.

    Manual trigger with @cocos-robot run test cases afterward.

  • does not change any runtime related code or build configuration

    If any reviewer thinks the CI checks are needed, please uncheck this option, then close and reopen the issue.


Compatibility Check

This pull request:

  • changes public API, and have ensured backward compatibility with deprecated features.
  • affects platform compatibility, e.g. system version, browser version, platform sdk version, platform toolchain, language version, hardware compatibility etc.
  • affects file structure of the build package or build configuration which requires user project upgrade.
  • introduces breaking changes, please list all changes, affected features and the scope of violation.

当父节点不存在时,  _parentOpacity 需要还原为 1 .

否则 下次执行  UIOpacity 的 onEnable() 时, 
还是用的之前的  _parentOpacity .

```ts
    public onEnable (): void {
        this.node.on(NodeEventType.PARENT_CHANGED, this._parentChanged, this);

        // 这里用的还是 之前的 this._parentOpacity . _parentOpacityResetFlag 并没有发挥什么作用.
        this.node._uiProps.localOpacity = this._parentOpacity * this._opacity / 255;

        if (this._parentOpacityResetFlag) {
            this._parentChanged();
            this._parentOpacityResetFlag = false;
        } else {
            this._setEntityLocalOpacityRecursively(this.node._uiProps.localOpacity);
        }
    }
```
Copy link

github-actions bot commented Apr 16, 2025

Code Size Check Report

Wechat (WASM) Before After Diff
2D Empty (legacy pipeline) 1006139 bytes 1006097 bytes 👍 -42 bytes
2D All (legacy pipeline) 2668665 bytes 2668623 bytes 👍 -42 bytes
2D All (new pipeline) 2756873 bytes 2756831 bytes 👍 -42 bytes
(2D + 3D) All 10010462 bytes 10010420 bytes 👍 -42 bytes
Web (WASM + ASMJS) Before After Diff
(2D + 3D) All 16924878 bytes 16924836 bytes 👍 -42 bytes

Interface Check Report

This pull request does not change any public interfaces !

@finscn finscn changed the title ui-opacity.ts: 父节点不存在时, 需要 还原 _parentOpacity. 修正 UIOpacity 组件 在处理 localOpacity 和 _parentOpacity 时的若干错误 Apr 16, 2025
const render = this.node._uiProps.uiComp as UIRenderer;
if (render && render.color) { // exclude UIMeshRenderer which has not color
render.renderEntity.colorDirty = true;
render.renderEntity.localOpacity = opacity;
render.node._uiProps.localOpacity = opacity;
// render.node._uiProps.localOpacity = opacity;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

render.node._uiProps.localOpacit 等价于 this.node._uiProps.localOpacity.

而 this.node._uiProps.localOpacity = opacity; 无论是否有 render 都需要被执行,
所以 移到前面去执行.

@@ -229,18 +233,20 @@ export class UIOpacity extends Component {

public onEnable (): void {
this.node.on(NodeEventType.PARENT_CHANGED, this._parentChanged, this);
this.node._uiProps.localOpacity = this._parentOpacity * this._opacity / 255;
const opacity = this._opacity / 255;
this.node._uiProps.localOpacity = opacity;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

在 非 JSB 环境, localOpacity 只与 this._opacity 有关.

}
}

public onDisable (): void {
this.node.off(NodeEventType.PARENT_CHANGED, this._parentChanged, this);
this.node._uiProps.localOpacity = 1;
this._setEntityLocalOpacityRecursively(this.node._uiProps.localOpacity);
this._parentOpacity = 1;
this._setEntityLocalOpacityRecursively(1);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里直接用 1 就行. 没必要再执行那么长的代码

if (this._parentOpacityResetFlag) {
this._parentChanged();
this._parentOpacityResetFlag = false;
} else {
this._setEntityLocalOpacityRecursively(this.node._uiProps.localOpacity);
this._setEntityLocalOpacityRecursively(this._parentOpacity * opacity);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_setEntityLocalOpacityRecursively 内的逻辑只有 jsb环境 才会被执行.
JSB 环境 下 此处需要传入 this._parentOpacity * this._opacity / 255

@finscn finscn mentioned this pull request Apr 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant