Unity3D學習筆記(十):Physics類和射線


物理系統:碰撞器、觸發器等
力:有大小有方向的矢量,有受力點位置(和向量的區別)
----F = ma(m質量,a加速度,質量越大,加速度越小,停下來越慢)
----m1v1 = m2v2(沖量守恆定理,質量越小,速度越快)
----力的分解
Ft = mv(動量定理)
----Rigid.AddForce(Vector3.forward, ForceMode mode);寫在Start里
----Force(默認):持續力,完全滿足動量守恆定理;Ft = mv
----Impulse:瞬間沖擊力、爆炸力,不完全滿足動量守恆定理;忽略t,讓t = 1,F = mv
----VelocityChange:直接改變速度;忽略t和m,讓t = m = 1,F =v
----Acceleration:給一個加速度;忽略m,讓m = 1,Ft =v
力矩:作用力使物體繞着轉動軸或支點轉動的趨向。
----Rigid.AddTorque(Vector3.up);
練習:Dota2的選人面板,人物可以拖拽旋轉,速度越來越快,反向拖動,轉速大幅降低
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ForceTest : MonoBehaviour {
    public float forceFactor = 10;
    private Rigidbody rigid;
    private float mouse_x;
    // Use this for initialization
    void Start () {
        //力需要一個目標,只有非運動學剛體才會收到力的影響
        rigid = GetComponent<Rigidbody>();
        //力的單位1牛頓,質量0.1KG
        //ForceMode是枚舉,
        //rigid.AddForce(Vector3.forward,ForceMode.Impulse);
        //rigid.AddForceAtPosition(Vector3.forward,new Vector3(1,1,1));
        //rigid.AddTorque(Vector3.up);
      
        //最大旋轉速度,限制物體旋轉速度,可以修改
        rigid.maxAngularVelocity = 999999;
      
    }
    // Update is called once per frame
    void Update () {
        //練習:Dota2的選人面板,人物可以拖拽旋轉,速度越來越快,反向拖動,轉速大幅降低
        //按下鼠標左鍵拖動才會接收值      
        if (Input.GetMouseButton(0))
        {
            mouse_x = Input.GetAxis("Mouse X");
        }
        else
        {
            mouse_x = 0;
        }
        rigid.AddTorque(Vector3.up * -mouse_x * forceFactor, ForceMode.Force);
        //鼠標當前幀的位置可以獲取,和上一幀相減,可以得到一個旋轉的偏移量
        //Input.mousePosition
    }
}
力給在物體重心上
rigid.AddForce(Vector3.forward,ForceMode.Impulse);
選一個受力點,添加一個力,可以讓物體旋轉起來
rigid.AddForceAtPosition(Vector3.forward,new Vector3(1,1,1));
Physics - Gravity,方向向下的重力

ForceMode是枚舉

直線:向兩端無限延長的直的線,沒有端點
線段:兩個點之間的直線,兩個端點
射線:由一個點向一個方向發射一條無限延長的直線,一個端點
Unity如何判斷前方扇形面積有敵人
Ray Unity中的射線(結構體),有兩個參數,origin原點,direction方向
射線檢測的唯一條件:游戲物體必須有碰撞器組件,有沒有剛體無所謂
layerMask層級遮罩,設置只檢查哪一個層級的游戲物體,默認全部檢測
RaycastHit hitInfo是碰撞信息
bool : Physics.Raycast(Ray ray, float maxDistance, int layerMask, QueryTriggerInteraction queryTriggerInteraction);
RaycastHit[] hitinfos = Physics.RaycastAll();
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RaycastTest : MonoBehaviour {
    private Ray ray;
    private RaycastHit hitInfo;
    // Use this for initialization
    void Start () {
        //層級位移運算
        int layerMask = (1 << 8);
        Debug.Log(layerMask);
        layerMask = (1 << 9);
        Debug.Log(layerMask);
        layerMask = (1 << 8) | (1 << 9);
        Debug.Log(layerMask);
        layerMask = LayerMask.GetMask(new string[] { "Lxm", "Cjy" });
        Debug.Log(layerMask);
        //結果第8位,第9位
        //Ray(Vector3 origin, Vector3 direction);
        //Ray射線是結構體,有兩個參數,origin原點,direction方向
        ray = new Ray(transform.position,Vector3.forward);
        //發射射線,物理系統的光線投射,有16種重載
        //Physics.Raycast(ray);
        //射線是沒有網格的,是看不到,是物理系統的一部分,是數學計算得來的
        if (Physics.Raycast(ray))
        {
            Debug.Log("射線已射中物體");
        }
        //maxDistance射線的最大距離就是float的最大值,可以手動設置
        //Raycast(Ray ray, float maxDistance);
        //hitinfo:這條射線所碰撞物體的相關信息,儲存碰撞物體的信息;
        //Raycast(Ray ray, out RaycastHit hitInfo);
        if (Physics.Raycast(ray, out hitInfo, 100, layerMask, QueryTriggerInteraction.Ignore))
        {
            Debug.Log(hitInfo.transform.name);
            Debug.DrawLine(transform.position, hitInfo.point,Color.red,100);
        }
        //層級遮罩,設置只檢查哪一個層級的游戲物體,默認全部檢測
        //層級實質相當於枚舉項,值是2的冪次方,序號只是層級的索引
        //Raycast(Ray ray, float maxDistance, int layerMask);
        //如果檢測第八層,需要填寫256
        if (Physics.Raycast(ray, collider.gameObject.tag, 256))
        {
            Debug.Log(hitInfo.transform.name);
            Debug.DrawLine(transform.position, hitInfo.point, Color.red, 100);
        }
        //Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int layerMask);
        //Ray ray是射線;RaycastHit hitInfo是碰撞信息;float distance是碰撞距離;int layerMask是碰撞的層
        //RaycastAll穿過多個物體
        RaycastHit[] hitinfos = Physics.RaycastAll(ray,100);
        foreach (var item in hitinfos)
        {
            Debug.Log(item.transform.name);
        }
        //不僅發射攝像,還可以發射形狀物體
        //Physics.BoxCast();
        //Physics.CapsuleCast();
        //如何檢測一個人在地面上而不是在空中(二段跳判定)
        //1、在人物半身添加一個向下的射線,射線剛好接觸地面
        //2、在人物頭頂添加一個投射盒
        //特點:
        //射線是一幀判定
        //射線沒有運行時間
        //位運算符(二進制的加減乘除)
        //&與運算:有零即為零,全一才是一
        //1001010
        //1000111  &
        //-----------
        //1000010
        //|或運算:有一就是一,全零才是零
        //1001010
        //1110001   |
        //-----------
        //1111011
        //~非運算符:一變零,零變一
        //1101010  ~
        //-----------
        //1111011
        //^異或運算:相同即為零,不同即為一
        //1010001
        //1100010   ^
        //-----------
        //0110011
        //<<向左移:所有二進制位向高位進位,空出來的位補零
        //1010<<1
        //-----------
        //10100
        //>>向右移:所有二進制位向低位進位,移出位被丟棄,左邊移出的空位或者一律補0
        //1011>>1
        //-----------
        //0101
    }
    // Update is called once per frame
    void Update () {
              
       }
}
相交球:
Collider[] OverlapSphere(Vector3 position, float radius);
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BoomScript : MonoBehaviour {
   
    public float forceFactor = 10;


    private void OnCollisionEnter(Collision collision)
    {
        //生成橡膠球,檢測碰撞
        Collider[] colliders = Physics.OverlapSphere(transform.position, 10);
        //剔除自己和沒有加剛體的
        foreach (var item in colliders)
        {
            //剔除自己
            if (item.transform == transform)
            {
                continue;
            }
            //判斷剛體不等於空,防止與地面碰撞
            //attachedRigidbody,碰撞器附加的剛體,如果碰撞器沒有附加剛體返回null。
            if (item.attachedRigidbody != null)
            {
                float distance = Vector3.Distance(transform.position, item.transform.position);
                float forceValue = 1 / distance * forceFactor;
                Vector3 dir = (item.transform.position - transform.position).normalized;
                Vector3 force = dir * forceValue;
                item.attachedRigidbody.AddForce(force, ForceMode.Impulse);
            }
        }
    }
}

