给3.x的node提个设计方案


以position举例:
设置坐标 this.node.x = 50;
获取坐标 let x = this.node.x;
要emit事件 this.node.setPosition(50,100,0);

1、为什么要这样设计

a)书写方便,易上手,尤其是tween可以恢复2.x的简洁

b)性能高
x的set函数只改变坐标的值,并标记flag
舍弃了emit,因为项目中大部分改变坐标都不需要监听事件
舍弃了每次修改坐标都要对子节点进行递归,改为:
每帧提交渲染前,才从场景根节点统一递归处理所有节点的flag
这样可以避免重复计算,即便频繁修改x,y,z的值也不会影响性能

c) 如果需要监听POSITION_CHANGED,就调用this.node.setPosition(100,50);
该函数内部也仅仅是修改x,y,z、标记flag、emit事件,其他啥也不干

d)避免重复new新的Vec3对象,内存更安全
不需要覆盖_lpos,仅仅只是改值

其他scale、rotate属性同理。

POSITION_CHANGED、SCALE_CHANGED、ROTATION_CHANGED分离,不要像现在这样& TransformBit,又没有提升任何性能,不应该让用户书写麻烦又增加学习门槛

这样设计比目前的2.x 3.x U3D都更加简洁且高性能

如果是重新设计不考虑兼容性和一致性的话我觉得没有问题。

讨论过这个问题。如果这样加的话,那么可能还需要:

  • 单独设置 y
  • 单独设置 z
  • 同时设置 x, y
  • 单独 scale x
  • 单独 scale y

这样的话,和别的接口的行为就不一致。

除了渲染,其它的逻辑也可能会用到节点的世界坐标。这个得全盘梳理下才知道是否有帮助。

目前的实现多了递归子节点,其它的差不多。这个和 b 有点重复了吧。

这个具体指的是什么呢?能否贴代码说明一下?

之前这样设计估计是想尽量减少更新。比如 updateWorldTransform() 会根据哪部分修改更新哪部分。不过我们也在考虑这样带来的好处和复杂度是否是值得的。这是比较大的改动,得比较详细地测试。

1赞

这个设计应该是为了异步考虑的,如果cocos永远是单线程,那怎么写都没问题。

这个是当然的,单独设置就直接用x,y,z,统一设置或要emit就用setPosition
这样是最简洁的,而且用户可以自己选择是否需要emit
和别的接口行为是否一致,这个和简洁高性能比,根本不是事吧 :grinning:

这个确实。希望这样调整后引擎的性能会有提升。

内存更安全是指,现在必须new一个新的Vec3去覆盖position才会触发位移,而我的方案是直接改x,y,z的值,省去new新对象。

POSITION_CHANGED、SCALE_CHANGED、ROTATION_CHANGED分离一样可以哪部分修改更新哪部分,这个和写法没必然联系只是底层处理掉就可以了

讨论过这个问题。如果这样加的话,那么可能还需要:

  • 单独设置 y
  • 单独设置 z
  • 同时设置 x, y
  • 单独 scale x
  • 单独 scale y
    我觉得这个没问题啊,甚至官方可以开个帖子,就负责大家想要的一些语法糖接口。

引擎组有没有考虑分一个哥们出来,专门给大家提供语法糖,让大家写代码写的更爽一点,就算后续合并到其他分支也没啥问题吧。
比如还有node.SetAsLastSibling() node.SetAsFirstSibling()
我也知道这些大家都能自己实现,但是微信上大部分出名/排名靠前的游戏都是cocos2d游戏,搞这个3d什么的渲染什么的又没人用,2d的工具链也差强人意,让大家开发游戏更爽一点吧。

1赞

再怎么异步,没渲染你处理了也没用啊,渲染了用户肉眼才能看到,所以我说渲染之前统一处理

目前cocos的渲染和逻辑是不分离的,这个设计已经做了分离准备。

梦想还是要有的,3d是趋势,但是cocos要比U3D更简单易上手,不然现在的新人都直接去学U3D了

对于这么底层的内容,没必要投票,有几个是真能做架构师的

还是不说了。

完全不赞成 x、y、z 不触发事件和最后统一更新子级 flag 这种设计。

上一句设置父节点的位置,下一句拿子节点的世界坐标肯定得是正确的。

如果没实际注册事件的话,只是多一次判断的性能消耗吧。

即使实在不行也是单独增加 setPositionWithoutNotify 来给高级用户进行显式的性能优化。

3赞

当前帧的节点是静态的,你设置了数值,是立即更改的,但是渲染不进行更新,不存在拿不到数值的问题。

基于不分离的属性,你怎么写都没问题。

本来现在渲染就不会更新

这块不能写死

对啊,所以你说的问题跟是否最后统一更新flag没关系,而是调用updateWorldTransform接口主动更新世界坐标来解决

这个在2.x是可以拿到的吗,理论上这个会增加单帧计算量拖垮性能。

说的就是不要让普通用户主动调用 update 才能拿到正确的世界坐标。

image
你这个需求和我这个很类似啊,这个只需要修改这个,然后自己调用update就行了

你想想官方为什么要提供updateWorldTransform,就是不需要更新的时候就不去算,节省开销
如果需要自己主动调用updateWorldTransform

1赞