Unity API 解析(9)—— Rigidbody 类

模拟 GameObject 对象在现实世界中的物理特性(重力,阻力,质量,速度)

对Rigidbody 对象属性的赋值代码通常放在脚本的OnFixedUpdate 方法中

 

collisonDetectionMode 属性 —— 碰撞检测模式

刚体的碰撞检测模式有3种

Discrete —— 静态离散检测模式

Continuous —— 静态连续监测模式 ,一般用在高速运动刚体的目标碰撞体上

ContinousDynamic —— 最强的连续动态检测模式

drag 属性 —— 刚体阻力

drag 值越大刚体速度减慢的越快,当drag >0 时,刚体在增加到一定速度后会匀速运动

刚体在自由落体运动中的最大速度值只与gravity 和drag值有关,与mass无关

inertiaTensor 属性 —— 惯性张量

在距离重心同等的条件下,刚体会向张量值大的一边倾斜

rigidbody.inertiaTensor = new Vector3(5.0f,10.0f,1.0f)

using UnityEngine;
using System.Collections;

public class inertiaTensor_ts : MonoBehaviour
{
    void OnGUI()
    {
        if (GUI.Button(new Rect(10.0f, 10.0f, 160.0f, 45.0f), "X轴惯性张量大于Y轴"))
        {
            transform.position = new Vector3(0, 4, 0);
            //transform绕Z轴旋转45度
            transform.rotation = Quaternion.Euler(0.0f, 0.0f, 45.0f);
            //设置rigidbody的惯性张量
            //X轴分量值大于Y轴,则刚体会向X轴方向倾斜
            rigidbody.inertiaTensor = new Vector3(15.0f, 10.0f, 1.0f);
        }
        if (GUI.Button(new Rect(10.0f, 60.0f, 160.0f, 45.0f), "Y轴惯性张量大于X轴"))
        {
            transform.position = new Vector3(0, 4, 0);
            transform.rotation = Quaternion.Euler(0.0f, 0.0f, 45.0f);
            //设置rigidbody的惯性张量
            //X轴分量值小于Y轴,则刚体会向Y轴方向倾斜
            rigidbody.inertiaTensor = new Vector3(5.0f, 10.0f, 1.0f);
        }
        if (GUI.Button(new Rect(10.0f, 110.0f, 160.0f, 45.0f), "X轴和Y轴惯性张量相同"))
        {
            transform.position = new Vector3(0, 4, 0);
            transform.rotation = Quaternion.Euler(0.0f, 0.0f, 45.0f);
            //设置rigidbody的惯性张量
            //X轴和Y轴惯性张量相同,则刚体会保持静止
            rigidbody.inertiaTensor = new Vector3(10.0f, 10.0f, 1.0f);
        }
    }
}

mass 属性 —— 刚体质量

一般刚体质量取值在0.1 附近模拟最佳,最大不要超过10,否则容易出现模拟不稳定的情况

mass 的主要作用是物体发生碰撞时计算碰撞后的物体的速度

velocity 属性 —— 刚体速度

在脚本中无论是给刚体赋予一个vector3类型的速度向量,还是获取当前刚体的速度,v的方向都是相对世界坐标系而言

velocity 的单位是米每秒 —— 米是Unity中默认的长度单位

AddExplosionForce 方法 —— 模拟爆炸力

爆炸力的大小,爆炸点的坐标,爆炸力的有效半径

AddForceAtPosition —— 增加刚体点作用力

为参数position点增加一个力force

AddForce 方法对刚体施加力时不会产生扭矩使物体发生旋转,但此方法会

using UnityEngine;
using System.Collections;

public class AddExplosionForce_ts : MonoBehaviour
{
    public Rigidbody A;
    public Transform Z;//Scene视图中显示爆炸点坐标
    Vector3 E = Vector3.zero;//爆炸点坐标
    float F, R, y_m;
    bool is_change = false;

    void Start()
    {
        //初始位置使得爆炸点和A的x,y轴坐标值相等
        //可以更改F及R的大小查看运行时结果
        E = A.position - new Vector3(0.0f, 0.0f, 3.0f);
        F = 40.0f;
        R = 10.0f;
        y_m = 0.0f;
        A.transform.localScale = Vector3.one * 2.0f;
        Z.position = E;
    }