Line Renderer

線體渲染,添加顏色,Line Renderer 配合 ray射線 可以制作鐳射激光
用材質球渲染射線,粒子特效
Width曲線,調節粗細,添加關鍵幀,調節線體不同部位的粗細
畫復雜線段,多點添加
設置顏色的漸變

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerFire : MonoBehaviour {
    LineRenderer lineR;
    public Transform fireTrans;
    //方便對layer作調節
    public LayerMask layer;
    Ray ray;
    RaycastHit hit;
       void Start () {
        lineR = GetComponent<LineRenderer>();
    }
       
       void Update () {
        ray = new Ray(fireTrans.position, fireTrans.up);
        if(Physics.Raycast(ray, out hit, 1000, layer))
        {
            //hit.point
            lineR.positionCount = 2;
            lineR.SetPosition(0, fireTrans.position);
            lineR.SetPosition(1, hit.point);
        }
        else
        {
            lineR.positionCount = 0;
        }
       }
}

 

C#的委托和事件在Unity中的用法
委托 - Action:沒有返回值,沒有參數的,在using System命名空間下
帶一個參數,沒有返回值的委托怎么定義,public Action<float> OnValueChanged
委托變事件,直接加event
通過滑動條Value的變化,來調用委托
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class DeleTest : MonoBehaviour
{
    public float width = 100;
    public float height = 50;
    public event Action buttonClickCallback;
    public event Action<float> OnValueChanged;  // 事件 用來封裝委托的
    private float floatValue;
    public float FloatValue
    {
        get
        {
            return floatValue;
        }
        set
        {
            if (value != floatValue)
            {
                // 觸發事件
                if (OnValueChanged != null) OnValueChanged(value);
            }
            floatValue = value;
        }
    }
    public float size = 1;
    public GUIStyle sliderStyle;
    public GUIStyle thumbStyle;
    void Start()
    {
        FloatValue = 100;
    }
    void Update()
    {
    }
    private void OnGUI()
    {
        if (GUI.Button(new Rect((Screen.width - width) / 2, (Screen.height - height) / 2, width, height), "開始游戲"))
        {
            if (buttonClickCallback != null) buttonClickCallback();
        }
        //  public static float Slider(Rect position, float value, float size, float start, float end, GUIStyle slider, GUIStyle thumb, bool horiz, int id);
        //value = GUI.Slider(new Rect(10, 10, width, height), value, size, 0, 10, sliderStyle, thumbStyle, true, 0);
    }
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour {
       void Awake () {
        DeleTest del = GetComponent<DeleTest>();
        del.buttonClickCallback += SceneChange;
        del.OnValueChanged += MusicValueChange;
        //del.OnValueChanged();
    }
       
       void Update () {
              
       }
    void SceneChange()
    {
        Debug.Log("切換場景啦!!!!");
    }
    void MusicValueChange(float value)
    {
        Debug.Log("音量調節為了:" +value);
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM