Unity踩坑
以下是对Unity开发过程中遇到的一些疑难杂项的记录:1. 子物体旋转后会发生形变
通过关节将两个物体相连,并且物体间在层级上也是父子关系(图2),这个时候如果让子物体旋转会出现子物体错误变形的情况(图1).
图1 子物体错误变形
图2 物体父子层级关系及关节关联关系
这种情况主要是因为父物体的scale各向相异(图3)而Unity在处理子物体的端点相关的数据时是会乘上父物体坐标系下的缩放矩阵的,因此当发生旋转时缩放轴并没有跟着旋转,因而整个图形会发生扭曲。
图3 父物体scale
所以解决方案也很明显:针对只考虑运动学的物体,可以在原有的父子物体间套一层,把子物体的缩放系数编程各向相同的,比如针对图3中的物体,可以在它和旋转的子物体间加一个空物体,空物体的scale设为(0.33333,0.5,0.3333),或(2,3,2)即保证二者相乘后x,y,z的值相同
2. 根据父类获取Component
有时候我们希望获取一类Component,比如所有种类的Collider,这个时候我们可以直接使用GetComponent<父类>()
3. LayerMask的使用
再Raycast中使用Layer时,其实它底层是用layermask的二进制形式的每一位对应一个层的开关状态。 比如我们想要第0层和第三层开启,那传入raycast的参数应该是101 也就是9
在类似于 Raycsat()中使用LayerToName()的时候需要注意,比如我们希望只检测Default层,此时我们应该这样使用:
public float dis = 10f;
//注意这里是1<<layer
Physics.Raycast(ray,out hitInfo,dis,1<<LayerMask.LayerToName(&#34;Default&#34;));但仅仅是LayerToName()适合这么用,因为它返回的是当前layer对应的层的序号,比如Default对应的层是0,所以1<<0意味着 1左移0位。但是如果这里直接使用的是LayerMask的话,就不同了,因为如果直接从Inspector对LayerMask进行赋值的话得到的就直接是一个调整好的数,比如我们设置了第四层的话那里面的数字就直接时32
public LayerMask layer
public float dis = 10f;
Physics.Raycast(ray,out hitInfo,dis , layer );4. isKinematic和Collision以及 Trigger的关系
当isKinematic发生变化时会触发一次对OnCollisionExit、OnCollisionEnter、OnTriggerExit、OnTriggerEnter的调用。
isKinematic由True变为False时会重新开启OnCollisionEnter相关的逻辑和检测并强制触发一次OnTriggerExit,但由于此时并不会影响Trigger的功能,所以如果Trigger并没有移动的话就会立马触发一次OnTriggerEnter。isKinematic由False变为True时,因为会关闭Collision相关的功能,所以会触发一次CollisionExit,同时也会触发一次OnTriggerExit。
5. 攀爬时角色动作的处理
看到了Unreal官方对Kinematic的一点讲解
当我们进行诸如爬墙动作时,可以把固定位置设置为isKinematic,然后身体的其他部分保留物理, 比如说我们把手设置为isKinematic,如图4,其余部分设置让物理计算,这样玩家再攀爬的过程中既能保证四肢是固定在墙比上的,又能使得身体的其他部分有物理效果
图4 UE4中攀爬角色各部分属性示意
6. Unity isKinematic属性的底层实现(猜测)
Unity底层对isKinematic的应用应该是直接用了PhysX提供的接口:Kinematic Actors,只要对下面的标志位进行操作就能实现物体在Kinematic和Dynamic之间的切换
PxRigidBody::setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
页:
[1]