碰撞检测

碰撞产生的必要条件是两个物体都有碰撞器(Collider),至少一个物体有刚体(rigidbody)

有了刚体才会模拟受到力的作用

Mass - 质量 默认为千克

Drag - 阻力 0表示没有阻力

Angular Drag - 扭矩阻力 阻碍旋转的阻力 0表示没有阻力

Is Kinematic - 如果启动此选项,则对象将不会被物理引擎驱动,只能通过Transform操作

Interpolate - 插值运算 让刚体物体运动更平滑

Interpolate 根据前一帧

Extrapolate 根据后一帧

一般于物理帧更新间隔过大的场景

Collision Detection - 碰撞检测模式

用于防止快速移动的对象穿过其他对象而不检测碰撞

Discrete - 离散检测

Continuous - 连续检测

Continuous Dynamic - 连续动态检测

Continuous Speculative - 连续推测检测

性能消耗:连续动态>连续推测>连续>离散

alt text

Constraints - 约束 对刚体运动的限制

对什么轴进行约束就在什么轴上不会产生位移,旋转同理


3D碰撞器的类型

盒装,球状,胶囊,网格,轮胎,地形

Is Trigger 是否是触发器,如果启用此属性,则该碰撞体将用于触发事件,并被物理引擎忽略,主要用于进行没有物理效果的碰撞检测

Center 碰撞器中心点相对物体的偏移

异形物体使用多种碰撞体组合 刚体的子对象碰撞器参与碰撞检测

网格碰撞器 加了刚体的网格碰撞器必须勾选Convex才能模拟力的租用

轮胎碰撞器 必须在根物体(车本体父对象)上添加刚体才会生效


物理材质

Dynamic Friction - 动摩擦力 越小动摩擦力越小

Static Friction - 静摩擦力

Bounciness - 弹性 越大弹性越好

Friction Combine 碰撞对象摩擦力组合方式

unce Combine 碰撞对象弹力组合方式


检测函数

public class Lesson16 : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {

    }
    //碰撞和触发响应函数属于特殊生命周期函数,也是通过反射调用

    #region 物理碰撞检测响应函数
    //碰撞触发时会自动调用这个函数
    private void OnCollisionEnter(Collision collision)
    {
        //碰撞到的对象的碰撞器信息
        //collision.collider

        //碰撞对象的依附对象
        //collision.gameObject

        //碰撞对象的依附对象的位置信息
        //collision.transform

        //触碰点相关
        //点数
        //collision.contactCount
        //接触点坐标
        //ContactPoint[] pos = collision.contacts;
        print("被" + collision.gameObject.name + "撞到了");
    }

    //碰撞结束分离时自动调用的函数
    private void OnCollisionExit(Collision collision)
    {
        print("和" + collision.gameObject.name + "分开了");
    }

    //碰撞发生过程中一直调用的函数
    private void OnCollisionStay(Collision collision)
    {
        print("和" + collision.gameObject.name + "正在接触");
    }
    #endregion

    #region 触发器检测响应函数
    //接触时会调用
    private void OnTriggerEnter(Collider other)
    {
        print("被" + other.gameObject.name + "触发");
    }

    //分开时调用
    private void OnTriggerExit(Collider other)
    {
        print("和" + other.gameObject.name + "分开了");
    }

    //接触过程中一直调用
    private void OnTriggerStay(Collider other)
    {
        print(other.gameObject.name + "正在触发");
    }
    #endregion

    //父对象刚体上面没有挂载碰撞器而子对象上挂载碰撞器时,如果把碰撞或触发响应代码相关脚本挂载在子对象身上时
    //此时碰撞或触发响应相关代码不会有响应,只能把相关脚本挂载到父对象上

    //碰撞和触发响应函数都可以写成虚函数,在子类中去重写逻辑
    //一般会把想重写的碰撞和触发响应函数都写成protected
    
}

public class Lesson17 : MonoBehaviour
{
    Rigidbody rigidBody;
    // Start is called before the first frame update
    void Start()
    {
        #region 刚体自带的添加力的方法
        //给刚体加力的目的是为了让它有一个速度

        //首先要获取刚体组件
        rigidBody = GetComponent<Rigidbody>();

        //添加力
        //相对世界坐标添加力
        //相对世界坐标系Z轴正方向加力
        rigidBody.AddForce(Vector3.forward);
        //相对本地坐标添加力
        rigidBody.AddRelativeForce(Vector3.forward);

        //添加扭矩力,让其旋转
        //相对世界坐标系
        rigidBody.AddTorque(Vector3.forward);
        //相对本地坐标系
        rigidBody.AddRelativeTorque(Vector3.forward);

        //直接改变速度
        //相对世界坐标系
        rigidBody.velocity = Vector3.forward;

        //模拟爆炸效果
        //第一个参数是力的大小,第二个是爆炸中心,第三个是爆炸半径
        //仅影响挂载了该脚本的物体
        rigidBody.AddExplosionForce(10, Vector3.zero, 10);
        #endregion

        #region 力的不同模式
        //第二个参数为力的模式,主要作用是影响计算过程,最终得出的移动速度不同
        rigidBody.AddForce(Vector3.forward,ForceMode.Acceleration);

        //动量定理 Ft = mv , v =Ft/m

        //不忽略时间的话,时间按物理帧间隔时间算,t=0.02s;

        //Acceleration
        //给物体一个持续的加速度,忽略其质量
        //质量默认为1

        //Force
        //给物体加一个持续的力,与物体的质量有关

        //Impulse 
        //给物体添加一个瞬时的力,与物体质量有关,忽略时间,默认时间为1

        //VelocityChange
        //给物体添加一个瞬时速度,忽略质量和时间,都默认为1
        #endregion

        #region 力场脚本
        //Constant Force
        #endregion
        //刚体的休眠
        //判断刚体是否休眠
        if(rigidBody.IsSleeping())
        {
            //唤醒刚体
            rigidBody.WakeUp();
        }
    }

}
posted @ 2025-03-17 14:02  cannedmint  阅读(48)  评论(0)    收藏  举报