刚体:

同是物理引擎提供的功能,碰撞检测只需要有 Collider 便可以运作,但所有与作用力相关的属性和函数却都依赖 Rigidbody。

重力:

  一旦使用了 Rigidbody 组件,这个 GameObject 就会受全局重力影响,同时在发生物理碰撞时会自动调用物理引擎进行碰撞处理。

  全局重力可以在 Physics Manager 中进行调整,具体位置为:“Edit -- Project Settings -- Physics”。

  其中,

  Gravity 项就是全局重力,是一个 Vector3 型变量,包含 X,Y,Z 三个分量,默认情况下其大小为 (0, -9.81, 0) 也就是指向全局坐标 -Y 方向大小为 9.81 的作用力。

  Default Material 是所有 Collider 在默认情况下使用的物理材质,物理材质定义了跟表面摩擦系数和弹性系数相关的参数,默认情况下这里使用的是 None(Physic Material) ,在实际游戏中静摩擦为 0.4,动态摩擦为 0.4。

  Sleep Velocity 定义了 GameObject 退出物理运算的速度阈值,当 GameObject 的运动速度低于这个阈值时将进入休眠状态,物理引擎不再对其进行运算,一旦休眠的 GameObject 受到其他 GameObject 碰撞,或者被施加了作用力,则会立刻解除休眠。

  Sleep Angular Velocity 定义了 GameObject 退出物理运算的角速度阈值,当 GameObject 的旋转速度低于这个阈值时将进入休眠状态。

  Max Angular Velocity 是最大旋转速度,任何 GameObject 在默认状态下都不会超过这个旋转速度。这里有意思的一点是,当一个球在粗糙面(有摩擦)上受到外力滚动时,在旋转速度没有超过最大旋转速度阈值前,其位移速度和旋转速度是匹配的(也就是可以通过滚动一周位移距离为2πr,转过角度为2π,从一个速度换算出另一个);一旦超过阈值,球的旋转速度不再增加,而位移速度不受限制,此时两种速度不再匹配;外力撤除后,球在摩擦作用下减速,这时可以发现旋转速度不变而位移速度飞快下降,直到位移速度恢复到能够与阈值范围内的旋转速度相匹配时,两种速度才开始共同下降,并且位移速度的下降幅度也瞬间回到正常摩擦作用下的递减水平(大大减缓)。

  重力其实可以看作是一个施加在所有 rigidbody 上的 constant force,所以即便是将全局重力设为 0,也可以通过给一个 rigidbody 添加 (0, -9.81, 0) 的 constantForce 来达到模拟重力的目的。

阻力:

  阻力有 Friction 和 Drag 两种,前者是表面摩擦,后者是风阻。Friction 在 Collider 的 Physic Material 中定义,Drag 则是在 Rigidbody 里定义。

  Friction 又有 staticFriction 和 dynamicFriction 之分,staticFriction 是当 GameObject 静止时的静摩擦,它决定要用多大的作用力才能让 GameObject 开始运动,dynamicFriction 是 GameObject 开始运动时会受到来自接触面的摩擦,这是只要 GameObject 保持接触并存在相对运动就会一直存在的作用力。

  Drag 区分为 Drag 和 Angular Drag,前者影响位移,后者影响旋转,而且 Drag 与 Friction 不同的地方在于,Drag 不依赖碰撞或者接触,只要物体在运动就会一直受到的与运动反向的作用力。

  此外,在 Physics Material 里还有另外一种各向异性摩擦的定义,包括三个变量:frictionDirection2,staticFriction2,dynamicFriction2。

  其中,frictionDirection2 决定各向异性摩擦的方向,如果方向向量为 0,那么就没有各向异性摩擦。

  staticFriction2 定义静各向异性摩擦大小,其方向为 frictionDirection2 定义的方向。

  dynamicFriction2 定义动态各向异性摩擦大小,其方向为 frictionDirection2 定义的方向。

  各向异性摩擦与普通表面摩擦的区别就在于它的方向是固定的,而且跟相对运动方向无关。

  此外,在 Physic Material 中有一个变量 frictionCombine 用来决定相互接触的两个 Rigidbody 它们之间的摩擦要如何计算,因为两个 Rigidbody 都分别有各自的摩擦定义。frictionCombine 有四种模式:Average,Multiply,Minimum,Maximum。

  其中,Average 就是取两个 Rigidbody 的摩擦的平均值作为两者间的摩擦。

  Multiply 是取两个 Rigidbody 摩擦的乘积作为两者间的摩擦。

  Minimum 是取两个 Rigidbody 摩擦中最小的那个作为两者间的摩擦。

  Maximum 是去两个 Rigidbody 摩擦中最大的那个作为两者间的摩擦。

