天天看点

《Unity 4 3D开发实战详解》一6.1 刚体

本节书摘来异步社区《unity 4 3d开发实战详解》一书中的第6章,第6.1节,作者: 吴亚峰 , 杜化美 , 张月霞 , 索依娜 责编: 张涛,更多章节内容可以访问云栖社区“异步社区”公众号查看。

unity 4 3d开发实战详解

在unity内建物理引擎中,首先要介绍的是刚体(rigidbody)的概念。包含有该类组件的游戏对象,会遵循万有引力定律,在重力的作用下,使物体垂直下落。刚体组件还会影响物体发生碰撞时的反应,使物体遵循惯性定律,并在其他物体运动冲击作用下产生速度或者形变。

刚体作为物理引擎中的最基本组件,保证了所有物体受到重力的约束。unity开发平台中,对刚体设置了很多属性和变量,并对应封装了多个相关方法,下面进行分别介绍。

1.刚体属性

为了利于开发者控制物理系统,unity提供了多个属性接口。开发者可以通过更改这些参数来控制物体的物理状态。实际开发中,这些参数都被详细地罗列在属性查看器中,开发者很容易就可以对其进行更改。接下来对这些属性进行介绍。

(1)质量(mass)

该属性表示刚体的质量,其数据类型是float,默认值为1。其在属性查看器中的位置如图6-1所示。该属性的大小是有严格要求的,一般来说,大部分物体的质量属性值接近0.1才符合日常生活的感官感受,一旦超过10.0,就会失去仿真所需达到的效果。

(2)平移阻力(drag)

该属性是物体的平移阻力,其数据类型是float,初始值为0。drag属性在属性查看器中的位置如图6-2所示。在现实生活中,物体会受到各方面的影响,速度会渐渐衰减,为了模拟这一效果,unity设定了平移阻力属性。这一属性值越高,物体的速度衰减越严重。

(3)旋转阻力(angular drag)

该属性表示物体的旋转阻力,其数据类型是float,初始值为0.05。其在属性查看器中的位置如图6-3所示。当一个物体进行旋转的时候,其旋转的角速度也会受各方面影响衰减,为模拟这一现象,unity设定了旋转阻力属性。此属性值越高,物体的角速度衰减越严重。

《Unity 4 3D开发实战详解》一6.1 刚体

(4)使用重力(use gravity)

该属性表示的是该物体是否受到重力的影响,其数据类型是boolean,初始值为true。其在属性查看器中的位置如图6-4所示。这一属性被设为false时可以模拟物体在外太空状态下的失重状态。有时候也可以根据需要用于某些特殊的场合。

《Unity 4 3D开发实战详解》一6.1 刚体
注意 当该值被设定为false的时候,物体将不受重力影响,但刚体的其他特性还是存在的。

(5)是否遵循运动学(is kinematic)

该属性表示本游戏对象是否遵循牛顿运动学物理定律,其数据类型是boolean,初始值为false。其在属性查看器中的位置如图6-5所示。如果该属性被置为true,本物体的运动状态将不受外力、碰撞和关节的影响,而只受到动画以及附加在物体上的脚本的影响。

另外,虽然当该属性被置为true时物体将不受物理定律的约束,但是该物体还是会影响其他的物体,改变其他物体的运动状态。在游戏开发中此属性会被经常用到,想象一下在第一人称射击游戏中,敌人被击杀后会倒地不动,因为这个敌人对象rigidbody的is kinematic属性被设置为了true。

(6)插值(interpolate)

该属性表示的是该物体运动的插值模式。其在属性查看器中的位置如图6-6所示。在默认状态下,插值interpolate是被禁用的,可以选择interpolate模式,在此模式下物理引擎会在物体的运动帧之间进行插值,使得运动更加自然。

《Unity 4 3D开发实战详解》一6.1 刚体

不得不提的是,插值导致了物理模拟和渲染的不同步,进而产生物体轻微抖动的现象。建议在开发中,对主要角色使用插值,而其他的则禁用此功能,以达到折中效果。

(7)冻结旋转(freeze rotation)

该属性表示的是该物体的旋转是否受到物理定律的约束。其在属性查看器中的位置如图6-7所示。默认状态下任意轴的旋转是受物理定律控制的。该属性的值是修改在每个轴上的旋转属性来实现的,实际开发中可以灵活地使用。

在第一人称射击游戏中,通过此属性去除物理属性对旋转的控制,可以使玩家完全控制视角旋转。

(8)碰撞检测模式(collision detection)

该属性表示的是碰撞检测模式。其在属性查看器中的位置如图6-8所示。默认状态下,碰撞检测模式是discrete 。在没有碰撞检测的情况下,碰撞物体会穿过对方,产生所谓的“穿透”现象。为避免此类问题的发生,碰撞检测工作是必须做的。

《Unity 4 3D开发实战详解》一6.1 刚体

