关于Unity中Rigidbody组件的各个变量的含义

本文详细介绍了Unity中刚体组件的使用方法及其属性,包括质量、阻力、重力使用等,并探讨了刚体与变换控制的区别及动画与物理控制的结合。

刚体能让你的游戏对象被物理引擎所控制,它能通过受到推力和扭力来实现真实的物理表现效果。所有游戏对象必须包含刚体组件来实现重力、通过脚本施加力、或者与其他对象进行交互,这一切都通过NVIDIA的PhysX物理引擎来实现。


4.jpg


属性

Mass 质量,单位为Kg,建议不要让对象之间的质量差达到100倍以上

Drag 空气阻力,为0表示没有阻力,infinity表示立即停止移动

Angular Drag 扭力的阻力,数值意义同上

Use Gravity 是否受重力影响


Is Kinematic 是否为Kinematic刚体,如果启用该参数,则对象不会被物理所控制,只能通过直接设置位置、旋转和缩放来操作它,一般用来实现移动平台,或者带有HingeJoint的动画刚体


Interpolate 如果你的刚体运动时有抖动,尝试一下修改这个参数,None表示没有插值,Interpolate表示根据上一桢的位置来做平滑插值,Extrapolate表示根据预测的下一桢的位置来做平滑插值


Freeze Rotation 如果选中了该选项,那么刚体将不会因为外力或者扭力而发生旋转,你只能通过脚本的旋转函数来进行操作

Collision Detection 碰撞检测算法,用于防止刚体因快速移动而穿过其他对象


Constraints 刚体运动的约束,包括位置约束和旋转约束,勾选表示在该坐标上不允许进行此类操作


详细描述

刚体让你的游戏对象处于物理引擎的控制之下,这打开了实现真实碰撞,各种连接类型,以及其他各种效果的大门。通过给刚体施加外力来移动它,与以前的通过设置其位置变换来移动它有非常大的不同。通常情况下,你不会同时操作刚体和变换,你只会使用其中之一。


这两者之间最大的差异在于力(Forces)的使用,刚体能接受推力和扭力,变换不可以。变换同样可以实现位置变化与旋转,但这与通过物理引擎来实现是不一样的。给刚体施加力来移动他的时候同时也会影响对象的变换数值,这也是为什么只能使用这两者之一的原因,如果同时直接操作了刚体的变换,那么在执行碰撞和其他操作的时候会出问题。


你必须显示的将刚体组件添加到你的游戏对象上,通过菜单项 Component -> Physics -> Rigidbody即可添加,之后对象就处于物理引擎控制之下了,他会受到重力的影响而下落,也能够通过脚本来受力,不过你可能还需要添加一个Collider或者Joint来让他表现的更像你所期望的。


Parenting

当一个对象处于物理引擎控制之下,他的运动将会与其父对象的移动半独立开。如果你移动任意的父对象,他们将会拉动刚体子对象,然而,刚体在重力及碰撞影响下还会下落。


Scripting

控制刚体的方法主要是通过脚本来施加推力和扭力,通过在刚体对象上调用AddForce()和AddTorque()方法。再次注意,当你使用物理引擎来控制刚体的时候,不要直接操作对象的变换数值。


Animation

在某些时候,主要是创建纸娃娃效果的时候,你可能需要在动画与物理控制之间进行切换。你可以将刚体设置为IsKinematic,当设置为Kinematic模式,它将不再受到外力影响。这时你只能通过变换方式来操作对象,但是Kinematic刚体还会影响其他刚体,但他自己不会再受物理引擎控制。比如,连在Kinematic刚体上的Joints还会继续影响连接的另一个非Kinematic刚体,同时也能够给其他刚体产生碰撞力。


Colliders

碰撞体是另一类必须手动添加的的组件,用来让对象能够发生碰撞。当两个刚体接触到一起的时候,除非两个刚体都设置了碰撞属性,否则物理引擎是不会计算他们的碰撞的。没有碰撞体的刚体在进行物理模拟的时候将会简单的穿过其他刚体。


5.jpg


Composed Colliders