让物体动起来:

  要让附加了 Rigidbody 的物体运动起来有两种方式,利用重力和施加额外作用力。

  利用重力又可以有两种方式,一种是让 GameObject 落在倾斜的平面上,它会自然向平面倾斜方向运动,另一种是改变重力方向,通过 Physics.gravity 来重新指定全局重力的大小和方向。

  施加外力是物理引擎下让 Rigidbody 运动的常规方法,利用 Physics.AddForce 或者 Physics.AddRelativeForce 来给 GameObject 施加作用力。这两个函数的区别在于,前者参数中定义作用里的 Vector3 变量使用的是全局坐标系(世界坐标系),后者则是用的是 GameObject 的本地坐标系。这两个函数还有第二个参数 ForceMode,用来区分不同的作用力施加方式,ForceMode 有四种:Force,Acceleration,Impulse,VelocityChange。

  Force 模拟在一个 FixedUpdate 的时间片段内持续作用在 Rigidbody 上的力(一个 FixedUpdate 的时间片段长度可以在 Project Settings 中设置,默认为 0.02 秒),假设使用 AddForce 函数对静止的 Rigidbody 施加一个大小为 100 单位的作用力,模式选用 Force,且 Rigidbody 的质量为 1 单位,那么在这个作用力作用结束后,Rigidbody 的位移速度将从 0 变为大小 2 单位,方向为作用里方向(v=f*t/m)。由于模拟里作用的结果就是 Rigidbody 的速度发生变化,所以虽然这个模式是模拟一个持续作用的力,但实际上在 AddForce 函数调用后的下一帧里,Rigidbody 的速度已经变化了(默认情况下帧的间隔时间是 0.16 秒左右,也就是说,本来应该是力持续作用 0.02 秒后才会让 Rigidbody 达到的速度,其实在 0.16 秒后 Rigidbody 就已经达到这个速度了,如果帧的间隔时间更短,那么 Rigidbody 就会更早获得这个速度),这也是涉及到 Rigidbody 的操作最好都放到 FixedUpdate 而不是 Update 里的原因——物理引擎对 Rigidbody 的各种模拟都是以 FixedUpdate 的时间间隔来计算的,如果将这些操作放在 Update 里进行,那么就会因为 FixedUpdate 和 Update 的时间差而导致每一帧都会出现误差,从而最后模拟出来的物理现象与理论不符。

  Impulse 模拟一个瞬间作用在 Rigidbody 上的冲量,AddForce 的第一个参数指定的 Vector3 类型变量就是这个冲量,假设使用 AddForce 函数对精致的 Rigidbody 施加一个大小是 100 单位的冲量,且 Rigidbody 的质量为 1 单位,那么这个冲量的作用结果就是 Rigidbody 的位移速度从 0 变化为大小 100 单位,方向为冲量方向(I=mv1-mv0,这里v0=0)。

  Acceleration 模拟在一个 FixedUpdate 的时间片段内持续作用在 Rigidbody 上的加速度,假设使用 AddForce 对一个静止的 Rigidbody 施加 100 单位的加速度,且 Rigidbody 的质量为 1 单位,那么在这个加速度作用结束后,Rigidbody 的位移速度将从 0 变为大小 2 单位,方向为加速度方向(v=v0+at,这里v0=0)。这个模式与 Force 模式类似,是模拟持续作用约 0.02 秒的加速度,所以 FixedUpdate 和 Update 对其的影响也跟 Force 模式类似。

  VelocityChange 模拟一个 Rigidbody 在瞬间获得一个位移速度。

几段测试用的代码:

GiveForce.cs