    void FixedUpdate()
    {
        if (is_change)
        {
            A.AddExplosionForce(F, E, R, y_m);
            is_change = false;
        }
    }

    void OnGUI()
    {
        //当爆炸点和A的重心的两个坐标轴相等时,A将平移不旋转
        if (GUI.Button(new Rect(10.0f, 10.0f, 200.0f, 45.0f), "刚体移动不旋转"))
        {
            is_change = true;
            inits();
        }
        //虽然受力大小不变,但产生扭矩发生旋转
        if (GUI.Button(new Rect(10.0f, 60.0f, 200.0f, 45.0f), "刚体发生移动但受力大小不变"))
        {
            inits();
            A.position += new Vector3(0.5f, -0.5f, 0.0f);
            is_change = true;
        }
        if (GUI.Button(new Rect(10.0f, 110.0f, 200.0f, 45.0f), "按最近表面距离计算力的大小"))
        {
            inits();
            A.position += new Vector3(0.0f, 2.0f, 0.0f);
            is_change = true;
        }
        //y 轴的偏移改变了A的原始方向
        // 可以更改y_m的值查看不同的效果
        if (GUI.Button(new Rect(10.0f, 160.0f, 200.0f, 45.0f), "Y?á·¢éú??ò?"))
        {
            inits();
            is_change = true;
            A.position += new Vector3(0.0f, 2.0f, 0.0f);
            y_m = -2.0f;
        }
    }
    //初始化数据
    void inits()
    {
        A.velocity = Vector3.zero;
        A.angularVelocity = Vector3.zero;
        A.position = E + new Vector3(0.0f, 0.0f, 3.0f);
        A.transform.rotation = Quaternion.identity;
        y_m = 0.0f;
    }
}

AddTorque 方法 —— 刚体添加扭矩

using UnityEngine;
using System.Collections;

public class AddTorque_ts : MonoBehaviour {
    public Rigidbody R;
    Vector3 m_torque = new Vector3(0.0f,10.0f,0.0f);
	void Start () {
        R.transform.localScale = new Vector3(2.0f,2.0f,2.0f);
        R.mass = 1.0f;
        R.angularDrag = 0.0f;
        Debug.Log("刚体默认的最大角速度"+R.maxAngularVelocity);
        // 可以使用如下代码更改刚体的最大角速度
        //R.maxAngularVelocity = 10.0f;
	}

	void FixedUpdate () {
        // 每帧给物体添加一个扭矩,使其转速不断加快
        R.AddTorque(m_torque,ForceMode.Force);
        Debug.Log("刚体当前角速度"+R.angularVelocity);
	}
}

ClosestPointOnBounds 方法 —— 爆炸点到刚体最短距离

此方法通常用在 AddExplosionForce 中计算爆炸力的大小

GetPointVelocity —— 刚体点速度

获取世界坐标系中worldPoint点在刚体局部坐标系中的速度 ,速度的计算会受刚体角速度的影响

GetRelativePointVelocity —— 刚体点相对速度

 

MovePosition —— 刚体位置移动

对刚体的位置进行移动,通常用在刚体失去动力学模拟的情况下 —— isKinematic 为 true时

Sleep —— 刚体休眠

SweepTest —— 检测碰撞器

检测在刚体的direction方向是否有碰撞器对象,且对象的有效探测距离不大于distance

using UnityEngine;
using System.Collections;

public class SweepTest_ts : MonoBehaviour
{
    public GameObject A, B;
    RaycastHit hit;
    float len = 10.0f;// 有效探测距离
    void Start()
    {
        A.transform.position = new Vector3(1.0f, 1.0f, 1.0f);
        B.transform.position = new Vector3(4.0f, 1.0f, 1.0f);
    }

    void FixedUpdate()
    {
        // 探测刚体A右侧len距离内是否存在物体
        if (A.rigidbody.SweepTest(A.transform.right, out hit, len))
        {
            Debug.Log("A物体右侧存在物体" + hit.transform.name + " 其距A的距离为" + hit.distance);
        }
        else
        {
            Debug.Log("A物体右侧" + len + "米范围没有检测到带碰撞器的物体");
        }
    }

