向官方引擎组提一个Creator3D和Creator3.0很想吐槽的设定问题,也包含bug

现在在用creator3d 和 creator3.0做项目,做项目中自然少不了使用3d物理引擎,但是在使用这两个版本的引擎过程中,遇到了很多引擎设定上难以吐槽的坎。

首先就是碰撞图层分组的问题,场景里有上百个各种类型的碰撞体,如地面,石头,建筑,角色,飞行道具等。很少有游戏不做分组,让这么多物体随便互相碰撞,所以设置碰撞分组是很有必要。

初次时用这两个引擎,我还以为碰撞分组就是按节点上的layer属性做区分的,后面经过多次试验发行,居然是由另外一个物理碰撞组设置,也就是说存在两种图层组,一种是用于渲染的,也就是节点上的layer属性,一种是碰撞用的,也就是刚体上的group属性。
如下图:



我是从unity到creator2.0用过来的,unity是只有layer这个东西,渲染和物理都是基于这个做处理,creator2.0也一样,渲染和物理共用节点的group属性,现在3d和3.0把渲染和物理的层分开管理了,虽然灵活,但是也加大了使用的复杂度。unity和creator2.0渲染和物理都共用一个层概念,也能做出各种大作,为什么到3d和3.0要分开呢,合在一起方便用户不是更好码。

即使按现在的图层和碰撞组的概念做开发,还是被现在的设定搞哭。看下面截图:


截图里的图文解释很清楚了,用刚体决定碰撞分组设定很不好,这样就导致其它一切静态物体要做碰撞分组全都要加刚体,碰撞器就无法独立存在了,必须和刚体捆绑在一起使用。最好把刚体的group属性提出到碰撞组件或者节点管理,用户一看就清楚是什么功能了,或者和layer图层合并,layer等于碰撞分组,untity和creator2.0就是这么玩的。

最后提一个3d射线无法根据图层过滤碰撞体检测射线碰撞的bug。3d和3.0两个版本都有这个问题。
我做的案例是,场景有一个地面和其它物体,地面分配图层layer为Floor,碰撞组为Floor_Hit。其它物体的图层layer为SceneObject,碰撞组为SceneObject_Hit。现在要通过鼠标检测点击到地面哪个地方,不能被其它物体阻挡射线,所以射线只检测Floor层。但是物理射线的图层过滤算法无效。
PhysicsSystem.instance.raycastClosest(ray,mask);
目前还没搞清楚射线方法的第二个参数掩码代表什么,官方文档也没解释,我自己估计不是节点的layer图层,就是刚体的group碰撞组,所以这两个情况都测试,结果什么效果都没有,检测不到射线碰撞地面。
以下是截图


测试项目
TestRaycast.zip (1.1 MB)

自己测试过很多次,可以猜到,发射射线函数的第二个参数掩码应该是和刚体的碰撞分组group属性有关的。不填第二个参数mask的时候,地面的group设置为DEFAULT可以检测到碰撞,设置为自己定义的碰撞组Floor_Hit时,mask不填或者无论怎么填都不行,这也是个很重大的bug。还有如果官方设定射线分组检测碰撞是根据刚体的group属性判断的话,那么所有静态物体都要加刚体,包括:地面,空气,宇宙。毕竟实际开发中使用射线时,80%的情况都会用到射线分组检测碰撞。

最后衷心希望引擎官方能重视这个节点图层和刚体碰撞组的设定体验很差的问题吧

0b1代表default层,依次0b10是下一层,如果检测这两层就填0b11

现在是关键问题是设置掩码没用啊
只要刚体的group属性设置了自己定义的Floor_Hit层,我把掩码mask设置为默认值0xffffffff都没用,
PhysicsSystem.instance.raycastClosest(ray,0xffffffff)
按理说这个值是能检测所有碰撞组的。但是检测不到射线碰撞,只有设置为default才行,这样就无法分碰撞射线检测了。
射线demo已经上传,你可以自己测试一下看。
或者你自己写一个demo,看能不能做得到按自己定义的碰撞组掩码检测射线碰撞。

正常啊,你需要吧default层和其他层的检测打开啊

怎么打开,设置面板里还是刚体?

捕获 就是这个,ray在default层,你不打开和其它层检测当然检测不到了

按你的设置可以了,但是官方文档上的“物理射线章节”居然没解释和备注有射线属于DDEFAULT层,也没有写如何分层射线检测,这文档写得太过敷衍了吧,让用户去猜怎么用。

但是让射线属于哪个层这个设定真的好吗?
假如我的角色是Default层,敌人是Enemy层,我不想让这两个对象做物理碰撞,所以在物理设置面板里设置这两个层不能碰撞,这时我又想通过鼠标用物理射线检测是否点击到敌人,由于这两个层已经设置不能碰撞,而射线又是默认属于Default层,射线检测无效,这样我永远点击不到敌人。

射线是个抽象的东西,就不该属于碰撞层,可以自由选择和哪些层做物理检测。
官方引擎组可以参考一下unity的物理射线怎么用,别人写的射线就是可以自由选择和哪些层进行碰撞,射线本身没有层的概念,方便易用。

写引擎就该怎么方面用户去使用,不应该被概念束缚,因为物理碰撞需要层,所以给射线也强行加上层的概念,最后搞出很多让用户难以理解的东西。

最后还是前面哪个问题,因为碰撞层需要刚体做支持,导致了像“地面”这种静态物体必须要加刚体才能做分层射线检测,真是无力吐槽。

官方出来解释一下,像Unity中的Tag多好,简简单单

对于tag我目前通过节点名字做判断,节点名字后面加下划线和tag名,数量多的时候有100个以上只能含泪一个一个写。检测时先对节点名字做下划线字符串分割,判断第二个字符串的tag值是什么。

