可能大家都聽說過大名鼎鼎的easytouch,然而easytouch是基于UGUI的,兩種不同的UI混用,可能會造成項目管理的混亂,并且可能會出現各種幺蛾子,比如事件傳遞互相擾亂的問題。
于是就想找一種基于NGUI的搖杆,搜尋網上的文章,都有很多問題,總結來說三個問題很突出。
一:代碼本事存在缺陷或者BUG,或者想得太簡單,比如沒有考慮手指相對按鈕的偏移,造成實際并不實用,隻能用來學習。
二:号稱是NGUI的搖杆,但是有些實作卻用了UGUI的東西。
三:未考慮通用性,參數都是固定值,什麼43啊73啊,都不知道這些值怎麼來的。
于是自己寫吧,NGUI怎麼用就不教了。
①首先,建立兩個Sprite(我這裡偷懶用了2DSprite,因為不用打包圖檔)和一個Texture。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIx0DciV2dmADM30zd-cGcq5CRzUCRzUydadHctxEeBpnTxkFVNBTVU5EdRpXTzkERNpXTq50dRRUT0EEVPhXQq1EdJpmTy0EROBDOD90drRVT3lkeMlXWq5keRRkT2NmMiNnSywEd5ITW110MaZHetlVdO1GT0UERNl3YXJGc5kHT20ESjBjUIF2Lc12bj5SYphXa5VWen5WY35iclN3Ztl2Lc9CX6MHc0RHaiojIsJye.jpg)
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部落格釋出作者和部落格園作者為同一作者,特此說明】