using UnityEngine;
using System.Collections;public class GiveForce : MonoBehaviour
{public float ForceFactor = 100;private float time = 0.0f;// Use this for initializationvoid Start(){}// Update is called once per framevoid Update(){//Debug.Log("Time of frame: " + (Time.time - time).ToString());//time = Time.time;}void FixedUpdate(){//Debug.Log("Time of fixedframe: " + (Time.time - time).ToString());//time = Time.time;if (Input.GetMouseButtonDown(0)){gameObject.rigidbody.AddForce(new Vector3(-1, 0, 0) * ForceFactor);//gameObject.rigidbody.AddForce(gameObject.transform.TransformDirection(new Vector3(-1, 0, -1)) * ForceFactor);//gameObject.rigidbody.AddRelativeForce(new Vector3(-1, 0, 0), ForceMode.VelocityChange);Debug.Log(gameObject.rigidbody.velocity.ToString() + gameObject.rigidbody.angularVelocity.ToString() + gameObject.rigidbody.drag.ToString());Debug.Log(gameObject.rigidbody.constantForce.ToString());}else if (Input.GetMouseButtonDown(1)){gameObject.rigidbody.AddForce(new Vector3(1, 0, 0) * ForceFactor, ForceMode.Impulse);//gameObject.rigidbody.AddForce(gameObject.transform.TransformDirection(new Vector3(1, 0, 1)) * ForceFactor);Debug.Log(gameObject.rigidbody.constantForce.ToString());}else if (Input.GetMouseButtonDown(2)){gameObject.rigidbody.AddForce(new Vector3(1, 0, 0) * ForceFactor, ForceMode.VelocityChange);//gameObject.rigidbody.AddForce(gameObject.transform.TransformDirection(new Vector3(1, 0, 1)) * ForceFactor);Debug.Log(gameObject.rigidbody.constantForce.ToString());}}
}

GiveConstantForce.cs

using UnityEngine;
using System.Collections;public class GiveConstantForce : MonoBehaviour
{public bool Enabled = false;// Use this for initializationvoid Start(){}// Update is called once per framevoid Update(){if (Enabled && constantForce != null){constantForce.force = new Vector3(0.0f, -9.81f, 0.0f);}else if (!Enabled && constantForce != null){constantForce.force = Vector3.zero;}}
}

SetFriction.cs

using UnityEngine;
using System.Collections;public class SetFriction : MonoBehaviour
{public float StaticFrictionFactor = 0.0f;public float DynamicFrictionFactor = 0.0f;public bool ShowInstanceID = false;// Use this for initializationvoid Start(){//Debug.Log(gameObject.collider.material.dynamicFriction.ToString());//Debug.Log(gameObject.collider.material.dynamicFriction2.ToString());//Debug.Log(gameObject.collider.material.staticFriction.ToString());//Debug.Log(gameObject.collider.material.staticFriction2.ToString());}// Update is called once per framevoid Update(){PhysicMaterial material = new PhysicMaterial();material.staticFriction = StaticFrictionFactor;material.dynamicFriction = DynamicFrictionFactor;material.frictionCombine = PhysicMaterialCombine.Maximum;gameObject.collider.material = material;//Debug.Log(gameObject.collider.material.dynamicFriction.ToString() + " " + //    gameObject.collider.material.dynamicFriction2.ToString() + " " + //    gameObject.collider.material.staticFriction.ToString() + " " + //    gameObject.collider.material.staticFriction2.ToString());if (ShowInstanceID){Debug.Log(gameObject.collider.material.GetInstanceID().ToString());}}
}

ShowVelocity.cs

using UnityEngine;
using System.Collections;public class ShowVelocity : MonoBehaviour {// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {Debug.Log(gameObject.rigidbody.velocity.ToString() + gameObject.rigidbody.angularVelocity.ToString() + gameObject.rigidbody.drag.ToString());}
}

HoldStill.cs

using UnityEngine;
using System.Collections;public class HoldStill : MonoBehaviour
{public bool Hold = false;// Use this for initializationvoid Start(){}// Update is called once per framevoid Update(){if (Hold){gameObject.rigidbody.Sleep();Hold = false;}}
}

MoveCamera.cs

using UnityEngine;
using System.Collections;public class MoveCamera : MonoBehaviour {public Transform targetTransform = null;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {if (targetTransform){transform.position = targetTransform.position + new Vector3(0, 3, -10);}}
}

