2018-08-27 20:19:16 loongkingwhat 阅读数 1835

写在前面
阅读该文章之前,首先需要知道:
1.不同坐标系(世界坐标系、物体坐标系、惯性坐标系)之间的联系和区别;可参考博客坐标系详解
2.同一个物体基于不同的坐标系进行旋转所得结果不一样;

本文的目的是探究游戏引擎Unity3D不同的旋转API的表现,我们都知道,在Unity3D中有多种刚体旋转的API:①有对localRotation进行赋值修改的方式达到旋转的目的;②有通过Rotate方法(Space.Self)进行旋转的;③对应还有通过Rotate方法(Space.World)进行旋转的。按照网上一些教程的解释,①就是在父节点坐标系下进行旋转,②和③则分别是绕物体坐标系和世界坐标系的轴进行旋转。

在理解世界坐标系、物体坐标系和惯性坐标系的基础上,非常有必要明确各个API定义的刚体旋转到底是如何进行的,是基于世界坐标系还是基于世界坐标系平移之后的惯性坐标系;基于父节点的局部坐标系进行旋转,是否需要将父节点的物体坐标系平移到本物体坐标系原点之后再进行旋转。

这部分的内容在其他的博客或者资料中是没有详细讲解的,通常默认大家是已知的,但是这种不明确容易造成对API理解不深而使用错误的情况。这篇博客主要探究这部分的问题。

(一)Unity 3D绕轴旋转

本文之后的示例都将使用下图中的实例,以研究小臂这一段刚体为代表,去研究刚体在Unity中的旋转。

值得注意的是,人体关节刚体与普通的几何物体刚体在物体坐标系上有一定的差别。常见的几何刚体(例如立方体,球体,圆柱体)的物体坐标系的原点都在几何刚体的中心点,而人体关节刚体的物体坐标系原点一般在关节的某一端。例如,小臂关节的物体坐标系的原点就在肘关节,大臂关节的物体坐标系的原点在肩关节附近。

此处选用物体坐标系原点位于物体某一端点的例子去讨论,更加直观。
这里写图片描述

1.transform.localRotation属性控制刚体旋转

API手册中Description 描述
The rotation of the transform relative to the parent transform’s rotation.
该变换的旋转角度相对于父级变换的旋转角度。
·
Unity stores rotations as Quaternions internally. To rotate an object, use Transform.Rotate. Use Transform.localEulerAngles for modifying the rotation as euler angles.
Untiy使用四元数来存储旋转角度。要旋转一个物体,可以使用Transform.Rotate,也可以使用Transform.localEulerAngles为设置作为欧拉角的旋转角度。

这个API解释对不熟悉Unity3D和图形学的同学来说,看到就会觉得什么都说了,什么都没说。看懂了也不太会用。下面来做具体的测试看看到底这个API是怎么在父坐标系下控制刚体旋转的。

通过以下代码控制人物:

    GameObject upperarm_l;
    GameObject lowerarm_l;
    public float Local_X =0.0f;
    public float Local_Y = 0.0f;
    public float Local_Z = 30.0f;

    // Use this for initialization
    void Start () {
        upperarm_l = GameObject.Find("upperarm_l");
        lowerarm_l = GameObject.Find("lowerarm_l"); 
    }

    // Update is called once per frame
    void Update () {
        lowerarm_l.transform.localRotation = Quaternion.Euler(Local_X, Local_Y, Local_Z);
    }
}

这里写图片描述
从图中可以看出结论,rotation of the transform relative to the parent transform's rotation的意思就是子物体的物体坐标系相对于平移之后父物体物体坐标系之间的旋转角度。读起来可以很绕,解释以下主要是两个点。首先,父物体的物体坐标系要平移,使得父子两个物体坐标系的坐标原点重合;然后,旋转rotation是父子两个物体坐标系之间的关系,也就是说,欧拉角(或者四元数)描述的是如何旋转父物体坐标系,会使得其与子物体坐标系重合。以上就是API手册中英文解释的全部意思。

当然,把父物体的坐标系作为参考系,localRotation这个属性也描述了子物体坐标系的旋转角度。所以,通过给这个属性赋值,可以达到控制刚体旋转的目的。

2.transform.Rotate()中的Space.Self和Space.World

transform.Rotate是正儿八经用来控制刚体旋转的方法,其参数除了欧拉角之外,还有一个可选参数Space.Self/Space.World,默认是前者。在API手册中对这两个的解释也不是特别清晰。下面我们来进行简单的梳理和理解。
下面两张图片载自大佬博客,可以通过看图直观理解Space.Self和Space.World的区别和联系。联系就是两者都是将自身的物体坐标系进行旋转。区别在于旋转的参考系不一样。前者(Space.Self)的参考系是旋转前一刹那时的自身物体坐标系;而后者(Space.World)是评议之后的世界坐标系。此处注意仍然是平移之后的世界坐标系(经过平移,与物体坐标系坐标原点重合的世界坐标系又称惯性坐标系),不懂可以参考博客坐标系详解