    void OnGUI()
    {
        if (GUI.Button(new Rect(10.0f, 10.0f, 200.0f, 45.0f), "设置B坐标使A无法探测到"))
        {
            // 重置B的position,使得物体A,B的间距大于len值
            B.transform.position = new Vector3(12.0f, 1.0f, 1.0f);
        }
        if (GUI.Button(new Rect(10.0f, 60.0f, 200.0f, 45.0f), "取消B中的Rigidbody组件"))
        {
            // 销毁B物体中的Rigidbody组件
            // 运行程序可以发现,B物体中是否存在Rigidbody对探测结果没有影响
            if (B.GetComponent<Rigidbody>())
            {
                Destroy(B.GetComponent<Rigidbody>());
            }
        }
        if (GUI.Button(new Rect(10.0f, 110.0f, 200.0f, 45.0f), "取消B中的Collider组件"))
        {
            // 销毁B物体中的Collider组件
            // 运行程序发现,如果B中无Collider组件则A无论如何也探测不到B的存在
            if (B.GetComponent<Collider>())
            {
                Destroy(B.GetComponent<Collider>());
            }
        }
        // 对B物体的状态重置
        if (GUI.Button(new Rect(10.0f, 160.0f, 200.0f, 45.0f), "重置"))
        {
            B.transform.position = new Vector3(4.0f, 1.0f, 1.0f);
            if (!B.GetComponent<Collider>())
            {
                B.AddComponent<BoxCollider>();
            }
            if (!B.GetComponent<Rigidbody>())
            {
                B.AddComponent<Rigidbody>();
                B.rigidbody.useGravity = false;
            }
        }
    }
}

SweepTestAll —— 探测碰撞器

探测刚体的direction方向的distance距离内是否有碰撞器,并返回所有探测到的物体的RaycastHit

using UnityEngine;
using System.Collections;

public class SweepTestAll_ts : MonoBehaviour
{
    public GameObject A, B, C, D;
    RaycastHit[] hits;
    float len = 10.0f;//有效探测距离
    void Start()
    {
        A.transform.position = new Vector3(1.0f, 1.0f, 1.0f);
        B.transform.position = new Vector3(4.0f, 1.0f, 1.0f);
        C.transform.position = new Vector3(7.0f, 1.0f, 1.0f);
        //D 物体超出了A的有效探测距离,不会被探测到
        D.transform.position = new Vector3(12.0f, 1.0f, 1.0f);
        hits = A.rigidbody.SweepTestAll(A.transform.right, len);
        float l = hits.Length;
        Debug.Log("A 探测到的物体个数" + l + " 他们分别是");
        // 遍历
        foreach (RaycastHit hit in hits)
        {
            Debug.Log(hit.transform.name);
        }
    }
}

WakeUp 方法 —— 唤醒刚体

自动被唤醒的情况 —— 其他刚体与休眠中的刚体发生碰撞,使用关节链接的刚体发生移动,刚体属性发生改变,给休眠中的刚体施加了一个力

 

useGravity 用来确定刚体是否接受重力加速度的感应

isKinematic 属性 —— 用来确定是否接受动力学模拟(重力感应,速度,阻力,质量)

 

刚体velocity 的值只与Gravity ,drag及Kinematic有关,与质量mass及物体的sacle无关

 

若在脚本中未使用 Rigidbody.SetDensity 方法设置刚体的密度,则刚体的质量mass值为在Inspector面板中mass的大小,此mass与transform中的scale无关,否则有关

 

两物体碰撞符合动量守恒定律

 

作用力方式 ForceMode 的功能注解

ForceMode.Force —— 使用刚体质量计算,以每帧间隔时间为单位计算动量

ForceMode.Acceleration

ForceMode.Impulse

ForceMode.VelocityChange

 

onTriggerXXX  onCollisionXX

若A中无Rigidbody 组件,B中无论是否含有Rigidbody组件,A都将穿越B物体,并且A和B脚本中的OnTriger 和 OnCollision 都不会被调用

要激活以上两方法,必须使移动的物体中含有Rigidbody组件

时间: 2024-10-09 14:21:39

Unity API 解析(9)—— Rigidbody 类的相关文章

Unity API 解析 学习

