Unity里可以模拟一些物理表象,如重力、阻力、阻力、摩擦力、弹性、碰撞、等
1、刚体(Rigidbody)
影响和质量相关的物理表现,建议不同物体直接的质量不要相差超过一百倍,不然可能就会有一些违和感,显得失真了。
1、Mass: 质量
定义:该项用于设置游戏对象的质量,也就是重量。质量单位是KG(建议在同一个游戏场景中,游戏对象之间的质量差值不要大于100倍)
2、Drag: 阻力
定义:当对象受扭矩力旋转时受到的空气阻力。0表示没有空气阻力,阻力极大时游戏对象会立即停止运动
3、角阻力:Angular Drag
和阻力比较相似,只不过这个影响的是旋转的效果。
4、Use Gravity: 使用重力
定义:若开启此项,游戏对象会受到重力的影响
5、Is Kinematic: 是否开启动力学
定义:若开启此项,游戏对象将不再受物体引擎的影响从而只能通过Transform(几何变换组件)属性来对其操作。该方式适用于模拟平台的移动或带有铰链关节链接刚体的动画
6、Interpolate: 插值
定义:该项用于控制刚体运动的抖动情况,有3项可供选择。
None:没有插值
Interpolate:内插值。基于前一帧的Transform来平滑此次的Transform
Extrapolate:外插值。基于下一帧的Transform来平滑此次的Transform
7、Collision Detection: 碰撞检测
定义:该属性用于控制避免高速运动的游戏对象穿过其他的对象而未发生碰撞,有3项可供选择。
Discrete: 离散碰撞检测。该模式与场景中其他的所有碰撞体进行碰撞检测。该项为默认值。
Continuous:连续碰撞检测。该模式用于检测与动态碰撞体(带有Rigidbody)的碰撞,使用连续碰撞检测模式来检测与网络碰撞体的(不带Rigidbody)碰撞。其他的刚体会采用离散碰撞模式。此模式适用于那些需要与采用连续动态碰撞检测的对象相碰撞的对象。这对物理性能会有很大的影响,如果不需要对快速运动的对象进行碰撞检测,就使用离散碰撞检测模式。
Continuous Dynamic:连续动态碰撞检测模式。该模式用于检测与采用连续碰撞模式或连续动态碰撞模式对象的碰撞,也可用于检测没有Rigidbody的静态网格碰撞体。对于与之碰撞的其他对象可采用离散碰撞检测,动态连续碰撞检测模式也可用于检测快速运动的游戏对象。
1.1、恒力组件(Constant Force)
1.1.1、属性介绍
1、绝对力Force
施加在世界坐标中的力,让他按照世界坐标来移动
2、相对力RelativeForce
施加在本地坐标中的力,让他按照世界坐标来移动
3、绝对扭矩力Torque
施加在世界坐标中的扭矩力,让他按照世界坐标进行旋转
4、相对扭矩力RelativeTorque
施加在本地坐标中的扭矩力,让他按照本地坐标进行旋转
1.1.2、Api使用
1、刚体速度:Rigidbody. velocity
可以给他赋值来控制该刚体的物体向某个方向移动
public class Test : MonoBehaviour {
Rigidbody rigidbody;
void Start() {
rigidbody = transform.GetComponent<Rigidbody>();
rigidbody.velocity = new Vector3(0, 0, 5);
}
}
2、添加绝对力Rigidbody. AddForce
rigidbody = transform.GetComponent<Rigidbody>();
rigidbody.AddForce(new Vector3(0, 0, 5));
3、添加相对力Rigidbody. AddRelativeForce
rigidbody = transform.GetComponent<Rigidbody>();
rigidbody.AddRelativeForce(new Vector3(0, 0, 5));
4、添加绝对扭矩力Rigidbody. AddTorque
rigidbody.AddTorque(new Vector3(0, 0, 5));
5、添加相对扭矩力Rigidbody. AddRelativeTorque
rigidbody.AddRelativeTorque(new Vector3(0, 0, 5));
6、添加爆炸力Rigidbody.AddExplosionForce
添加爆炸力,参数是爆炸力度,爆炸的位置,爆炸的范围
rigidbody.AddExplosionForce(500f, transform.position, 10);
1.2、刚体休眠和唤醒
Rigidbody.Sleep();//强制刚体休眠
Rigidbody.WakeUp();//唤醒休眠中的刚体
1.3、力的常用函数
1、在指定位置上给物体添加力
使用的API是;AddForceAtPosition参数是一个三维的向量,代表向哪个方向发力,第二个参数也是一个三维向量,表示发力的位置
2、使用方式
public class Test : MonoBehaviour {
Rigidbody rigidbody;
void Start() {
rigidbody = transform.GetComponent<Rigidbody>();
// A点去B点=B点位置-A点位置
Vector3 direction = transform.position + new Vector3(0, 1, 0) - transform.position;
rigidbody.AddForceAtPosition(direction * 100f, transform.position);
}
}
2、碰撞器和触发器
2.1、Capsule Collider(胶囊碰撞器)
用途:常用于角色控制器(如人体、圆柱形物体)。
优点:结合球体和圆柱体的优势,适合角色移动时的稳定碰撞检测。
缺点:无法适配非对称形状。
2.1.1、常用属性
1、是触发器Is Trigger
勾选碰撞器会作为触发器使用
2、物理材质Material
给碰撞器提供一些物理属性
3、Center中心
碰撞器的位置
2.1.2、常用的API
public class Test : MonoBehaviour {
void OnCollisionEnter(Collision collision) {
Debug.Log("我发生了碰撞");
}
void OnCollisionExit(Collision collision) {
Debug.Log("碰撞结束了");
}
void OnCollisionStay(Collision collision) {
Debug.Log("停留在碰撞上");
}
}
2.1.3、碰撞和触发检测的条件
1、碰撞器
都需要有碰撞器组件且都不能勾选为触发器
挂脚本的物体上有刚体组件
2、触发器
都需要有碰撞器组件,至少有一个勾选为触发器
挂脚本的物体上有刚体组件
2.2、Box Collider(盒型碰撞器)
用途:适用于方形/矩形物体(如箱子、墙壁)。一般你直接创建的3D物体会自带一个这样的碰撞器
参数:
Size:定义碰撞盒的 XYZ 轴向尺寸。
Center:调整碰撞盒相对于物体中心的偏移。
优点:计算效率高,性能消耗最低。
缺点:无法贴合复杂形状。
2.3、Sphere Collider(球形碰撞器)
用途:适用于球体或近似球形的物体(如炮弹、头部碰撞检测)。
参数:
Radius:控制球体半径。
Center:调整球心位置。
优点:计算速度快,适合动态物体的快速碰撞检测。
缺点:仅适用于对称圆形物体。
2.4、Mesh Collider(网格碰撞器)
用途:精确贴合复杂模型(如高精度地形、不规则物体)。
参数:
Mesh:指定用于生成碰撞的网格。你可以直接使用别人的这个网格信息,直接拖过来就是
Convex:勾选此复选框可启用 Convex。如果启用此属性,该 Mesh Collider 将与其他 Mesh Collider 发生碰撞。Convex Mesh Collider 最多 255 个三角形。你可以理解为为一个对象身上,他不是一个完整的个体,而是由不同的这种小网格组成的碰撞体,局部满足碰撞。
Cooking Options:就是处理碰撞模型的不同处理方式
启用或禁用影响物理引擎对网格处理方式的网格烹制选项。
-None
禁用下方列出的所有 Cooking Options
-Everything
启用下方列出的所有 Cooking Options。
-Cook for Faster Simulation
使物理引擎烹制网格以加快模拟速度。启用此设置后,这会运行一些额外步骤,以保证生成的网格对于运行时性能是最佳的。这会影响物理查询和接触生成的性能。禁用此设置后,物理引擎会使用更快的烹制速度,并尽可能快速生成结果。因此,烹制的 Mesh Collider 可能不是最佳的。
-Enable Mesh Cleaning
使物理引擎清理网格。启用此设置后,烹制过程会尝试消除网格的退化三角形以及其他几何瑕疵。此过程生成的网格更适合于在碰撞检测中使用,往往可生成更准确的击中点。
-Weld Colocated Vertices
使物理引擎在网格中删除相等的顶点。启用此设置后,物理引擎将合并具有相同位置的顶点。这对于运行时发生的碰撞反馈十分重要。
优点:完全贴合模型表面,精度最高。
缺点:性能消耗大,非凸面体(Concave)仅适用于静态物体。
2.5、Wheel Collider(车轮碰撞器)
用途:专为车辆模拟设计(如汽车轮胎)。
参数:
Mass
车轮的质量
Radius
车轮的半径
Wheel Damping Rate(车轮阻尼率)
作用:控制车轮旋转的阻力(类似“惯性”),影响车辆加速/刹车的响应速度。
值越大,车轮旋转阻力越大,车辆加速变慢,刹车更快停止。
典型应用:高阻尼率模拟越野车轮胎,低阻尼率适合赛车。
Suspension Distance 控制车轮悬挂系统的弹性和阻尼,模拟车辆减震效果。
车轮悬架的最大延伸距离(在局部空间中测量)。悬架始终向下延伸穿过局部 Y 轴
2.6、Terrain Collider(地形碰撞器)
用途:专门适配 Unity 的 Terrain 系统(如开放世界地形)。这个我们后面再学习
参数:
Terrain Data:关联地形数据。
Enable Tree Colliders:是否启用树木碰撞。
优点:自动匹配地形高度图,节省手动配置时间。
3、物理材质
3.1、作用
调节碰撞物体的摩擦力和弹力效果
3.2、属性
1、动态摩擦力Dynamic Friction
动态摩擦力,物体移动的时候的摩擦力
2、静态摩擦力 Static Friction
静态摩擦力,当物体在表面静止时使用的摩擦力
3、弹力 Bounciness
表面弹力,值为0-1 0是没有弹力 1是没有能量损失的反弹。
4、关节
4.1、关节类型
1、弹簧关节(Spring Joint)
模拟了弹簧的效果,将刚体组件拖动到弹框关节的 Connected Body属性选项。
拖动一个物体另一个物体也受到影响。
2、铰链关节(Hinge Joint)
模拟的是两个物体以链条形式绑定在了一起,当力量大于链条固定力矩时,两个物体会产生相互的拉力
3、固定关节(Fixed Joint)
模拟的是两个物体之间有一根杆子连接再一起,使他们永远以相对的位置固定在一起
4、角色关节(Character Joint)
模拟人体骨头关节的连接,就是两个物体能根据一个关节点自由的朝一个方向旋转,但固定在一个相对的距离
5、可配置关节(Configurable Joint)
可以模拟任意关节的效果,但是需要通过配置大量的属性来实现,效率相对比较低
4.2、关节通用属性
1、连接的刚体Connected Body
2、断开力Break Force
通过脚本可以捕获断开力的大小
public class NewBehaviourScript : MonoBehaviour {
void OnJointBreak(float breakForce) {
Debug.Log("断开连接的力量:"+ breakForce);
}
}
3、断开力矩 Break Torque
5、射线
5.1、概念
指3D世界中由一个点向一个方向发射的一条没有终点的线,一般是用来和碰撞组件做交互,检测一些碰撞信息的。被射线碰撞的物体必须有碰撞组件。
5.2、应用场景
多用于子弹飞行过程中来判断是否击中了目标,一些游戏设计是点击地板来控制人物移动的,这时候也可以通过射线检测来判断点击的目标是否是地板
5.3、常用函数
5.3.1、绘制射线(用于测试环境)
1、Debug.DrawLine();
// 当前位置到身前1米的位置,颜色,消失时间,是否能够穿透相机
Debug.DrawLine(transform.position, transform.position + transform.forward, Color.red, 100, false);
2、Debug.DrawRay();
5.3.2、从相机发出的射线
Physics.Raycast();返回一个布尔值,真true代表有命中碰撞器,否则为false。
有多种重载,一般常用的是
- (射线、光线碰撞到的物体out hit(类型RaycastHit)、射线长度float、遮罩过滤层LayerMask)
- (射线起点Vector3、射线方向Vector3、光线碰撞到的物体out hit(类型RaycastHit)、射线长度float、遮罩过滤层LayerMask)
- 补充:RaycastHit碰撞物体信息和遮罩过滤层LayerMask是可选参数,根据实际需求决定是否需要的,另外LayerMask可以定义为全局公开变量,直接在组件面板快速勾选和哪些层做交互,也可以通过代码来设置LayerMask=LayerMask.GetMask(),括号内填写要开启的层级名称,多个层级用,分割开
Camera.ScreenPointToRay();从摄像机通过屏幕点发射一条射线
public class Test : MonoBehaviour {
Camera camera;
void Start() {
camera = GameObject.Find("Camera").GetComponent<Camera>();
}
void Update() {
if (Input.GetMouseButtonDown(0)) {
Ray ray = camera.ScreenPointToRay(Input.mousePosition);
RaycastHit hit; // 获取到的碰撞信息
if (Physics.Raycast(ray, out hit, 100f)) {
Debug.Log("位置:" + hit.point + "名称:" + hit.collider.name);
}
}
}
}
3、层级遮罩的用法
public class Test : MonoBehaviour {
public LayerMask layerMask;
void Start() {
layerMask = LayerMask.GetMask("BOSS");
}
// Update is called once per frame
void Update() {
if (Input.GetMouseButtonDown(0)) {
RaycastHit hit; // 获取到的碰撞信息
if (Physics.Raycast(transform.position, transform.forward, out hit, 1000f, layerMask)) {
Destroy(hit.collider.gameObject);
}
}
}
}
4、Physics.RaycastAll();
返回一个储存所有射线命中的物体信息数组RaycastHit[]
public class Test : MonoBehaviour {
void Update() {
if (Input.GetMouseButtonDown(0)) {
// 获取到的碰撞信息
RaycastHit [] hit = Physics.RaycastAll(transform.position, transform.forward, 1000f);
Debug.Log("一共碰到了:" + hit.Length + "个物体");
for (int i = 0; i < hit.Length; i++) {
Debug.Log("碰到了:" + hit[i].collider.gameObject.name);
}
}
}
}
5、Physics.OverlapSphere()
球形射线,返回一个储存所有射线命中的物体信息数RaycastHit[]
public class Test : MonoBehaviour {
void Start() {
Collider[] hit = Physics.OverlapSphere(transform.position, 100f);
Debug.Log("一共碰到了:" + hit.Length + "个物体");
for (int i = 0; i < hit.Length; i++) {
Debug.Log("碰到了:" + hit[i].gameObject.name);
}
}
}