码迷,mamicode.com
首页 > 数据库 > 详细

Unity API 解析(9)—— Rigidbody 类

时间:2014-11-09 22:13:43      阅读:724      评论:0      收藏:0      [点我收藏+]

标签:des   style   io   color   ar   os   使用   sp   for   

模拟 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组件

Unity API 解析(9)—— Rigidbody 类

标签:des   style   io   color   ar   os   使用   sp   for   

原文地址:http://www.cnblogs.com/sprint1989/p/4085901.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!