Unity筆記 第一天

與3D物體交互

  • 思路

    第一步,我們想在Unity3D中交互的時候,首先我們想到的是射線,調用Ray這個API,這樣我們就可以用我們的鼠標(鍵盤)來與3D物體交互了,在這個案例中我用的是鼠標與之交互,如果有興趣的可以用鍵盤試一試,我在下一篇中將會使用鍵盤與之交互,並且製作類似於喫雞或者APG遊戲中拾取物體那樣。

    第二步,交互一般都是有UI或者是窗口,當觸發一個事件時將UI彈出來。

    第三步,製作UI。

  • 步驟

	 private void MouseClickRay()
	    {
	        
	        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
	
	        if (Physics.Raycast(ray, out hit, 50, ClickCub.value))
	        {
	            WindosOfCube.Instance.ClickCubeisShow();
	            Debug.Log("被檢測的物體的名字:" + hit.collider.gameObject.name);
	        }
	    }

我在TouchCube這個類中寫了用鼠標控制射線的方法
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
這樣就可以將射線與鼠標綁定;下面的ClickCub我定義的是LayerMask,通過給物體設 置不同的層級,也可以用Tag(標籤),來區分要交互的物體。

然後,這裏我遇到一個坑,我開始想的的在UpDate裏面去使用它,然後控制它每次點擊只會運行一次,但是在經歷的多次嘗試以後發現,我無法控制它,只能降低其頻率,可能是我的方法不太對,我下來在試一試,如果成功我會在下一篇或者下下篇進行講解,不過我找到了另一種方法,那就是OnMousexxx,這裏有個小知識點
(Event和Input.GetMousexxx事件會被任何gameobject監控到,而OnMousexxx事件只會被該腳本附加上的gameobject監控到),Inpput.GetMousexxx要寫在Update中,就會出現每幀調用的現象,而OnMousexxx只會在過載的gameobject中才可以,而且只運行一次。

接下來,就可以開始寫UI的邏輯了,這個面板是不是在開始的時候應該隱藏起來,有很多種方法,比如,先將UI移出Canvas,需要的時候在移回來,或者直接讓面板開始不可見,然後需要的時候在顯示,這樣他的位置就不需要移動,還有一種不太可取的方法就是,需要的時候實例化出來,用完就銷燬,然後反覆這個操作,各有個的特點,不過我用的是第二種方法,將其添加CanvasGroup組件,然後可以修改透明度值,就可以達到這種效果,怎麼簡單怎麼來。

需要隱藏的時候:

canvasGroupWindos.GetComponent<CanvasGroup>().alpha = 0;
canvasGroupWindos.GetComponent<CanvasGroup>().interactable = false;
canvasGroupWindos.GetComponent<CanvasGroup>().blocksRaycasts = false;

需要顯示的時候:

canvasGroupWindos.GetComponent<CanvasGroup>().alpha = 1;
canvasGroupWindos.GetComponent<CanvasGroup>().interactable = true;
canvasGroupWindos.GetComponent<CanvasGroup>().blocksRaycasts = true;

我將另外兩個腳本寫成單例,調用的時候就比較簡單了,寫按鈕的時候我用了拉姆達表達式,匿名委託來表示回調,也是比較的簡單,(寫代碼,簡單明瞭實現功能就可以了,不需要搞得太複雜)這樣一個與3D物體的交互就完成了。

以下是源代碼和腳本的名字

ClickManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ClickManager : MonoBehaviour
{

    public Button CloseBtn;

    private void Start()
    {
        //lambda(拉姆達)匿名委託
        CloseBtn.onClick.AddListener(()=> {
            WindosOfCube.Instance.ButtonWindosClose();
        });
    }
}

WindosOfCube.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class WindosOfCube : MonoBehaviour
{
    //單例,方便其他腳本調用
    public static WindosOfCube Instance;

    private void Awake()
    {
        Instance = this;
    }
    
    public CanvasGroup canvasGroupWindos;

    //設置一個布爾條件保護
    bool isShow;

    void Start()
    {
        isShow = true;
        if (isShow)
        {
            //開始先將窗口UI隱藏起來
            canvasGroupWindos.GetComponent<CanvasGroup>().alpha = 0;
            canvasGroupWindos.GetComponent<CanvasGroup>().interactable = false;
            canvasGroupWindos.GetComponent<CanvasGroup>().blocksRaycasts = false;
            
        }
    }

    public void ClickCubeisShow()
    {
        //當isShow爲true時將UI顯示出來
        if (isShow)
        {
            canvasGroupWindos.GetComponent<CanvasGroup>().alpha = 1;
            canvasGroupWindos.GetComponent<CanvasGroup>().interactable = true;
            canvasGroupWindos.GetComponent<CanvasGroup>().blocksRaycasts = true;
        }
    }

    public void ButtonWindosClose()
    {
        if (isShow)
        {
            canvasGroupWindos.GetComponent<CanvasGroup>().alpha = 0;
            canvasGroupWindos.GetComponent<CanvasGroup>().interactable = false;
            canvasGroupWindos.GetComponent<CanvasGroup>().blocksRaycasts = false;
        }
    }
}

TouchCube.cs

using UnityEngine;

public class TouchCube : MonoBehaviour
{

    RaycastHit hit;

    public LayerMask ClickCub;

    private void MouseClickRay()
    {
        
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        if (Physics.Raycast(ray, out hit, 50, ClickCub.value))
        {
            WindosOfCube.Instance.ClickCubeisShow();
            Debug.Log("被檢測的物體的名字:" + hit.collider.gameObject.name);
        }
    }

    private void OnMouseDown()
    {
        MouseClickRay();
    }


    /*這個是我之前的錯誤方法,代碼寫錯了,可以註釋掉
    知道整個完成了以後就可以刪掉,這樣有助於思路的擴展,也會減少代碼的書寫
    private bool isState = true;
    void Update()
    {
        //if (isState)
        //{
            //Debug.Log("come  2222");

            if (isState && Input.GetKey(KeyCode.Mouse0))
            {
                Debug.Log("come 333");
                
                isState = false;
            }
        isState = true; 
            
        //}
    }
    */
}

效果圖

點擊前
在這裏插入圖片描述
點擊後
在這裏插入圖片描述
這次沒用動圖,下次一定~

我用的版本爲Unity2018.3.5

https://pan.baidu.com/s/1Xg5el7psfpN2lNzJCC_9oA
提取碼:2j2g

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