[Unity 3D] 物理引擎学习笔记(一)相关推荐

  1. Unity 3D 物理引擎简介 || Unity 3D 物理材质|| Unity 3D 力(AddForce)

    Unity 3D 物理引擎简介 早期的游戏并没有强调物理引擎的应用,当时无论是哪一种游戏,都是用极为简单的计算方式做出相应的运算就算完成物理表现,如超级玛丽和音速小子等游戏. 较为常见的物理处理是在跳 ...

  2. Chipmunk-js物理引擎学习笔记

    一.基本概念 空间:在Chipmunk中,空间是所有对象容器.因此,刚体.形状.链接节点等对象都需要添加到空间中.空间控制这些对象的相互作用. 刚体:物理上的刚体指的是在运动和受力作用后,形状和大小不 ...

  3. C++ 3D物理引擎库BulletPhysics基本使用

    前言:最近在接触OpenGl和DX11的时候,顺便学习了Bullet这个3D物理引擎的基本使用,记录一下. |BulletPhysics介绍 BulletPhysics是一个跨平台的开源物理引擎,也是 ...

  4. 一篇上手LayaAir的3D物理引擎

    昨天,我们分享了一篇2D物理文档<LayaAirIDE的可视化2D物理使用文档>. 今天,我们针对LayaAir引擎的初学者,以及对物理引擎使用不熟悉的开发者,再来分享一篇3D物理文档,本 ...

  5. 常见3D物理引擎概述

    今天帮朋友找3D物理引擎的资料,以前也看过那么多了,一直没有总结过,今天顺便整理一下. 1.  Havok: 老牌的君王,支持功能如下: http://www.havok.com ·          ...

  6. Cannon.js -- 3d物理引擎

    文章目录 前言 一.关于Cannon.js 二.Cannon.js的使用 最后 注意点: 优化 事件 其他 本文完整代码下载: 相关链接: 前言 本篇将介绍Cannon.js -- 3d物理引擎的基础 ...

  7. 【vn.py学习笔记(三)】vn.py事件引擎 学习笔记

    [vn.py学习笔记(三)]vn.py事件引擎 学习笔记 1 时间驱动 2 事件驱动 3 事件引擎工作流程 4 事件引擎结构 4.1 事件队列 4.2 事件处理线程 4.3 事件处理函数字典/通用事件 ...

  8. Unity材质球个人学习笔记

    Unity材质球个人学习笔记 Shader FX: Lighting and glass effects.( 灯光.玻璃) GUI and UI: For user interface graphic ...

  9. 基于傅老师unity游戏教学的学习笔记(EX)将PMX格式的MMD模型导入unity并使用

    为了学习unity,开始游戏制作大业,我选择在bilibili上寻找unity游戏教学视频并边做边学,以此系列博客作为笔记. (EX)将PMX格式的MMD模型导入unity并使用 想做3D游戏,优秀的 ...

最新文章

  1. Shell脚本头定义
  2. 如何提升科研能力?以下这点最重要!
  3. mysql驱动为什么自动加载_为什么JDBC中加载驱动要使用反射?
  4. 18、正则表达式中常用字符
  5. vue的递归组件以及三级菜单的制作
  6. 现代女性都有哪些烦恼?
  7. centos 新装mysql 进入,centos5安装 mysql 提示需要用户及密码进入?Duplicate entry 'localhost-' for key 1...
  8. 计算机在材料科学中的应用上机二,计算机在材料科学中的应用-上机实验二.doc...
  9. Ubuntu 16.04安装Bless十六进制编辑器
  10. 前端小白,如何快速提升自己?了解3点,找工作不用愁
  11. 自动选择SVG和VML的WEB页面
  12. 解决Android拍照保存在系统相册不显示的问题
  13. 基于layui的select区域联动
  14. LeetCode 525 连续数组/剑指 Offer II 011. 0 和 1 个数相同的子数组
  15. unity 保存数据到本地的方法
  16. [从零开始学习FPGA编程-8]:快速入门篇 - 总体 - FPGA功能开发详细流程与关键步骤解读
  17. 不怕被群主踢,安心分享小游戏续命,上分好办法!
  18. 胡嘉伟 :实时计算在提升播放体验的应用实践
  19. 010-java 表单方式或者base64方式上传图片,后端使用nutz的post转发图片到另一个请求...
  20. The server time zone value xxxxxxx is unrecognized or represents more than one time zone.

热门文章

  1. 如何在博客主页添加音乐按钮(HTML小试)
  2. 甄别野鸡大学-中国大学查询
  3. c语言 字母消消乐,消消乐(C语言版)
  4. 第四次作业--项目选题报告(团队)
  5. 5W2H分析方法与项目管理思考
  6. 基于腾讯云个人博客的搭建
  7. elasticsearch 学习笔记(查询语句和修改语句)
  8. 5-13 九宫格输入法 (15分)
  9. Mary_Morton
  10. st7789屏幕+esp32+按键==游戏机?