关键是场景是美术建立的,命名都是有一定规范的,程序不可能再去修改一遍场景中物体节点名称,Unity中直接多选一类物体批量的设置Tag然后代码中通过这个Tag去检测,这样才对吧,但是Cocos就很难实现这个功能,真的是烦,一会mask,一会Group,一会layer,文档写的也是一塌糊涂。

我也是从unity过来的,很多东西用unity的概念来理解cocos就会陷入坑里,虽然他们结构比较相像。在unity的检测碰撞的mask就是指layer,在cocos里用的时候我把layer的值设置给mask半天没效果,后面才知道有个叫group的东西是专门做物理碰撞分组的,和layer是两个独立的东西。如果用射线,单独设置group还不行,还要设置default层是否和要检测的层能够碰撞,因为射线也是有层的概念的,属于default(既然已经有mask做分层检测了为什么还要给射线默认加个层,没想明白),而这些东西官方文档完全没有写。在unity里简单能实现的一个功能,在cocos里要绕1天找原因。


从creator3d的第一个版本到现在的creator3.0已经一年半了,项目设置里图层解释这个问题怎么没人发现,解释得很清楚Layer层可以做物理射线检测,但是却不行,射线检测的mask只认Physics设置的Group。真是误人啊。

cocos引擎组需要一个好的产品经理,不然做出来的东西,功能实现了,用起来很费劲

@JayceLai

sorry,后面加上物理分组后,这里的文案就不对了。
一开始确实是使用 layer 控制的。后来加了物理碰撞分组后,就拆分出去了。

物理碰撞分组没必要分出去啊,公用layer就可以了,unity就这么做的,别人做了这么多年开发都没问题。你现在分出去了,要管理两个层(layer层和group层),管理难度变大了,我现在用creator3d开发,只能先在layer层命名一次名字,然后再在group层按layer的顺序和名字重复再命名一次,降低管理难度。layer和group还是合在一起好,不然那些从unity或laya转过来的,根本就看不懂你们的设定,很快就放弃了。

1赞

之前也有一樣的問題,後來才發現分組竟然不是用layer分組,而是從剛體分組。
原本用不到剛體的為了分組都必須加上剛體。

简单有简单的好处,复杂有复杂的好处。之前 2.0 还有人吐槽呢。Unity 也有人吐槽渲染和物理必须用同一个分组,看看这个帖子 https://forum.unity.com/threads/separate-physics-and-rendering-layers.505580/ Unity 官方也认可了 layer 分离的方案,并且将会改进。

看了一下核心反馈的问题是物理碰撞组和渲染 layer 的拆分,对渲染 layer 进行分组和对物体的碰撞进行分组的目标完全不同,很可能同样的 layer 需要不同的碰撞组,这种情况下会加大 camera visibility 和 layer 设置的复杂度。假设 layer 和碰撞组是相交的情况,比如

节点 A:场景渲染组,物理是地面,B:场景渲染组,物理是场景中的物体,C:角色渲染组,物理是敌人,D:角色渲染组,物理是主角。

那么不拆分的情况下就需要下面几个 layer

  1. 场景地面
  2. 场景物体
  3. 角色敌人
  4. 角色主角

才能做到比较好得控制渲染和物理,复杂度很高。

加上 layer 掩码给用户的只有 20 位(共 32 位,12 位保留给引擎内部),在大项目中如果物理和渲染分组都比较复杂的情况下,一定会不够用。这是我们拆分的核心原因

我不太明白,用不到刚体就不用物理分组了,加了分组就肯定是用到了物理,那么刚体也是必然会加的。
前面有一个论点是如果集合在节点中设置,就不需要加刚体组件,那是需要引擎底层分析你的组是否需要物理刚体,需要的话主动加上的,该有物理表现的一定会有刚体组件,并没有省掉任何的开销。我们也希望这种开销是显式可注意到的

但是文档方面我们确实做得很不够,还需要加强,把这些改动都说清楚,很抱歉

其实你把问题想复杂了。

一,同一个layer有不同的碰撞组这个问题:

  1. 场景地面 layer: floor
  2. 场景物体 layer: sceneobject
  3. 角色敌人 layer: enemy
  4. 角色主角 layer: player

同一个layer的目的是可以用相同的摄像机渲染,如果这4个物体在不同的层,也可以做到用同一个摄像机渲染,设置摄像机的渲染层掩码就行。剩下的就是相同摄像机下的不同碰撞组,就按layer的碰撞关系处理,完全能解决你说的不拆分碰撞组遇到的问题。你现在拆分碰撞组唯一的用处是,相同碰撞组的物体可以选择用不同摄像机渲染,但是从游戏的角度思考,市面上有哪款游戏有物理交互的多个物体不是用同一个摄像机渲染的,用多个摄像机分别渲染相同碰撞组不同物体的情况几乎就没有,就算有也是运行效率低,画面怪异(因为每个摄像机位置不同)。为了这么一个几乎不存在的用法去拆分碰撞组增加管理难度不值得吧。

二,还有你说的 layer 掩码只有20位,怕不够用。
可能你做引擎时间比较长,没经历过多少实际游戏里的应用。
在游戏开发过程中,并不是什么物体都要做分层的,只有那些要多摄像机渲染和做物理分层碰撞时才会用的上,就算分层,很多相同类型的一类物体都可以用同一个层。我搞u3d也好几年了,无论自己开发的项目还是看别人的项目源码, 一个项目里能用超过10个层就很不错了,就算破天荒会用超过20位掩码,这个完全可以在代码运行过程中动态去修改节点的layer,在不需要掩码处理的时候暂时设位default,用到时手动设置其它图层。

我觉得还是没必要为一个很低概率用到的情况去做渲染层和碰撞层拆分