Unity3D學習筆記(二十三):事件接口、虛擬搖桿、層級管理和背包系統
阿新 • • 發佈:2019-02-12
ram veh ces 跟隨鼠標 style 組件 屏幕 向上 grid 事件接口
IDragHandler(常用):鼠標按下拖動時執行(只要鼠標在拖動就一直執行)
IDropHandler:對象拖動結束時,如果鼠標在物體的範圍內,執行一次(依賴於IDragHandler存在)
(結束時鼠標必須在圖片範圍內)
IBeginDragHandler:開始拖動時執行一次
IEndDragHandler:拖動結束時執行一次(結束時對鼠標在哪沒有要求)
IScrollHandler:監控鼠標滾輪
using System; using System.Collections; using System.Collections.Generic; using UnityEngine;PointerEventData: button:鼠標按下時判斷左右鍵 clickCount:點擊次數(時間間隔固定) delta:拖動時鼠標的偏移量(一般用在拖動的事件接口中) dragging:是否處於拖動狀態 enterEventCamera:鼠標進入時的事件相機 pressEventCamera:鼠標按下時的事件相機 pointerDrag:拖動的物體(一般用在拖動接口裏) pointerEnter:進入的物體 pointerPress: pointerCurrentRaycast:鼠標當前的射線檢測結果 pointerPressRaycast:鼠標按下時的射線檢測結果 scrollDelta:鼠標滾輪的 使用EvenData類的參數時,首先要考慮有無意義 例如,在鼠標進入的事件接口裏,無法獲得拖動的物體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() { } }
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學習筆記(二十三):事件接口、虛擬搖桿、層級管理和背包系統