关于碰撞模式的选择,可选的有不连续模式(discrete)、连续模式(continuous)和动态连续模式(continuousdynamic),其中动态连续模式适用于高速运动的物体,但是耗费资源较大。连续模式仅仅可以用于球体、胶囊和盒子碰撞者的刚体,而且会严重影响物体的运动表现。所以大部分的物体采用不连续模式作为碰撞检测模式。

2.刚体变量

为了获取或者更改物体的运动状态,unity还预留了多个变量接口,这些接口使得运动处理变得相当简单。接下来将具体地介绍一下这些变量。

(1)刚体的速度(velocity)

此变量表示物体的速度值,在unity中单位1表示现实生活中的1米。在开发过程中,直接更改此变量的值并不是一种明智的做法,因为unity中物体的运动经过非常复杂的计算使得物体的运动自然平滑,如果有外加干预,会迫使物体的运动模拟失真。

下面的代码可以实现一个物体的速度骤增,以实现瞬移效果,具体代码如下:

(2)是否使用重力(usegravity)

此变量表示当前的物体是否受到重力的约束。在开发过程中,灵活地更改此变量可以达到一些特殊的场景要求,比如在外太空环境下的失重状态。

可以编写代码实现物体的失重状态,具体代码如下:

(3)冻结旋转(freezerotation)

此变量表示当前的物体的旋转是否受到物理定律的约束。通过此变量,可以更改x、y、z三个方向中的某个方向的旋转约束,以达到开发者想要达到的旋转效果。

该变量使用的具体语法代码如下所示:

(4)刚体的位置(position)

此变量表示了刚体的位置,改变此变量时,引擎会在物理阶段结束后,将物体放置到指定的位置。

下面的脚本实现了将物体放置于原点的功能,具体代码如下:

说明 这种做法不适用于旋转物体,可以使用moveposition代替。

(5)刚体的旋转(rotation)

此变量表示了物体的旋转状态,改变此变量时,引擎会在物理阶段结束后,将物体旋转到指定的状态。

下面的脚本实现了设置物体无旋转,具体代码如下:

2   rigidbody.rotation = quaternion.identity;//将物体的旋转状态设置为原始态(无旋转)

3 }

这种做法不适用于旋转物体。可以使用moverotation方法来代替。

3.刚体常用方法

在讲解了刚体的属性与变量后,有必要讲解一下unity提供的相关方法。

(1)给刚体施加力(addforce)

此方法被调用时,将会施加给刚体一个瞬时力,然后物体在力的作用下,产生一个初速度,接着物体在初速度的作用下开始运动。

下面的代码实现了对物体施加竖直向上的力,具体代码如下:

addforce方法尽量不要用在update方法中,因为这样的方法在update中会被不停地调用,与被调用一次不同,这种是模拟了一种加速度的效果。

(2)移动刚体位置(moveposition)

此方法被调用时,会使刚体按照参数移动到某个位置。此方法经常用于fixedupdate方法中。具体用法如下列代码所示:

(3)旋转刚体(moverotation)

此方法被调用时,会使刚体按照参数旋转到某个方位。此方法经常用于fixedupdate方法中。具体用法如下列代码所示:

前面的内容简单介绍了刚体的属性、变量和常用方法。接下来这一部分将讲解一下物理管理器(physics manager)的相关内容。

unity作为一个优秀的游戏开发平台,其出色的管理模式是令人称赞的。在unity中,不仅可以对单个分组进行属性设置,也可以对场景全局进行设置。这一部分讲解unity中场景的全局物理参数是如何设置的。

1.物理管理器预览

(1)打开unity开发平台,在菜单栏中选择“edit”选项,会弹出编辑列表,如图6-9所示。在编辑列表中,选择“project settings”选项,弹出全局设置列表,如图6-10所示。在全局设置列表中选择“physics”,即可进入物理管理器。

《Unity 4 3D开发实战详解》一6.1 刚体
《Unity 4 3D开发实战详解》一6.1 刚体

(2)按照第(1)步进行操作以后,会在属性查看器中呈现物理管理器编辑器,如图6-11所示。

《Unity 4 3D开发实战详解》一6.1 刚体

2.物理管理器参数

在前面的内容中,讲解了物理管理器的打开操作。接下来介绍的是物理管理器中的相关参数的含义和用法。

(1)重力(gravity)。

该属性表示的是项目中的重力加速度,该参数将被应用于所有刚体。其在物理管理器中的位置如图6-12所示,该属性3个数值分别指定在x、y、z方向上的重力加速度,一般重力是竖直向下的,所以只有y轴上有一个负值,大小默认为单位是-9.81米/(秒^2)。

(2)默认材质(default material)。

该属性表示当物体没有被指定物理材质的时候,该物体的默认材质。其在物理管理器中的位置,如图6-13所示。默认状态下是没有指定值的,因为在unity中,每个物体的物理材质可能会有很大的不同,有时候指定默认材质并不是有太大的用途。

