1. 程式人生 > >Unity3D學習筆記(二十三):事件接口、虛擬搖桿、層級管理和背包系統

Unity3D學習筆記(二十三):事件接口、虛擬搖桿、層級管理和背包系統

ram veh ces 跟隨鼠標 style 組件 屏幕 向上 grid

事件接口 IDragHandler(常用):鼠標按下拖動時執行(只要鼠標在拖動就一直執行) IDropHandler:對象拖動結束時,如果鼠標在物體的範圍內,執行一次(依賴於IDragHandler存在) (結束時鼠標必須在圖片範圍內) IBeginDragHandler:開始拖動時執行一次 IEndDragHandler:拖動結束時執行一次(結束時對鼠標在哪沒有要求) IScrollHandler:監控鼠標滾輪
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events; using UnityEngine.EventSystems; public class EventDrag : MonoBehaviour, IDragHandler, IDropHandler, IBeginDragHandler, IEndDragHandler, IPointerEnterHandler, IPointerUpHandler, IPointerClickHandler { public void OnDrag(PointerEventData eventData) { Debug.Log(
"IDragHandler.OnDrag"); //Debug.Log("eventData.delta:" + eventData.delta);//上次執行與本次執行的鼠標偏移量 Debug.Log("eventData.scrollDelta:" + eventData.scrollDelta);//上次執行與本次執行的鼠標偏移量 } public void OnDrop(PointerEventData eventData) { Debug.Log("IDropHandler.OnDrop"); }
public void OnBeginDrag(PointerEventData eventData) { Debug.Log("IBeginDragHandler.OnBeginDrag"); } public void OnEndDrag(PointerEventData eventData) { Debug.Log("IEndDragHandler.OnEndDrag"); } public void OnPointerEnter(PointerEventData eventData) { //Debug.Log("eventData.delta.name" + eventData.pointerDrag.name);//報錯:在鼠標進入的事件接口裏,無法獲得拖動的物體 } public void OnPointerUp(PointerEventData eventData) { Debug.Log("當前的結果:" + eventData.pointerCurrentRaycast.gameObject.name); Debug.Log("按下的結果:" + eventData.pointerPressRaycast.gameObject.name); } public void OnPointerClick(PointerEventData eventData) { Debug.Log("點擊次數:" + eventData.clickCount); } // Use this for initialization void Start() { } // Update is called once per frame void Update() { } }
PointerEventData: button:鼠標按下時判斷左右鍵 clickCount:點擊次數(時間間隔固定) delta:拖動時鼠標的偏移量(一般用在拖動的事件接口中) dragging:是否處於拖動狀態 enterEventCamera:鼠標進入時的事件相機 pressEventCamera:鼠標按下時的事件相機 pointerDrag:拖動的物體(一般用在拖動接口裏) pointerEnter:進入的物體 pointerPress: pointerCurrentRaycast:鼠標當前的射線檢測結果 pointerPressRaycast:鼠標按下時的射線檢測結果 scrollDelta:鼠標滾輪的 使用EvenData類的參數時,首先要考慮有無意義 例如,在鼠標進入的事件接口裏,無法獲得拖動的物體
    public void OnPointerEnter(PointerEventData eventData)
    {
        //Debug.Log("eventData.delta.name" + eventData.pointerDrag.name);//報錯:在鼠標進入的事件接口裏,無法獲得拖動的物體
    }

技術分享圖片

射線檢測結果:按下結果和當前結果是有差別的

    public void OnPointerUp(PointerEventData eventData)
    {
        Debug.Log("當前的結果:" + eventData.pointerCurrentRaycast.gameObject.name);
        Debug.Log("按下的結果:" + eventData.pointerPressRaycast.gameObject.name);
    }

技術分享圖片

RaycastResult - gameObject:一般情況下,判斷檢測結果是誰的(常用) 連續點擊的次數,在一定時間間隔內,會累積計數,超過時間間隔則歸零重新計數
    public void OnPointerClick(PointerEventData eventData)
    {
        Debug.Log("點擊次數:" + eventData.clickCount);
    }

技術分享圖片

鼠標有球形滾輪,數值是二維的

技術分享圖片

虛擬搖桿案例

技術分享圖片

畫布設置1280x720

技術分享圖片

輪盤功能

技術分享圖片

輪盤的代碼邏輯

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
//1、鼠標在搖桿背景下按下的時候,需要把搖桿移動到鼠標按下的位置
//2、鼠標在拖動的時候,搖桿需要跟隨鼠標移動
//3、鼠標松開的時候,搖桿回到中心位置
//4、搖桿的拖動範圍是一個圓形區域
    //1)、鼠標在圓形區域內,搖桿跟著鼠標移動
    //2)、鼠標超出圓形區域,搖桿要在圓的邊緣
//5、默認情況搖桿是隱藏的,當鼠標按下時顯示,只有在屏幕左下方有效
    //創建一張透明圖片,在屏幕的左下方
    //當在這個透明圖片的區域內按下時,整個搖桿的輪盤到鼠標的位置,並且顯示
    //松開鼠標時,隱藏輪盤
public class Rocker : MonoBehaviour,
    IDragHandler,
    IPointerDownHandler,
    IPointerUpHandler
{
    private GameObject handler;//搖桿的句柄,也就是跟隨鼠標移動的物體
    private GameObject rocker;//搖桿的輪盤
    private float r = 90f;//圓形區域的半徑
    private RectTransform handlerParent;//句柄的父物體的Rect Transform
    private RectTransform rockerParent;//輪盤的父物體的Rect Transform
    private Vector2 outPos;//轉換之後的位置坐標
    private void Awake()
    {
        handler = GameObject.Find("HandlerBig/HandlerSmall");
        rocker = GameObject.Find("HandlerBig"); ;
        //找到父物體的Rect Transform
        handlerParent = handler.transform.parent as RectTransform;      
        rockerParent = handler.transform.parent as RectTransform;
    }
    public void OnDrag(PointerEventData eventData)
    {
        //拖動時,遙感句柄跟隨鼠標移動
        MoveHandler(eventData);
    }
    public void OnPointerDown(PointerEventData eventData)
    {
        PlayerMove.movespeed = 0.1f;
        //按下時,輪盤顯示,輪盤到鼠標的位置,同時輪盤在鼠標的位置
        rocker.SetActive(true);
        //轉換輪盤的坐標
        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
            rockerParent,
            eventData.position,
            eventData.pressEventCamera,
            out outPos
            ))
        {
            rocker.transform.localPosition = outPos;
        }
        //按下時,遙感句柄移到鼠標位置
        MoveHandler(eventData);
    }
    public void OnPointerUp(PointerEventData eventData)
    {
        //擡起時,輪盤隱藏
        rocker.SetActive(false);
        //擡起時,遙感句柄回到中心位置
        rocker.transform.localPosition = Vector3.zero;
        PlayerMove.movespeed = 0f;
    }
    /// <summary>
    /// 封裝好的移動句柄的方法
    /// </summary>
    /// <param name="eventData"></param>
    void MoveHandler(PointerEventData eventData)
    {
        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
            handlerParent,
            eventData.position,
            eventData.pressEventCamera,
            out outPos
            ))
        {
            //判斷鼠標在圓內還是圓外,通過圓的中心點指向鼠標點的向量的模長來判斷
            //1、計算圓心指向鼠標向量的模長
            //Vector2 temp = outPos - Vector.zero;//outPos就是從圓心指向鼠標的向量
            if (outPos.magnitude >= r)
            {
                //計算圓心指向鼠標的方向 outPos.normalized
                //最終位置 - 原點位置 + 在圓心指向鼠標的方向上,移動半徑個距離的向量
                //Vector2 temp = outPos.normalized * r + Vector3.zero;
                Vector2 temp = outPos.normalized * r;
                handler.transform.localPosition = temp;
            }
            else
            {
                handler.transform.localPosition = outPos;
            }
        }
    }
    // Use this for initialization
    void Start()
    {
        rocker.SetActive(false);//默認隱藏
    }
    // Update is called once per frame
    void Update()
    {
    }
}
在C#中,<summary> 標記應當用於描述類型或類型成員。 生成<summary>註釋的方法很簡單,在方法之前輸入 /// 就會自動生成。 移動的功能 技術分享圖片

