Unity3D學習筆記(四):物理系統碰撞和預制體


Rigidbody(剛體組件):加了此組件游戲物體就變成剛體了
----Mass(質量,單位kg):重力G = 質量m * 重力加速度g(g=9.81 m/s^2)
--------沖量守恆定理 動量守恆定律:m1v1+m2v2=m1v1'+m2v2'
----Drag(空氣阻力):和摩擦力不同,與物體不接觸也有
----Angular Drag(旋轉角阻力):物體自身旋轉與空氣的阻力,值越大,旋轉越慢
----Use Gravity(是否使用重力):默認勾選,Gravity的值可以修改,默認值-9.81

自由落體(勻變速運動)需要掌握的三個公式
輕重物體的自由下落速度是相同的,即重力加速度的大小都是相同的。
加速度a(單位時間速度變化量) = 重力加速度g
初速度Vo=0
末速度Vt=gt
1、vt = v0 + gt
2、h = 1/2 * gt^2(h是下落的高度,g是重力加速度,t是運動時間)
3、2as = vt^2 - v0^2
平拋運動:平拋+自由落體
拋物線運動:上拋+自由落體
----Is Kinematic(此剛體是否為運動學剛體):不會受到力的影響(改變運動和旋轉),只能使用transform讓運動學剛體動起來。
--------讓物體移動三種方法:改坐標,施加力,加動畫。
----Interpolate(剛體抖動修正):當你的剛體遇到抖動時,可以選擇其中一種去解決,下一幀,上一幀
--------修正剛體運動的下一幀,讓變化進行平滑過度
----Collision Detection(碰撞檢測頻率):越往下檢測的精度就越高,相應的,性能消耗就越大,所以不推薦大家使用高精度的檢測。(子彈:射線檢測,客戶端都是騙人的)
防止物體運動速度過快,穿過其他物體。

----Constraints:約束(凍結)某一根軸,或者位移,或者旋轉,凍結偏移度

 
剛體的作用
1、受到力的影響發生位移
2、和其他游戲物體發生碰撞
 
發生碰撞的必要條件是什么?
1、所有想要發生碰撞的游戲物體都必須帶有碰撞器組件,Edit Colider:編輯碰撞器的輪廓
2、至少一方帶有剛體組件,最好是運動的一方(長時間不動,剛體會休眠的)
3、如果一方是運動學剛體,想要發生碰撞,另外一方必須是非運動學剛體
Collision:是發生碰撞信息的集合(另外一個物體的信息)
collider:和我發生碰撞的另外一個物體的碰撞器
contactPoint[] contacts:碰撞點數組
obsolete:棄用
gameObject:和我發生碰撞的另外一個物體
other:另外一個物體的組件
relativeVelocity:發生碰撞的相對速度
rigidbody:另外一個物體的剛體
transform:另外一個物體的坐標

 
Is Trigger(觸發器):就是將Collider碰撞器身上的對勾勾上,就變成了觸發器,沒有碰撞效果。
發生觸發的必要條件是什么?
1、所有想要發生觸發的游戲物體都必須帶有碰撞器組件
2、至少一方帶有剛體組件,最好是運動的一方(長時間不動,剛體會休眠的)
3、和碰撞不同,和運動學剛體沒有必要關系,只要是剛體就行,無論是不是運動學剛體
只要一方有觸發器,兩方都沒有碰撞效果,但兩方都會調用觸發器

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CollisionTest : MonoBehaviour {
    //檢測碰撞
    //Collision是類,是發生碰撞信息的集合(另一個物體的信息)
    //兩個物體,發生接觸的時候
    private void OnCollisionEnter(Collision collision)
    {
        Debug.Log("我進來了!");
        Debug.Log(collision.gameObject.name);
    }
    //兩個物體,持續接觸的時候
    private void OnCollisionStay(Collision collision)
    {
        Debug.Log("我在里面了!");
    }
    //兩個物體,發生分離的時候
    private void OnCollisionExit(Collision collision)
    {
        Debug.Log("我出來了!");
    }
    //觸發器檢測
    //Collider是碰撞器的引用,包含於collision
    //觸發器和觸發器或碰撞器,發生接觸的時候
    private void OnTriggerEnter(Collider other)
    {
        Debug.Log("觸發了!");
    }
    private void OnTriggerStay(Collider other)
    {
       
    }
    private void OnTriggerExit(Collider other)
    {
       
    }
}

 

預制體Prefab:
存檔:序列化,就像類的實例化
讀檔:反序列化
預制體,在檢視面板多出三個按鈕
選擇,還原,應用改變到游戲物體
場景里的游戲物體和資源文件夾的預制體,兩者的生命周期不同,Unity不允許將場景里的游戲物體拖到預制體里,一旦切換場景就會丟失游戲物體。
 
工程之間遷移資源
1、拖拽生成預制體(母體)
2、導出資源包
3、導入資源包
4、拖拽預制體到層級面板(藍色就是克隆的預制體,紅色表示丟失了預制體),斷掉預制體關聯,可恢復正常顏色

 