左图和右图都是绕Y轴进行旋转。左图是Space.Self参数控制下的情况,可以看到圆柱体是绕本地坐标系的Y轴进行旋转的。右图是Space.World参数控制下的情况,可以看出圆柱体是绕惯性坐标系(平移之后的世界坐标系)进行旋转的。
这里写图片描述这里写图片描述

(二)结论总述

1.在Unity 3D中控制刚体旋转的主要方法可以分为三个类别:①以父物体的物体坐标系为参考系进行旋转;②以世界坐标系为参考系进行旋转;③以自身物体坐标系为参考系进行旋转。当然还有绕点旋转和绕轴旋转,这些此处暂不讨论。

2.不论是以哪一个坐标系为参考系进行旋转,都需要在旋转之前把参照系平移,使得参照系与带旋转物体的物体坐标系坐标原点重合

3.旋转的欧拉角是两个坐标系之间的旋转角度,具体来说就是将参照系旋转到和物体坐标系重合需要的欧拉角。

2018-08-23 18:23:05 qq_38061677 阅读数 2058

这里写图片描述
1.1
Mass表示物体的质量,数值类型为float,默认值为1。大部分物体的质量属性接近于0.1才符合日常生活感官感受,超过10 ,则失去了仿真效果。
2.2
Drag表示平移阻力,其数值类型为float,初始值为0,用来表示物体因受阻力而速度衰减的状态。
3.3
Angular Drag 旋转阻力,其数值类型为float,初始值为0.05,用于模拟物体因旋转而受到的各方面的影响的现象。
4.4
Use Gravity使用重力,表示物体是否受到重力影响,其数据类型是boolean ,初始值为true,该属性设置为false时用来模拟失重现象。
5.5
Is Kinematic是否遵循运动学,该属性表示对象是否遵循牛顿运动学物理定理,其数据类型是boolean ,初始值为false。如果该属性设置为true表示该物体运动状态不受外力,碰撞和关节的影响,而只受到动画以及附加在物体上的脚本影响,但是该物体仍然能改变其他物体运动状态,例如游戏中倒下的敌人始终不动 ,就是利用这个属性 。
6.6
Interpolate 插值,还属性表示的是该物体运动的插值模式,默认状态下是被禁用的。选择该模式时,在此模式下物理引擎会在物体的运动帧之间进行插值,使得运动更加自然。另外插值导致了物理模拟和渲染的不同步,进而产生物体轻微抖动现象,建议可以对主要角色使用插值,而其他的则禁用此功能,以达到折中的效果。
None表示没有插值,Interpolate表示根据上一桢的位置来做平滑插值,Extrapolate表示根据预测的下一桢的位置来做平滑插值

7.7
Freeze Rotation冻结旋转,该属性表示的是该物体的旋转是否受到物理定理的约束。默认状态下任意轴的旋转是受物理定律控制的,该属性的值是修改在每个轴上的旋转属性来实现的。例如在第一人称射击游戏中,通过去除该属性的控制,可以使玩家完全控制视角旋转。
8.8
Collision Detection碰撞检测模式,默认状态时Discrete。在没有发生碰撞检测的情况下,碰撞物体会穿过对方,产生所谓 穿透现象。碰撞模式有不连续模式(Discrete),连续模式(Continuous)和动态连续模式(ContinuousDynamic),动态连续模式适用于高速运动的物体,连续模式仅仅可以用于球体,胶囊和盒子碰撞者的刚体,而且会严重影响物体的运动表现,因此大部分采用不连续模式。
Continuous Collision Detection

CCD用来防止快速移动的物体穿过其他对象。

当使用默认的离散式碰撞检测时,如果前一桢时对象在墙这一面,下一桢时对象已到到了墙另一面,那么碰撞检测算法将检测不到碰撞的发生,你可以将该对象的碰撞检测属性设置为Continuous,这时碰撞检测算法将会防止对象穿过所有的静态碰撞体,设置为Continuous Dynamic将还会防止穿过其他也设置为Continuous或者Continuous Dynamic的刚体。

2016-06-11 10:51:00 weixin_30693183 阅读数 45

一般一个物体除了手动添加刚体受到重力作用外,还可以给该刚体添加一个其他的力。

这里就要涉及到一个恒定力(Constant Force)组件

首先要去掉物体的重力(因为重力是刚体组件中默认的一个向下的力)影响。然后在力组件中添加一些力去控制该物体。

转载于:https://www.cnblogs.com/sunxun/p/5574886.html

2016-10-17 14:26:00 weixin_30413739 阅读数 6
 

刚体(Rigidbody)的官方(摘自Unity3d的官方指导书《Unity4.x从入门到精通》)解释如下:

Rigidbody(刚体)组件可使游戏对象在物理系统的控制下来运动,刚体可接受外力与扭矩力用来保证游戏对象像在真实世界中那样进行运动。任何游戏对象只有添加了刚体组件才能受到重力的影响,通过脚本为游戏对象添加的作用力以及通过NVIDIA物理引擎与其他的游戏对象发生互动的运算都需要游戏对象添加了刚体组件。

