筆記14 燈光、預設體、3d物體的事件、碰撞體、剛體、炸箱子、觸發器、物理材質、射線

燈光

基本項

在這裏插入圖片描述

烘焙

在這裏插入圖片描述

燈光的種類

在這裏插入圖片描述

Lighting窗口

在這裏插入圖片描述

預設體

瞭解預設體

在這裏插入圖片描述

利用代碼操作預設體

實例化預設體Instantiate

在這裏插入圖片描述

    //預設體的類型也是GameObject,名字是CubePre。
    public GameObject CubePre;
    //注意這一步:在unity中,將預設體關聯到腳本的變量上來。
    void Start () {
        /*法一:實例化到指定位置。
預設體,位置(中心),旋轉(默認四元數。此處設爲不轉)。返回值是剛生成的物體。*/
        GameObject go = Instantiate(CubePre, transform.position, Quaternion.identity);
        //法二:不指定位置的實例化。
        Instantiate(CubePre);
    }

刪除

位置:Start

刪除物體

        /*刪除物體。一般是在一幀完了之後刪除。
 不能寫在Update裏,因爲這個刪除是有延遲的,和垃圾回收機制一樣。*/
        Destroy(go);

3秒之後刪除

        Destroy(go, 3f);   //3秒之後刪除

立刻刪除

       //立刻刪除(強制刪除)。可以寫在Update裏。費性能,少用。
        DestroyImmediate(go);   

刪除組件

        //刪除組件。例如刪除AudioSource組件
        Destroy(GetComponent<AudioSource>());

3d物體的事件

注意:該物體需勾已選碰撞器這個組件;在Game窗口進行操作

鼠標移動進物體,在物體範圍內,離開物體

 //鼠標移動進物體
    private void OnMouseEnter()
    {
        Debug.Log("Enter");
    }
    //鼠標在物體範圍內
    private void OnMouseOver()
    {
        Debug.Log("Over");
    }
    //鼠標離開物體
    private void OnMouseExit()
    {
        Debug.Log("Exit");
    }

鼠標按下,擡起,按下並擡起

//鼠標按下
    private void OnMouseDown()
    {
        Debug.Log("Down");
    }
    //鼠標擡起。如果按下是在物體上,那麼一出物體時,擡起是調用的
    private void OnMouseUp()
    {
        Debug.Log("Up");
    }
    //按下並擡起(上面兩個方法的結合)。按下並擡起必須都在物體身上
    private void OnMouseUpAssButton()
    {
        Debug.Log("Butten")
    } 

按下持續調用

//按下持續調用(可用於拖拽,但拖拽更多是用射線)
    private void OnMouseDrag()
    {
        Debug.Log("Drag");
    } 

碰撞體、剛體

兩個物體產生碰撞的條件:兩個物體都要有碰撞體,且至少一個有剛體。
注意:運行時添加的組件,在運行結束後會消失。

Unity裏

在這裏插入圖片描述

代碼

產生碰撞的時候會調用OnCollisionEnter

    //產生碰撞的時候會調用。
    /*unity裏面的碰撞器是Collider,但代碼中Colision是一個類,它裏面包含一些數據信息。
    裏面可以找到碰撞器、遊戲物體、剛體等。 */
    private void OnCollisionEnter(Collision collision)
    {
    
    } 

當碰撞結束的時候會調用OnCollisionExit

 //當碰撞結束的時候會調用
    private void OnCollisionExit(Collision collision)
    {
        Debug.Log("Exit");
    }

獲得碰撞的物體的碰撞器,碰撞點,碰撞法線

    //產生碰撞的時候會調用。
    private void OnCollisionEnter(Collision collision)
    {
        //獲得碰撞的物體的碰撞器
        Collider collider = collision.collider;
        Debug.Log("Enter" + collider.name);   //此時獲得的是地面

        //碰撞點。它是個數組,因爲物體不同,碰撞點的個數不同。
        Vector3 point = collision.contacts[0].point;
        //碰撞法線
        Vector3 normal = collision.contacts[0].normal;
    } 

移動物體

法一:無剛體時用。有剛體,速度特別快時,不能用(遇牆抖動)。

void Update () {
        //移動物體,法一:無剛體時用。有剛體,速度特別快時,不能用。向前每秒走十米   
        transform.Translate(transform.forward * 10 *Time.deltaTime);  
    } 

法二:給力Rbody.AddForce(利用剛體,只給一次力。所以速度是越來越慢的)

    //移動物體,法二、法三:利用剛體
    private Rigidbody Rbody;

	void Start () {
        //先得到物體身上的剛體組件
        Rbody = GetComponent<Rigidbody>();
        //法二:給力(給一次。所以速度是越來越慢的 )。方向(前方向量)* 力
        Rbody.AddForce(transform .forward * 300f);		
	}

法三:給速度Rbody.velocity(利用剛體)

    //移動物體,法二、法三:利用剛體
    private Rigidbody Rbody;

	void Start () {
        //先得到物體身上的剛體組件
        Rbody = GetComponent<Rigidbody>();
    }
    
    void Update () {
        /*移動物體,法三:給速度。velocity代表當前物體的速度。
        transform.forward我的前方,如果是會滾動的物體,那麼它的前方是會發生改變,
        所以注意是否需要鎖定滾動。*/
        Rbody.velocity = transform.forward * 10;
        
        //勻速移動。Vector3.forward世界的前方,方向不會變。
        Rbody.velocity = Vector3.forward * 10;
    } 

在這裏插入圖片描述

炸箱子

課程代碼

    //產生碰撞的時候會調用。
    /*unity裏面的碰撞器是Collider,但代碼中Colision是一個類,它裏面包含一些數據信息。
    裏面可以找到碰撞器、遊戲物體、剛體等。 */
    private void OnCollisionEnter(Collision collision)
    {
        //爆炸範圍半徑5m
        float r = 5;
        //Physics物理的類,它有很多方法,比如此處的OverlapSphere。
        //得到圓心爲collision.contacts[0].point,半徑爲r的圓中間的所有碰撞體。
        Collider[] colliders = Physics.OverlapSphere(collision.contacts[0].point,r);
        //在unity裏面把箱子的標籤統一成Box
        //遍歷碰撞體
        foreach(Collider collider in colliders)
        {
            //判斷是不是可以被擊飛的箱子
            if(collider.tag == "Box")
            {
                /*給箱子添加爆炸力。首先拿它的剛體GetComponent,
          然後給它一個爆炸力AddExplosionForce,參數:力(50),爆炸點(圓心),半徑(r)*/
                collider.GetComponent<Rigidbody>().AddExplosionForce(500f, collision.contacts[0].point, r);
            }
        } 

複習自寫代碼

   //產生碰撞時調用
    void OnCollisionEnter(Collision collision)
    {
        //爆炸半徑
        float radius = 5f;
        //爆炸點
        Vector3 point = collision.contacts[0].point;
        //拿到要炸的物體
        Collider[] colliders = Physics.OverlapSphere(point, radius);
        //遍歷物體,找到要炸的
        for(int i = 0; i < colliders.Length; i++)
        {
            if (colliders[i].CompareTag("Box"))
            {
                //給爆炸力
                colliders[i].GetComponent<Rigidbody>().AddExplosionForce(500f, point, radius);
            }
        }
    }

觸發器

在這裏插入圖片描述
下面的實例中,腳本在球上,讓球穿過立方體,立方體的觸發器應該打上勾。

進入觸發區域調用

 //進入觸發區域調用。other代表你(球)進入的那個物體(立方體)的觸發器
    private void OnTriggerEnter(Collider other)
    {
        //打印觸發器的名字,結果是立方體
        Debug.Log("Enter" + other.name); 
    }

離開觸發區域調用

     //離開觸發區域調用
    private void OnTriggerExit(Collider other)
    {
        Debug.Log("Exit");
    } 

物理材質

在這裏插入圖片描述

射線

畫出射線

 void Start () {
        //射線。射線的起始點,射線向量。從003的點向下4米的射線。
        Ray ray = new Ray(Vector3.up * 3, Vector3.down * 4);
	}
	
	void Update () {
        //畫出射線
        Debug.DrawRay(Vector3.up * 3, Vector3.down * 4);                    
	}

檢測碰撞

法一:只顯示第一個碰撞點

   void Start () {
        //射線。射線的起始點,射線向量。從003的點向下4米的射線。
        Ray ray = new Ray(Vector3.up * 3, Vector3.down * 4);
        //取得射線碰撞的物體。RaycastHit碰撞數據結構體。
        RaycastHit hit;   //聲明一個碰撞數據結構體。 
        /*檢測射線碰撞。out的意思就是,我們把hit傳進去,
            它在內部可以給hit賦值,之後我們就可以把hit拿出來了。*/       
        bool res = Physics.Raycast(ray, out hit);
        if (res == true)
        {
             //鼠標點在地面上。打印碰撞點(只會打印第一個碰撞點)。
             //Debug.Log("鼠標點在:" + hit.point);
         }
	}
	
	void Update () {
        //畫出射線
        Debug.DrawRay(Vector3.up * 3, Vector3.down * 4);
            }
        }
	}

法二:RaycastHit[]碰撞點的集合

  void Start () {
        //射線。射線的起始點,射線向量。從003的點向下4米的射線。
        Ray ray = new Ray(Vector3.up * 3, Vector3.down * 4);
        //取得射線碰撞的物體。RaycastHit碰撞數據結構體。
        RaycastHit hit;   //聲明一個碰撞數據結構體。
        
        //法二:檢測射線碰撞
        RaycastHit[] hits = Physics.RaycastAll(ray);
	}
	
	void Update () {
        //畫出射線
        Debug.DrawRay(Vector3.up * 3, Vector3.down * 4);
            }
        }
	}

鼠標點在地面上

	   void Update () {
        if(Input.GetMouseButtonDown(0))
        {
            //取得射線。Camera.main主攝像機。屏幕座標的位置
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            //取得射線碰撞的物體。RaycastHit碰撞數據結構體。
            RaycastHit hit;   //聲明一個碰撞數據結構體。
            /*檢測射線碰撞。
 意思就是,我們把hit傳進去,它在內部可以給hit賦值,之後我們就可以把hit拿出來了。*/
            bool res = Physics.Raycast(ray, out hit);
            if (res == true)
            {
                //鼠標點在地面上。打印碰撞點(只會打印第一個碰撞點)。
                Debug.Log("鼠標點在:" + hit.point);
            }
        }
	}

物體向鼠標點擊的位置移動

 public class ReyTest : MonoBehaviour {
    //目標點traget
    private Vector3 target;
	 
	void Start () {
        //首先,目標點位置就是自身位置
        target = transform.position;   
	}
	
	// Update is called once per frame
	void Update () {
        if(Input.GetMouseButtonDown(0))
        {
            //取得射線。Camera.main主攝像機。屏幕座標的位置
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            //取得射線碰撞的物體。RaycastHit碰撞數據結構體。
            RaycastHit hit;   //聲明一個碰撞數據結構體。
            /*檢測射線碰撞。out的意思就是,我們把hit傳進去,
            它在內部可以給hit賦值,之後我們就可以把hit拿出來了。*/
            bool res = Physics.Raycast(ray, out hit, 500f,1<<LayerMask.NameToLayer("Ground"));
            if (res == true)
            {
                //鼠標點在地面上。打印碰撞點(只會打印第一個碰撞點)。
                //Debug.Log("鼠標點在:" + hit.point);
               
                //之後,將鼠標點擊的位置賦值給目標點
                target = hit.point;
                //如果希望Y軸不變,則等於它自身的Y值
                target.y = transform.position.y;
            }
            //判斷一下目標位置和我的位置之間的距離,如果大於0.3就向目標距離前進
            if(Vector3.Distance(target,transform.position)> 0.3f)
            {
                //得到向量。(目標位置-我的位置),然後轉換成單位向量,這樣便於計算速度。
                Vector3 dir = (target - transform.position).normalized;
                //轉向這個向量。Quaternion四元數
                transform.rotation = Quaternion.LookRotation(dir);
                //前進
                transform.Translate(Vector3.forward * 2 * Time.deltaTime);
            }
        }
	}
}

特別說明

法一:(ray, out hit)兩個參數(會出現牆後位置不能到達的問題)

            //法一:(ray, out hit)兩個參數。會出現牆後位置不能到達的問題。
//檢測射線碰撞。out的意思就是,我們把hit傳進去,它在內部可以給hit賦值,之後我們就可以把hit拿出來了。
            bool res = Physics.Raycast(ray, out hit);

法二:四個參數(指定與哪一層進行檢測,解決牆後位置不能到達的問題)

參數3:射線長度是500米。參數4:第幾層(層Ground在第8層)。
第四個參數:
1、左移運算符<<
2、導致兩種寫法:比如此處都是要檢測地面。
3、第四個參數還影響着:如果不想和誰檢測。
即將第四個參數用小括號括起來,前面加波浪線。例如:~(1<<8)

寫法一:1<<8 查看地面是哪一層,把層數寫在這裏,此處爲8.
            /*左移運算符<<。LayerMask:1<<層數,就代表和這層進行射線檢測。
            如果是兩層,則加|隔開,例如:1<<8 | 1<<9*/
            //法一:1<<8   查看地面是哪一層,把層數寫在這裏,此處爲8. 
            bool res = Physics.Raycast(ray, out hit, 500f,1<<8);
寫法二:1<<LayerMask.NameToLayer(“Ground”) 直接寫要檢測的物體的名字,此處爲地面
    //法二:1<<LayerMask.NameToLayer("Ground") 直接寫要檢測的物體的名字,此處爲地面
            bool res = Physics.Raycast(ray, out hit, 500f,1<<LayerMask.NameToLayer("Ground"));

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章