由多个基本的碰撞体对象组合而成,扮演一个独立的碰撞体对象。当你有一个复杂的模型,而你又不能使用Mesh Collider的时候就可以使用组合碰撞体。


6.jpg


Continuous Collision Detection

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


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


CCD只支持Box,Sphere和Capsule的碰撞体。


Use The Right Size

当使用物理引擎的时候,游戏对象的大小比刚体的质量更重要。如果你发现刚体的行为不是你所期望的,比如移动的太慢,漂浮,或者不能正确的进行碰撞,尝试一下修改你的模型的缩放值。Unity的默认单位是1 unit = 1 米,物理引擎的计算也是按照这个单位来的。比如,一个摩天大楼的倒塌与一个由积木搭成的玩具房子的倒塌是完全不一样的,所以,不同大小的对象在建模时都应该按照统一的比例。


对于一个人类角色模型来说,他应该有2米高。可以创建一个Box来作为参照物,默认的Box为1米,所以一个角色应该是Box的两倍高。


当然,你也可以通过修改导入模型的缩放来调整比例,如果你不能直接修改模型本身的话。在Project面板中选中模型,调整其Importer属性,注意不是变换里的缩放。


如果你的游戏需要你实例化具有不同缩放值的对象,你也可以调整变换里的缩放值,但是物理引擎来创建这个对象的时候会额外多做一点工作,这可能会引起一点性能问题。


这个问题不会太严重,但性能显然会比上面两种方法低。


同样要注意的是,non-uniform scales也会引起一些问题,如果这个对象具有父对象的话。基于以上原因,尽可能的在制作模型的时候就按照Unity的比例来建模。


Hints

两个刚体的相对质量决定他们在碰撞的时候将会如何反应。


给刚体设置更大的质量并不会让它下降的更快,如果要实现这个目的,使用Drag参数。


低的阻力值使得对象看起来更重,高的阻力值使对象看起来更轻。


典型的Drag值介于0.001(固体金属)到10(羽毛)之间。


如果你想同时使用变换和物理来控制对象,那么给他一个刚体组件并将其设置为Kinematic


如果你通过变换来移动对象,同时又想收到对象的碰撞消息,那么必须给他一个刚体组件。


Mass(质量):
学过物理的同学们都知道的吧,质量越大,惯性越大。这里的单位可以自己统一规定,但是官方给出的建议是场景中的物体质量最好不要相差100倍率以上。估计是防止两个质量相差太大的物体碰撞后会产生过大的速度,从而影响游戏性能吧。Drag(阻力):这里指的是空气阻力,当游戏物体收到某个作用力的时候,这个值越大越难移动。如果设置成无限的话,物体会立即停止移动。Angular Drag(角阻力):
同样指的是空气阻力,只不过是用来阻碍物体旋转的。如果设置成无限的话,物体会立即停止旋转。Use Gravity(使用重力):
勾选了这个项,游戏对象就会受到重力影响。Is Kinematic(是否动态):
勾选这个选项会使游戏对象不受物理引擎的影响,但这不等同于没有刚体组件。这通常用于需要用动画控制的刚体,这样就不会因为惯性而影响动画了。Interplate(差值类型):如果看到刚体移动的时候一直抽风或者运动的不是很平滑,可以选择一种平滑方式:
None(无差值):不使用差值平滑。
Interpolate(差值):根据上一帧来平滑移动。
Extrapolate(推算):根据推算下一帧物体的位置来平滑移动。Collision Detection(碰撞检测方式):
Discrete(离散):默认的碰撞检测方式。但若当物体A运动很快的时候,有可能前一帧还在B物体的前面,后一帧就在B物体后面了,这种情况下不会触发碰撞事件,所以如果需要检测这种情况,那就必须使用后两种检测方式。
Continuous(连续):这种方式可以与有静态网格碰撞器的游戏对象进行碰撞检测。
Continuous Dynamic(动态连续):这种方式可以与所有设置了2或3方式的游戏对象进行碰撞检测。Freeze Position/Rotation(冻结位置/旋转):
可以对物体在X、Y、Z三个轴上的位置/旋转进行锁定,即使受到相应的力也不会改变,但可以通过脚本来修改。