移動的代碼邏輯

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMove : MonoBehaviour {
    public static float movespeed = 0.1f;
    public GameObject handler;//遙感句柄
    private Vector3 moveDir;
       // Use this for initialization
       void Start () {
              
       }
       
       // Update is called once per frame
       void Update () {
        //計算圓心指向搖桿的向量
        //Vector3 temp = handler.transform.localPosition - Vector3.zero;
        //temp = handler.transform.localPosition
        moveDir.x = handler.transform.localPosition.x;
        moveDir.y = 0;
        moveDir.z = handler.transform.localPosition.y;
        transform.Translate(moveDir * Time.deltaTime * movespeed);
    }
}

層級管理

技術分享圖片

代碼操作層級

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LayerManager : MonoBehaviour {
    private GameObject red;
    private GameObject yellow;
    private GameObject blue;
    // Use this for initialization
    void Start () {
        red = GameObject.Find("Red");
        yellow = GameObject.Find("Yellow");
        blue = GameObject.Find("Blue");
        //red.transform.SetSiblingIndex(2);
        int temp = red.transform.GetSiblingIndex();
        red.transform.SetSiblingIndex(blue.transform.GetSiblingIndex());
        blue.transform.SetSiblingIndex(temp);
    }
       
       // Update is called once per frame
       void Update () {
              
       }
}
背包案例 Grid Layout Group(網格自動布局) Padding:距離邊界的距離 Cell Size:子物體元素的大小 Spacing:元素間的間隔、 Start Corner:第一個元素的位置,起點位置 Start Axis:排列的軸向 Child Alignment:對其方式 Constraint:約束,沒有約束, ----Fixed Row Count:約束行數 ----Fixed Column Count:約束列數 註意:9元素,3行4行一樣,拿走1個會缺一塊,整列拿走重排又會多出第5行 背包布局 技術分享圖片