个人理解就是刚体是用来模拟物体受到一个力作用时候的表现,这个从刚体中的参数就可以看出:

全是关于物体受到力之后,怎么运动的参数,比如Mass质量,Drag阻力。

 

碰撞体的官方(摘自Unity3d的官方指导书《Unity4.x从入门到精通》)解释如下:

碰撞体是物理组件的一类,它要与刚体一起添加到游戏对象上才能触发碰撞。如果两个刚体相互撞在一起,除非两个对象有碰撞体时物理引擎才会计算碰撞,在物理模拟中,没有碰撞体的刚体会彼此相互穿过。

 

个人是这样理解的,为什么要判断碰撞,判断碰撞就是需要计算力,无论是阻力也好,动力也好,如果此时物体有刚体组件,那么物体就会在力的作用下运动。如果这个物体没有刚体,那么碰撞产生的力就没有任何意义了,那计算碰撞也就没有任何意义了。

所以,我们可以推断出,如果两个碰撞体都没有刚体组件,那么这两个物体即使相互发生了碰撞,那么也不会有碰撞事件的。

 

官网上的碰撞的图如下(注:据说是官网的图,我在网上很多地方看到了,但我目前为止还没找到在官网的哪个位置哈):

 

从上面的图中我们看出来碰撞的双方中一定要有一个Rigidbody存在,并且碰撞双方必须都要有碰撞体组件。

 

但做实验的时候发现了一个很诡异的事情,就是发生碰撞的主体一定是要带刚体的,即只有带刚体的碰撞体去撞其他碰撞体时,双方才会收到碰撞事件,以下是我做的实验:

一、控制A(刚体加碰撞体)撞击 静止的B(只有碰撞体),双方能收到碰撞事件。

二、控制B(只有碰撞体)撞击 静止的A(刚体加碰撞体),双方收不到碰撞事件。

三、让A(刚体加碰撞体)自由下落,然后控制B(只有碰撞体)去撞击A,双方能受到碰撞事件。

 

得出的结论似乎是如果碰撞双方只有一个有刚体,那么那个刚体一定要处于运动的状态下才会有碰撞事件发生。

 

接下来就是IsTrigger选项了,上面的情况都没有触发信息,先列举一下触发事件和碰撞事件,如下:

 

触发信息检测: 1.MonoBehaviour.OnTriggerEnter(  Collider other )当进入触发器

                     2.MonoBehaviour.OnTriggerExit(  Collider other )当退出触发器

                     3.MonoBehaviour.OnTriggerStay(  Collider other )当逗留触发器
碰撞信息检测: 1.MonoBehaviour.OnCollisionEnter(  Collision collisionInfo ) 当进入碰撞器

                     2.MonoBehaviour.OnCollisionExit(  Collision collisionInfo ) 当退出碰撞器

                     3.MonoBehaviour.OnCollisionStay(  Collision collisionInfo )  当逗留碰撞器

 

触发器触发条件:

1、必须都要有碰撞器组件(Collider),其实上面的碰撞事件同样也需要这个前提条件。

2、必须有一个物体带刚体组件,并且处于运动状体中(包括主动运动去撞击别人和在运动过程中被别人撞击)。

3、两个碰撞器中至少有一个开启了IsTrigger。

 

此外还有两点:

一、产生触发事件的两个物体会相互穿越,准确的说是因为开启IsTrigger那个物体会被物理引擎锁忽略掉,所以会产生两个物体穿越的情况。

二、两个对象要么都收到碰撞事件,要么都收到触发事件,不会出现一个收到触发事件,一个收到碰撞事件的情况。

 

还有一个经验点就是,在控制一个物体A去撞另一个物体B时,不要直接去修改物体A的Transform的position属性,因为你会发现如果即使两者发生了碰撞也还是会穿越的,原因就在于我们是直接设置的坐标,如果物体A有刚体组件的话,应该用AddForce,给物体添加一个力,然后让物理引擎去让物体动,此时如果发生了碰撞的话,就不会穿越了。

unity3d中的碰撞器和触发器的区别?
 
碰撞器是触发器的载体,而触发器只是碰撞器身上的一个属性
当Is Trigger=false时,碰撞器根据物理引擎引发碰撞,产生碰撞的效果,可以调用OnCollisionEnter/Stay/Exit函数;
当Is Trigger=true时,碰撞器被物理引擎所忽略,没有碰撞效果,可以调用OnTriggerEnter/Stay/Exit函数。
 
如果既要检测到物体的接触又不想让碰撞检测影响物体移动或要检测一个物件是否经过空间中的某个区域这时就可以用到触发器
 
例子:
碰撞器:汽车被撞飞、皮球掉在地上又弹起效果
触发器:人站在靠近门的位置门自动打开效果

转载于:https://www.cnblogs.com/qiaogaojian/p/5969634.html

Unity3D中的刚体运动

阅读数 2931

没有更多推荐了,返回首页