[3.8.4 升级必读]:Node 的一些 set 接口行为的修正

在 3.8.4 中,对 Node.setPosition/Rotation/WorldPosition 等一些接口(没有包括所有接口)的行为有些修改。

之前的逻辑是,不管传进来的值是否和当前值相等,无脑设置,包括触发后续的回调等操作。新的接口会判断传进来的值是否相等,如果相等,那么直接返回。

对于之前在引擎外部修改 Node.worldPosition/worldScale 等返回的 readonly 属性,然后再调用引擎设置接口,这种情况将不会触发数据脏标记,导致渲染画面不更新。

比如:

// 这里直接缓存 node.worldPosition 的值
let worldPos = this.node.worldPosition;
worldPos.x = 10;

// 这里会直接返回,导致修改失效。 
//因为 worldPos 指向的就是 node 的 worldPosition,不管怎么改,setWorldPosition 在对比的时候,值都相等。
this.node.setWorldPosition(worldPos); //或者 this.node.worldPosition = worldPos;

注意:this.node.worldPosition = worldPos; 并非是引用赋值,而是走的 setter 流程,它的功能和 setWorldPosition 等效。 原型如下:

public set worldPosition(val:Readonly<Vec3>){
    this.setWorldPosition(val);
}

正确的做法应该是:

//准备一个缓存变量
private _worldPos = v3();

this.node.getWorldPosition(this._worldPos);
this._worldPos.x = 10;

this.node.setWorldPosition(this._worldPos); //或者 this.node.worldPosition = this._worldPos;

又或者:

let worldPos = this.node.worldPosition;
this.node.setWorldPosition(worldPos.x + 10, worldPos.y, worldPos.z);

其它属性(scale, rotation, color 等) 同理。

在 update 中,建议不要使用 node.worldPosition.clone(); 这样的写法,会导致内存GC和性能问题。

1赞

意思是值虽然改了 但是不会生效吗

1赞

意思是改的值和本来的不一样才会生效把,如果一样就直接返回

2赞

值是生效了,但是 Node.setWorldPosition 不只会设置 world position,还会计算 local position. 现在因为值相同返回,导致 local position 没有更改。而 Node.updateWorldTransform 会根据 local position 计算矩阵,就导致出问题了。

1赞

这个vec3的clone用起来真的很难受 干什么都要克隆 不过这么设计了 node的position是只读属性 为什么获取到通过add3f 或者别的接口更改不直接更新掉 还要在setPosition

1赞

每次都要克隆一个Vec3有点难受啊 要不给node加几个属性worldPositionX、worldPositionY、worldPositionZ

5赞

我觉得这种需要clone的,在客户代码里面很容易忽略。
要不就在接口里面加个参数 is_clone 在里面直接clone了。要不就单独加一个getPositionClone的接口。

2赞

我的代码只是片段,正常的情况是:

  • 如果是成员变量,那么只是克隆一次
  • 如果是临时使用,是这个接口
let worldPosition = node.getWorldPosition();
node.setWorldPosition(worldPosition.x + 10, worldPosition.y, worldPosition.z);
1赞

一直都是这么写的,要么clone要么单独设置,之前每次写起来感觉很别扭,现在是习惯了

1赞

能不能把x,y,width,height这些属性重定义set、get的报错去了
我改了原型一直报错
image
width、height、anchorX、anchorY直接提示废弃了不让用

1赞

还有就是 有的时候很多人做的是2d游戏在positions上用不到z 就会忘记写z 不写有按0处理了 这种问题很操蛋

2赞

参数是可选的,不知道你的具体问题是什么?

1赞

能否描述的更清楚些?谢谢。

1赞

之前看到一个帖子 有人默认的z设置了1 结果在setscale的时候没设置z 变为了0 导致了一个bug出现 具体那个帖子忘了 我看能不能找见

1赞

这个不应该吧 应该是用undefined来判断有没有传参的 :sweat_smile:

1赞

image
我重定义了Node的原型,但是编辑器会报错
image
x,y,z虽然报错但是原型修改能生效
width、height、anchorX、anchorY则不会生效,提示已弃用,只能换个别的属性名字了
我的目的是让3.x能像2.x一样,this.node.x++;this.node.width = 200;
而且移除了emit事件,如果非要emit就setPosition
width、height同理,但是引擎底层标记弃用了,导致我不能用width、height属性

2赞

不知道我理解得对不对啊。你重定义了 3.x 的 Node,然后加了 width 属性,但是无法设置。是这个意思吗?

如果是这样的话,我感觉加 width 也没有意义啊,因为引擎不会使用这个属性,那是干什么用的呢?

1赞

image
this.node.widthUT = 500;
就是直接修改节点宽度
但是由于width废弃了不让用,我只能写成widthUT了

1赞

目前的uitansform uiopacity割裂感很强 考虑到3d的部分 这样也能接受 不过这两个能不能合并起来 都是给2d对象用的

1赞

这个我好像有点印象类似的问题, 虽然不是这个 setPosition

好像 2D 中要是忽略 z 去设置缩放:比如 node.setScale(2, 2); 的话就会有问题,但是我忘记了是事件 hittest 会出问题还是啥会出问题,反正之后就一直强迫自己记住要加上 z 了。

1赞