可能大家都聽說過大名鼎鼎的easytouch,然而easytouch是基於UGUI的,兩種不同的UI混用,可能會造成專案管理的混亂,並且可能會出現各種么蛾子,比如事件傳遞互相擾亂的問題。
於是就想找一種基於NGUI的搖桿,搜尋網上的文章,都有很多問題,總結來說三個問題很突出。
一:程式碼本事存在缺陷或者BUG,或者想得太簡單,比如沒有考慮手指相對按鈕的偏移,造成實際並不實用,只能用來學習。
二:號稱是NGUI的搖桿,但是有些實現卻用了UGUI的東西。
三:未考慮通用性,引數都是固定值,什麼43啊73啊,都不知道這些值怎麼來的。
於是自己寫吧,NGUI怎麼用就不教了。
①首先,建立兩個Sprite(我這裡偷懶用了2DSprite,因為不用打包圖片)和一個Texture。
NGuiJoystick是搖桿的底盤,Thumb是搖桿的按鈕,NGuiJoystickArea用於Dynamic模式的顯示區域。
Dynamic模式:類似於EasyTouch外掛的Dynamic模式,平時不顯示搖桿,手指按下在手指處顯示搖桿,放開手指搖桿消失。
注意:三個UI物件名字隨意,但是層級關係不能錯。
②修改NGuiJoystick和Thumb的紋理圖片並調整到你想要的合適大小(這裡最好長寬相等,因為不等我沒有試過行不行),給NGuiJoystick和Thumb都Attack上Collider。設定NGuiJoystick的depth為100,Thumb的depth為101(儘可能處於最上層,當然也可根據需求來改)。
③修改NGuiJoystickArea的大小(根據Dynamic模式下你想顯示的區域,我這裡鋪滿了全屏),Attack上Collider,修改NGuiJoystickArea的紋理(我這裡用了一張白色方向紋理),設定NGuiJoystickArea的color hint的值為(255,,255,255,50),修改depth為1(如果UIRoot和UICamera都是預設值0的話)。
④接下來就是程式碼部分。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class JoyStickControl : MonoBehaviour { public enum ShowType{Static,Dynamic}; //顯示模式 public ShowType showType= ShowType.Static; public float radiusOffset = 0.0F; //半徑偏移值、用於圖片問題造成的偏差進行微調 public GameObject area = null; //Dynamic模式下的顯示區域 private float radius; //底盤半徑 private float ratio=1.0F; //縮放值 private bool isPress = false; //是否是按下狀態 private bool isFirstPress = false; //是否第一次按下 private Vector2 offset; //手指相對於按鈕的偏移值 private void Awake() { //獲取底盤半徑 UI2DSprite parentSpirite = transform.parent.GetComponent<UI2DSprite>(); float parentWidth = parentSpirite.width; radius = parentWidth / 2.0F+ radiusOffset; //獲取縮放值 UIRoot root = GameObject.FindObjectOfType<UIRoot>(); if (root != null) { // 實際尺寸和設計尺寸比例 ratio = (float)root.activeHeight / Screen.height; } //如果是Dynamic模式、一開始隱藏搖桿、並將Area設定到近乎透明 if (showType == ShowType.Dynamic) { transform.parent.gameObject.SetActive(false); if (area != null) { UITexture areaTexture = area.GetComponent<UITexture>(); areaTexture.color = new Color(1.0F, 1.0F, 1.0F, 1.0F/255.0F); } } else { if (area != null) { area.SetActive(false); } } } // Update is called once per frame private void Update() { // 觸控按下 if (isPress) { //最後一次觸控位置、基於螢幕座標 Vector2 touchpos = UICamera.lastEventPosition; //獲取搖桿按鈕的螢幕座標 Vector2 childCenterPos = UICamera.currentCamera.WorldToScreenPoint(transform.position); //第一次觸控的時候獲取手指相對於按鈕的偏移值 if (!isFirstPress) { offset = touchpos - childCenterPos; isFirstPress = true; } //獲取搖桿底盤的螢幕座標 Vector2 centerPos = UICamera.currentCamera.WorldToScreenPoint(transform.parent.position); //獲取touchpos - offset和centerPos之間的距離值 //凡是用到touchpos - offset的地方絕對不能用childCenterPos替代、可以考慮下為什麼 float distance = Vector2.Distance(touchpos - offset, centerPos); //如果距離小於半徑,則將按鈕位置移動到touchpos - offset位置 //distance算到的相對距離,需要乘以縮放值 if (distance * ratio < radius)// 距離在父精靈背景中圓內,radius為其半徑 { Vector3 worldTouchPos = UICamera.currentCamera.ScreenToWorldPoint(touchpos - offset); transform.position = worldTouchPos; } //距離超過半徑、則把按鈕的位置設定在底盤的圓上 else { transform.localPosition = (touchpos - offset - centerPos).normalized * radius; childCenterPos = UICamera.currentCamera.WorldToScreenPoint(transform.position); } } // 觸控抬起、那麼把按鈕位置恢復到原點、 將isFirstPress置否,如果是Dynamic模式、還要隱藏搖桿 else { if (showType == ShowType.Dynamic) { transform.parent.gameObject.SetActive(false); } transform.localPosition = Vector2.zero; isFirstPress = false; } } // 觸控按下、isPress為true、抬起為false public void OnPress(bool isPress) { this.isPress = isPress; } //用於Dynamic模式press事件的響應 public void startTouch() { if (showType == ShowType.Dynamic) { transform.parent.gameObject.SetActive(true); Vector2 startTouchPos = UICamera.lastEventPosition; Vector2 startTouchWorldPos = UICamera.currentCamera.ScreenToWorldPoint(startTouchPos); transform.parent.position = startTouchWorldPos; this.isPress = true; } } //用於Dynamic模式release事件的響應 public void endTouch() { if (showType == ShowType.Dynamic) { transform.parent.gameObject.SetActive(false); } transform.localPosition = Vector2.zero; isFirstPress = false; } }
⑤把指令碼拖到thumb物件上,並且把NGuiJoystickArea拖到指令碼的public成員上。
⑥增加一個事件觸發器,NGuiJoystickArea->Add Component->NGUI->Interaction->Event Trigger。
⑦將Thumb拖到觸發器press事件上,並設定響應函式為startTouch();將Thumb拖到觸發器release事件上,並設定響應函式為endTouch()。
【預覽】
過幾天再上傳和人物的關聯文章,實現EasyTouch的allow turn and move,已經DeadValue等一些配置引數。
【本文為原創文章,CSDN部落格釋出作者和部落格園作者為同一作者,特此說明】