Unity内置了NVIDIA的Physx物理引擎,Physx是目前使用最为广泛的物理引擎,被很多游戏大作所采用,开发者可以通过物理引擎高效、逼真地模拟刚体碰撞、车辆驾驶、布料、重力等物理效果,使游戏画面更加真实而生动。
Rigidbody(刚体)组件可使游戏对象在物理系统的控制下来运动,刚体可接受外力与扭矩力用来保证游戏对象像在真实世界中那样进行运动。任何游戏对象只有添加了刚体组件才能受到重力的影响,通过脚本为游戏对象添加的作用力以及通过NVIDIA物理引擎与其他的游戏对象发生互动的运算都需要游戏对象添加了刚体组件。
Rigidbody介绍
给物体添加刚体的方式如下图:
RigidBody中的一些属性
Mass 质量
Angular Drag 角阻力 (可用来减缓物体的旋转。阻力越高旋转越慢。 )
Use Gravity 是否使用重力
Is Kinmatic 是否使用运动学 (如果Use Gravity和Is Kinmatic同时勾选的话,那么Is Kinmatic的优先级比Use Gravity要高)
Interpolate
Collision Detection 碰撞检测
Constraints 约束
Freeze Position 冻结位置
Freeze Rotation 冻结旋转
我们在游戏场景中添加基本的游戏对象后,比如添加Cube后,是没有上任何的效果的。只有当我们给Cube添加Rigidbody组件后,运行程序,那么Cube就会向下掉。这时候就是因为有了重力的影响。
碰撞器
盒子碰撞器 BoxCollider
球形碰撞器 SphereCollider
胶囊碰撞器 CapsuleCollider (【注意】胶囊体和圆柱体的碰撞器都是CapsuleCollider )
【几种碰撞器的性能比较】
碰撞检测的条件
两个物体要想发生碰撞两者必须都有Collider组件,主动方必须要有刚体组件
相关代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TriggerDemo : MonoBehaviour {
//collision指的是和绑定此脚本游戏对象发生碰撞的游戏对象
//OnCollisionEnter在两个游戏对象发生碰撞的时候出发 一次碰撞只出发一次
private void OnCollisionEnter(Collision collision)
{
Debug.Log("开始发生碰撞"+ collision.collider.name);
}
//OnCollisionStay在两个游戏对象碰撞过程中执行 一次碰撞大约执行20次左右
private void OnCollisionStay(Collision collision)
{
Debug.Log("发生碰撞中");
}
//OnCollisionExit在两个游戏对象从接触状态开始分离的那一刻执行 再离开的瞬间 只执行一次
private void OnCollisionExit(Collision collision)
{
Debug.Log("准备结束碰撞");
}
}
触发器
其实就是碰撞器中,在检测触发的游戏对象上Collider组件中勾选IsTrigger就行了。这样的话,两个游戏对象就可以此相互穿越。
在主动方或者被动方对象上添加Rigidbody都可以
如何检测一个物体已经碰到另一个物体了呢?
代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TriggerDemo : MonoBehaviour {
//other表示的是和绑定此脚本的游戏对象发生碰撞的游戏对象
//在两个游戏对象接触的时候执行
private void OnTriggerEnter(Collider other)
{
Debug.Log("开始进入"+ other.gameObject.name);
}
//在两个游戏对象有交集的时候执行
private void OnTriggerStay(Collider other)
{
Debug.Log("进入" + other.gameObject.name);
}
//在游戏对象相互分开的时候有交集
private void OnTriggerExit(Collider other)
{
Debug.Log("准备出来" + other.gameObject.name);
}
}
穿越的问题
在控制一个物体A去撞另一个物体B时,不要直接去修改物体A的Transform的position属性,因为你会发现如果即使两者发生了碰撞也还是会穿越的,原因就在于我们是直接设置的坐标,如果物体A有刚体组件的话,应该用AddForce,给物体添加一个力,然后让物理引擎去让物体动,此时如果发生了碰撞的话,就不会穿越了。
但是这样需要注意的一点是 我们需要设置如下的参数 否则在添加力的情况下也是没有效果的
做了上面的操作后我们可以通过控制transform.translate方法,Speed =1000m/s的时候依然不会检测到碰撞
transform.Translate(Vector3.forward * Time.deltaTime * Speed);
如果不是特别高的运行速度,建议还是不要调整此参数了,毕竟这样持续检测很好性能的。
Force系列方法
Rigidbody.AddForce
Rigidbody.AddRelativeForce
Toque系列方法
Rigidbody.AddTorque
Rigidbody.AddRelativeTorque
角色控制器CharacterController
Move
角色移动只受到碰撞的约束。角色遇到碰撞时将会沿着碰撞盒滑动(你懂得)。返回值是对移动过程中遇到的碰撞信息的汇总。Move函数并不使用重力。
SimpleMove
简单移动(会自动模拟重力)
Y轴的速度将会被忽略。速度单位是米每秒。重力自动生效。返回值是角色是否着地。
物理射线Ray
RaycastHit
Physics.Raycast
射线可以分层访问