《Unity 4 3D开发实战详解》一6.1 刚体

(3)反弹阈值(bounce threshold)。

该属性表示的是项目中的反弹阈值,该参数将被应用于所有刚体。其在物理管理器中的位置如图6-14所示,如果两个碰撞体的相对速度低于该值,那么将不会反弹。该值也用于减少抖动,所以不建议设置为很低的值。

(4)休眠速度(sleep velocity)。

该属性表示的是项目中刚体自动进入休眠时状态的速度值。其在物理管理器中的位置如图6-15所示。该值是休眠的默认线速度,低于该速度的物体将会进入休眠。如果没有这种机制,项目中的所有物体将永远都在计算中,对于资源的回收利用很不利。

《Unity 4 3D开发实战详解》一6.1 刚体

(5)休眠角速度(sleep angular velocity)。

该属性表示的是项目中的休眠角速度,该参数将被应用于所有刚体。其在物理管理器中的位置如图6-16所示,如果角速度低于该值,物体将进入休眠状态。

(6)最大角速度(max angular velocity)。

该属性表示的是项目中刚体最大的角速度值。其在物理管理器中的位置如图6-17所示,设定最大值可以避免角速度数值不稳定现象的发生。在脚本中可以用语法rigidbody.maxangular velocity来更改此值。

《Unity 4 3D开发实战详解》一6.1 刚体

(7)最小穿透禁区(min penetration for penalty)。

该属性表示的是项目中的最小穿透禁区,该参数将被应用于所有刚体。其在物理管理器中的位置如图6-18所示,该属性的具体含义是在碰撞检测器将两个物体分开前,可以穿透多少米的距离。较高的值会导致较多的物体穿透,不过可以减少抖动。

(8)求解迭代次数(solver iteration count)。

该属性表示的是项目中关节和连接计算过程中的迭代次数。其在物理管理器中的位置如图6-19所示,决定了关节和连接的计算精度。求解迭代次数越高精度越高,但是次数过高会浪费过多的资源,不利于项目的正常运行,一般来说此值设置为7就可以适用于大多数情况。

(9)射线检测命中触发器(raycasts hit triggers)。

该属性表示的是项目中的射线检测命中触发器,该参数将被应用于所有刚体。其在物理管理器中的位置如图6-20所示。如果启用,那么进行射线检测时命中碰撞体会返回一个命中消息,如果关闭,则不返回命中消息。

(10)层碰撞矩阵(layer collision matrix)。

该属性表示的是项目中的层碰撞矩阵,该参数将被应用于所有刚体。其在物理管理器中的位置如图6-21所示。定义层碰撞检测系统的行为。

《Unity 4 3D开发实战详解》一6.1 刚体
《Unity 4 3D开发实战详解》一6.1 刚体
层碰撞矩阵在后面的介绍中会有比较详细的解释,此处不再赘述。

1.碰撞的使用

与碰撞相关的内容包括碰撞器(collision)类、碰撞检测模式选择和最小穿透禁区设置,后两个内容已经在前面的内容中进行了详细的介绍,这里不再赘述。下面重点讲解一下碰撞器类及其相关方法的使用。

(1)碰撞器类的变量如表6-1所示,碰撞器有很多变量供碰撞处理使用,其中除了碰撞接触点(contacts)变量,其他变量都是只读的,读者请务必注意。

《Unity 4 3D开发实战详解》一6.1 刚体

(2)碰撞器相关方法。

碰撞触发(oncollisionenter)

此方法在碰撞发生时被系统自动调用。该方法会传递一个collision类,该类包含了碰撞点和相对速度等信息。开发者可以利用这些信息对物体进行碰撞处理,下面的代码就是一个简单的例子:

该方法只有在两个物体都遵循物理定律的情况下发生,即两者的is kinematic属性都为false。

碰撞状态(oncollisionstay)

此方法在碰撞时两物体接触过程中被调用。该方法同样会传递一个collision类,该类包含了碰撞点和相对速度等信息,下面的代码就是一个简单的例子:

退出碰撞(oncollisionexit)

此方法在碰撞时停止触碰刚体或者碰撞的时候调用。该方法同样会传递一个collision类,该类包含了碰撞点和相对速度等信息,下面的代码就是一个简单的例子:

**1 function oncollisionexit(collisioninfo : collision) { //碰撞结束

2   print("不再和" + collisioninfo.transform.name+"发生碰撞。"); //打印**碰撞结束信息

2.睡眠的使用

(1)睡眠(sleep)。

该方法被调用时,会强制一个刚体进入睡眠状态至少一帧的时间。一般用在awake方法中,设置脚本开始执行时刚体睡眠。刚体进入睡眠后,物体相当于没有刚体存在,其具体的语法如下:

(2)强制唤醒(wakeup)。

该方法被调用时,会强制使一个处于睡眠状态刚体被唤醒,其具体的语法如下:

继续阅读