背包拖動

技術分享圖片

拖動的代碼邏輯

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;
//1、控制物品的拖動
//2、顯示物品
public class GridUI : MonoBehaviour,
    IDragHandler,
    IBeginDragHandler,
    IEndDragHandler
{
    public Transform tempParent;//臨時的父節點
    public string imageName;//物體圖片的名字,如果名字不為“”時有物品,為“”時沒有物品
    private Image image;//顯示物品的組件,拖動的也是他
    private RectTransform imageParent;
    private Vector2 outPos;
    private Vector2 offSet;//鼠標開始拖動時,距離圖片中心點的偏移量
    private void Awake()
    {
        image = transform.Find("Image").GetComponent<Image>();
        image.raycastTarget = false;//關閉image的射線檢測,避免擋住Grid
        imageParent = tempParent as RectTransform;
    }
    public void OnDrag(PointerEventData eventData)
    {
        if (imageName == "")
        {
            return;
        }
        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
            imageParent,
            eventData.position,
            eventData.enterEventCamera,
            out outPos
            ))
        {
            image.transform.localPosition = outPos - offSet;
        }
    }
    public void OnBeginDrag(PointerEventData eventData)
    {
        if (imageName == "")
        {
            return;
        }
        //開始時,把圖片放在臨時的父節點上,保證拖動的圖片永遠顯示在最前面
        image.transform.parent = tempParent;
        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
            imageParent,
            eventData.position,
            eventData.enterEventCamera,
            out outPos
            ))
        {
            //計算鼠標距離圖片中心點的偏移量
            offSet = outPos - new Vector2(image.transform.localPosition.x, image.transform.localPosition.y);
        }
    }
    public void OnEndDrag(PointerEventData eventData)
    {
        if (imageName == "")
        {
            return;
        }
        //結束時,需要把圖片的父節點還原,位置也需要歸零
        image.transform.parent = transform;
        //image.transform.SetParent(transform);
        image.transform.localPosition = Vector3.zero;
        //拖動結束時,判斷當前的鼠標位置是否在格子上
        if (eventData.pointerCurrentRaycast.gameObject != null &&
            eventData.pointerCurrentRaycast.gameObject.CompareTag("Grid"))
        {
            Debug.Log("格子:" + eventData.pointerCurrentRaycast.gameObject.name);
            //把自己的圖片給對方,把對方的拿過來
            GridUI target = eventData.pointerCurrentRaycast.gameObject.GetComponent<GridUI>();
            //把自己的圖片名字設置給目標,temp就是對方的圖片名字
            string temp = target.SetSpriteName(this.imageName);
            //然後把對方的圖片名字設置給自己
            this.SetSpriteName(temp);
        }
        else
        {
            Debug.Log("不是格子");
        }
    }
    void UpdateItem()
    {
        if (imageName == "")
        {
            image.enabled = false;
        }
        else
        {
            image.enabled = true;
            if (image.sprite.name != imageName)
            {
                Sprite sp = Resources.Load<Sprite>("Backpack/ICon/" + imageName);
                image.sprite = sp;
            }
        }
    }
    //設置自己圖片的名字,返回值是之前的名字
    public string SetSpriteName(string str)
    {
        string before = imageName;
        imageName = str;
        UpdateItem();
        return before;
    }
    // Use this for initialization
    void Start()
    {
        UpdateItem();
    }
    // Update is called once per frame
    void Update()
    {
    }
}

拖動的臨時父節點,保證圖片在最上方顯示

技術分享圖片

添加Grid標簽

技術分享圖片

給圖片添加名字

技術分享圖片

Unity3D學習筆記(二十三):事件接口、虛擬搖桿、層級管理和背包系統