1 Application类 2 Camera类 3 GameObject类 4 HideFlags类 5 Mathf类 6 Matrix4x4类 7 Object类 8 Quaternion类 9 Random类 10 Rigidbody类 11 Time类 12 Transform类 13 Vector2类 14 Vector3类 1 Application类 1 using UnityEngine; 2 using System.Collections; 3 4 public class

Unity API 解析(3)&mdash;&mdash; GameObject 类

GameObject 类是Unity场景中所有实体的积累.一个GameObject对象通常由多个组件component组成,且至少含有一个transform组件.   activeSelf 属性 -- GameObject的Active标识 activeInHierarchy 属性的功能是返回GameObject实例在程序运行时的激活状态,它只有当GameObect实例的状态被激活时才会返回true.而且它会受父类对象激活状态的影响.如果其父类至最顶层的对象中有一个对象未被激活,activeIn

Unity API 解析(7)&mdash;&mdash; Object 类

Object 类是Unity中所有对象的基类   GetInstanceID -- Object 对象ID 每个对象在工程中都有唯一的ID,并且从程序开始运行到结束,除非对象被销毁,否则每个实例对应的ID都不会改变 从GameObject.CreatePrimitive() 或 Object.Instantiate() 中创建或克隆的每个名字相同的GameObject对象都有唯一的ID using UnityEngine; using System.Collections; public cla

Unity API 解析(4)&mdash;&mdash; HideFlags 类

HideFlags 为枚举类,用于控制object对象的销毁方法以其在监视面板中的可视性   DontSave 保留对象到新场景 如果GameObject 对象被HideFlags.DontSave标识,则在新Scene中GameObject的所有组件将被保留下来,但其子类GameObject对象不会被保留到新scene中 不可对GameObject对象的某个组件如Transform进行HideFlags.DontSave标识,否则无效 即使程序已经退出,被HIdeFlags.DontSave

Unity API 解析(10)&mdash;&mdash; Time 类

realtimeSinceStartup 属性 -- 程序运行实时时间   smoothDeltaTime 属性 -- 平滑时间间隔 主要用在 FixedUpdate 方法中需要平滑过渡的计算   time 属性 -- 程序运行时间 从游戏启动到现在

Unity API 解析(5)&mdash;&mdash; Mathf 类

此类属于结构体类型,只有静态属性和静态方法,不可实例化 Deg2Rad 属性 -- 从角度到弧度常量 (2*PI)/360 Rad2Deg 属性 -- 从弧度到角度常量 Infinity 属性 -- 正无穷大   Clamp 方法 -- 返回有限范围值 返回有范围限制的value值 ClosestPowerOfTwo -- 返回2的某次幂 用于返回最接近参数值value的2的某次幂的值 DeltaAngle -- 最小增量角度 (-180,180] InverseLerp -- 计算比例值 (v

Unity API 解析(6)&mdash;&mdash; Matrix4x4 类

通常用在如摄像机的非标准投影变换等   MultiplyPoint 方法 -- 投影矩阵变换 对点v进行投影矩阵变换 主要用于Camera的投影变换,对于一般物体的矩阵变换用MultiplyPoint3x4方法,不涉及投影变换,计算速度更快 MultiplyPoint3x4 -- 矩阵变换 MultiplyVector 方法 -- 矩阵变换 对方向向量v进行矩阵变换 using UnityEngine; using System.Collections; public class Multipl

Unity API 解析(2)&mdash;&mdash; Camera 类属性

aspect属性 -- 摄像机视口比例 public float aspect {get ; set ;} 用于获取或设置camera适口的宽高比例值 aspect 只处理摄像机可以看到的试图的宽高比例,而硬件显示屏的作用只是把摄像机的内容显示出来,当硬件显示屏的宽高比例与aspect的比例值不同时,视图将发生变形 using UnityEngine; using System.Collections; public class Aspect_ts : MonoBehaviour { void

Unity API 解析(9)&mdash;&mdash; Random 类

不可实例化,只有静态属性和静态方法 insideUnitCircle -- 园内随机点 返回半径为1的园内的随机点坐标,Vector2类型 insideUnitSphere -- 半径为1的球内的随机点坐标 onUnitShper  -- 半径为1的球表面的随机点的坐标 using UnityEngine; using System.Collections; public class insideUnitCircle_ts : MonoBehaviour { public GameObject