Unity復習

牆體碰撞
凍結牆體的位置和旋轉,防止被撞動,也可以防止剛體進入休眠(還是會碰撞,只是不會動)
不凍結牆體,經過幾秒鍾,就會進入休眠,休眠狀態依然可以碰撞(運動學剛體和非運動學剛體)
判定休眠狀態:GUILayout.Label("Sleep :" + rig.IsSleeping());
判定碰撞狀態:void OnCollisionEnter(Collision collision) { Debug.Log("有碰撞到");}
喚醒休眠剛體:void Update () { rig.WakeUp();}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WallTest : MonoBehaviour {
    Rigidbody rig;
    private void Awake()
    {
        rig = GetComponent<Rigidbody>();
    }
    // Use this for initialization
    void Start()
    {
          // 可以碰撞的 (運動學干剛體和非運動學剛體)
          // 凍結的時候 剛體會進入休眠嗎?    不會                 
          // 如果不凍結的狀態 經過幾秒種以后 就會進入休眠狀態       
    }
    private void OnGUI()
    {
        GUILayout.Label("Sleep :" + rig.IsSleeping());
    }
    void OnCollisionEnter(Collision collision)
    {
        Debug.Log("有碰撞到");
    }
    // Update is called once per frame
    void Update () {
        rig.WakeUp();   // 喚醒
              
       }
}
子彈
加剛體,去重力,不下落
tag標簽,給游戲物體分類,通過獲取標簽,判斷是哪個物體的

子彈銷毀:延時銷毀,集中銷毀

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletMove : MonoBehaviour {
    public float moveSpeed = 10;
    // Use this for initialization
    void Start()
    {
        Destroy(gameObject, 10);
    }
       // Update is called once per frame
       void Update () {
              
       }
    void FixedUpdate()
    {
        transform.Translate(Vector3.up * moveSpeed * Time.deltaTime);
    }
    private void OnCollisionEnter(Collision collision)
    {
        if(collision.gameObject.tag == "Enemy")
        {
            // 敵人掉血
            EnemyInfo enemyInfo = collision.gameObject.GetComponent<EnemyInfo>();
            if(enemyInfo) enemyInfo.GetDamage(Random.Range(5, 25));
            // 子彈銷毀
            Destroy(gameObject);
        }
    }
}
角色控制
Instantiate實例化一個子彈,Instantiate是有返回值的,可以用於修改子彈的移動速度,Space.World改成世界的Y軸
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControl : MonoBehaviour {
    // 子彈的預制體
    public GameObject bulletPrefab;     // 資源面板中的
    // 生成的位置
    public Transform firePos; 
    public float moveSpeed = 1;
    public float rotSpeed = 1;
       // Use this for initialization
       void Start () {
              
       }
       
       // Update is called once per frame
       void Update () {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            // 發射子彈 在某個位置 實例化一個子彈
            GameObject bullet = Instantiate(bulletPrefab, firePos.position, firePos.rotation);
            BulletMove bulletMove = bullet.GetComponent<BulletMove>();
            bulletMove.moveSpeed = 20;
        }
              
       }
    // 物理相關的 寫在 FixedUpdate
    private void FixedUpdate()
    {
        transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime * Input.GetAxis("Vertical"));
        transform.Rotate(Vector3.up * rotSpeed * Time.deltaTime * Input.GetAxis("Horizontal"), Space.World);
    }
}

敵人信息

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyInfo : MonoBehaviour {
    public int hp = 100;
       // Use this for initialization
       void Start () {
              
       }
       
       // Update is called once per frame
       void Update () {
              
       }
    public void GetDamage(int dmg)
    {
        hp -= dmg;
        if(hp <= 0)
        {
            hp = 0;
            Destroy(gameObject);
        }
    }
}

敵人控制

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyControl : MonoBehaviour {
    public float moveSpeed = 1;
    Transform playerTrans;
       // Use this for initialization
       void Start () {
        GameObject player = GameObject.Find("Player");
        if(player)
        {
            playerTrans = player.transform;    // 如果沒有找到主角 會報 空引用
        }
    }
       
       // Update is called once per frame
       void Update () {
        transform.LookAt(playerTrans);
        transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
              
       }
}

敵人生成點:需要生成的預制體,需要生成的位置

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnEnemy : MonoBehaviour {
    // 需要生成的預制體
    public GameObject enemyPrefab;
    float spawnInterval;
    float timeCount = 0;
       // Use this for initialization
       void Start () {
        spawnInterval = Random.Range(5, 11);
    }
       
       // Update is called once per frame
       void Update () {
        timeCount += Time.deltaTime;
        if(timeCount >= spawnInterval)
        {
            Instantiate(enemyPrefab, transform.position, Quaternion.identity);  //  Quaternion.identity 表示沒有旋轉
            spawnInterval = Random.Range(5, 11);
            timeCount = 0;
        }
              
       }
}

 


免責聲明!

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



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