最后顺便再提一下恒力组件(Constant Force),由于比较容易理解我就不做详细介绍了。一共有4个参数,分别是Force/Relative Force(世界/相对作用力)、Torque/Relative Torque(世界/相对扭力)。这些参数代表了附加在刚体上的XYZ轴方向恒力的大小,另外还要注意必须是刚体才可以添加恒力。有兴趣可以自己尝试一下给物体一个Y轴方向的力,物体就会像火箭一样飞向天际,哈哈。

### 在Unity中获取和设置组件变量的方法 在Unity中,可以通过多种方式获取和设置组件变量。以下是一些常用方法,并附有示例代码。 #### 1. 使用 `GetComponent` 获取组件并设置变量 通过 `GetComponent` 方法可以获取指定游戏对象上的组件实例。然后可以直接访问该组件的公共变量或调用其方法。 ```csharp using UnityEngine; public class Example : MonoBehaviour { void Start() { // 获取当前游戏对象上的 Rigidbody 组件 Rigidbody rb = GetComponent<Rigidbody>(); if (rb != null) { // 设置 Rigidbody 的重力影响为 false rb.useGravity = false; } } } ``` 此方法适用于任何类型的组件[^2]。 #### 2. 使用静态实例化方法访问组件变量 如果一个脚本被设计为单例模式(Singleton),可以通过其静态实例直接访问变量或调用方法。 ```csharp using UnityEngine; public class GameManager : MonoBehaviour { public static GameManager Instance; // 静态实例 public int gameScore; // 示例变量 void Awake() { Instance = this; // 初始化静态实例 } } public class AccessGameManager : MonoBehaviour { void Start() { // 通过静态实例访问 GameManager 的变量 GameManager.Instance.gameScore = 100; Debug.Log("Game Score: " + GameManager.Instance.gameScore); } } ``` 这种方法适合全局管理类脚本[^3]。 #### 3. 使用 `Find` 方法获取游戏对象并设置组件变量 可以通过 `GameObject.Find` 或 `Transform.Find` 查找游戏对象,再通过 `GetComponent` 获取组件并设置变量。 ```csharp using UnityEngine; public class FindExample : MonoBehaviour { void Start() { // 使用 GameObject.Find 查找名为 "Player" 的游戏对象 GameObject player = GameObject.Find("Player"); if (player != null) { // 获取 Player 对象上的 Camera 组件 Camera cameraComponent = player.GetComponent<Camera>(); if (cameraComponent != null) { // 设置 Camera 的远裁剪平面 cameraComponent.farClipPlane = 1000f; } } // 使用 Transform.Find 查找子对象 Transform childObject = transform.Find("ChildObject"); if (childObject != null) { // 获取子对象上的 Light 组件 Light lightComponent = childObject.GetComponent<Light>(); if (lightComponent != null) { // 设置 Light 的强度 lightComponent.intensity = 2f; } } } } ``` 此方法展示了如何通过名称查找游戏对象及其子对象,并操作其组件[^5]。 #### 4. 使用泛型方法简化组件获取与变量设置 泛型方法可以进一步简化代码结构,减少重复代码。 ```csharp using UnityEngine; public class GenericExample : MonoBehaviour { T GetAndSetComponent<T>(string objectName, string componentName) where T : Component { GameObject obj = GameObject.Find(objectName); if (obj != null) { T component = obj.GetComponent<T>(); if (component != null) { // 根据组件类型设置变量 if (typeof(T) == typeof(Light)) { Light light = (Light)component; light.intensity = 1.5f; } else if (typeof(T) == typeof(Rigidbody)) { Rigidbody rb = (Rigidbody)component; rb.useGravity = true; } return component; } } return null; } void Start() { GetAndSetComponent<Light>("LightObject", "Light"); GetAndSetComponent<Rigidbody>("Player", "Rigidbody"); } } ``` ### 注意事项 - 确保目标游戏对象和组件存在,否则可能会导致 `NullReferenceException`。 - 使用 `Find` 方法时应避免频繁调用,因为它会带来性能开销。推荐将结果缓存到变量中以提高效率[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值