實(shí)現(xiàn)效果
本文最終實(shí)現(xiàn)效果:
一,實(shí)現(xiàn)思路
1.1 原理解析
做一個(gè)實(shí)驗(yàn)看一下使用ScrollRect
組件實(shí)現(xiàn)搖桿的原理。
-
在
Hierarchy
面板右鍵UI
->Scroll View
創(chuàng)建一個(gè)滾動(dòng)視圖,這個(gè)組件經(jīng)常被應(yīng)用于排行榜,選角色之類的可滑動(dòng)的界面。 -
在
Scroll View
->Viewport
->Content
添加一個(gè)Image組件 -
運(yùn)行場景,鼠標(biāo)點(diǎn)擊并拖動(dòng)中間部分,即可看到如下效果:
看到這里基本了解實(shí)現(xiàn)思路了吧,其實(shí)就是通過Scroll Rect
組件的Context和Viewport的關(guān)系來進(jìn)行模擬的。
更多關(guān)于ScrollRect的使用方法和實(shí)戰(zhàn)應(yīng)用,可以查看:Unity 之 UGUI Scroll Rect滾動(dòng)矩形組件詳解
1.2 思路概述
-
隨手指落下位置
思路:其實(shí)就是根據(jù)手指第一次落下的屏幕坐標(biāo),修改搖桿的初始位置;手抬起時(shí)再將搖桿位置還原
知識(shí)點(diǎn):獲取手指按下和抬起的回調(diào),將手指落下坐標(biāo)轉(zhuǎn)換為屏幕UI坐標(biāo) -
搖桿移動(dòng)
思路:使用Scroll Rect
的移動(dòng)回調(diào),來控制中間的虛擬搖桿進(jìn)行位置變化
注意的點(diǎn):使用OnDrag進(jìn)行回調(diào),并來控制虛擬搖桿的標(biāo)移動(dòng)位置不要超出背景 -
移動(dòng)回調(diào)
思路:當(dāng)使用搖桿時(shí)使用Update進(jìn)行實(shí)時(shí)回調(diào)
注意的點(diǎn):使用OnEndDrag進(jìn)行回調(diào),還原要個(gè)位置
二,實(shí)現(xiàn)代碼
2.1 隨手落下
通過錨點(diǎn)和RectTransformUtility
坐標(biāo)轉(zhuǎn)換方法進(jìn)行位置設(shè)置。
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
[RequireComponent(typeof(EventTrigger))]
public class JoystickTouch : ScrollRect
{
protected override void Start()
{
EventTrigger trigger = GetComponent<EventTrigger>();
EventTrigger.Entry entryPointerUp = new EventTrigger.Entry();
entryPointerUp.eventID = EventTriggerType.PointerUp;
entryPointerUp.callback.AddListener((data) => { OnPointerUp((PointerEventData)data); });
trigger.triggers.Add(entryPointerUp);
EventTrigger.Entry entryPointerDown = new EventTrigger.Entry();
entryPointerDown.eventID = EventTriggerType.PointerDown;
entryPointerDown.callback.AddListener((data) => { OnPointerDown((PointerEventData)data); });
trigger.triggers.Add(entryPointerDown);
}
// 隨手落下設(shè)置搖桿位置
private void OnPointerDown(PointerEventData eventData)
{
Vector2 LocalPosition;
RectTransformUtility.ScreenPointToLocalPointInRectangle(this.GetComponent<RectTransform>(),
eventData.position, eventData.pressEventCamera, out LocalPosition);
this.viewport.localPosition = LocalPosition;
}
// 抬起還原位置
private void OnPointerUp(PointerEventData eventData)
{
this.viewport.anchoredPosition3D = Vector3.zero;
}
}
2.2 搖桿轉(zhuǎn)動(dòng)
還是在上面的類中重寫OnDrag
方法,進(jìn)行虛擬搖桿中間位置的控制。
public class JoystickTouch : ScrollRect
{
// 半徑 -- 控制拖拽區(qū)域
private float mRadius;
protected override void Start()
{
mRadius = this.content.sizeDelta.x * 0.5f;
}
public override void OnDrag(PointerEventData eventData)
{
base.OnDrag(eventData);
joyIsCanUse = true;
//虛擬搖桿移動(dòng)
Vector3 contentPosition = this.content.anchoredPosition;
if (contentPosition.magnitude > mRadius)
{
contentPosition = contentPosition.normalized * mRadius;
SetContentAnchoredPosition(contentPosition);
}
// 搖桿內(nèi)部按鈕旋轉(zhuǎn)
//if (content.anchoredPosition.y != 0)
//{
// content.eulerAngles = new Vector3(0, 0,
// Vector3.Angle(Vector3.right, content.anchoredPosition) * content.anchoredPosition.y /
// Mathf.Abs(content.anchoredPosition.y) - 90);
//}
}
}
三,源碼分享
3.1 場景搭建
創(chuàng)建三個(gè)Image一個(gè)作為一個(gè)的子物體,依次為:接收點(diǎn)擊背景面積,搖桿背景板,搖桿中的虛擬按鈕。
第一個(gè)Image掛載新建腳本JoystickTouch
場景搭建如下:
3.2 完整代碼
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
[RequireComponent(typeof(EventTrigger))]
public class JoystickTouch : ScrollRect
{
/// <summary>
/// 拖動(dòng)差值
/// </summary>
public Vector2 offsetValue;
// 半徑 -- 控制拖拽區(qū)域
private float mRadius;
/// <summary>
/// 移動(dòng)中回調(diào)
/// </summary>
public System.Action<RectTransform> JoystickMoveHandle;
/// <summary>
/// 移動(dòng)結(jié)束回調(diào)
/// </summary>
public System.Action<RectTransform> JoystickEndHandle;
/// <summary>
/// 搖桿是否處于可用狀態(tài)
/// </summary>
public bool joyIsCanUse = false;
protected override void Start()
{
mRadius = this.content.sizeDelta.x * 0.5f;
EventTrigger trigger = GetComponent<EventTrigger>();
EventTrigger.Entry entryPointerUp = new EventTrigger.Entry();
entryPointerUp.eventID = EventTriggerType.PointerUp;
entryPointerUp.callback.AddListener((data) => { OnPointerUp((PointerEventData)data); });
trigger.triggers.Add(entryPointerUp);
EventTrigger.Entry entryPointerDown = new EventTrigger.Entry();
entryPointerDown.eventID = EventTriggerType.PointerDown;
entryPointerDown.callback.AddListener((data) => { OnPointerDown((PointerEventData)data); });
trigger.triggers.Add(entryPointerDown);
}
protected override void OnEnable()
{
joyIsCanUse = false;
offsetValue = Vector2.zero;
}
public override void OnDrag(PointerEventData eventData)
{
base.OnDrag(eventData);
joyIsCanUse = true;
//虛擬搖桿移動(dòng)
Vector3 contentPosition = this.content.anchoredPosition;
if (contentPosition.magnitude > mRadius)
{
contentPosition = contentPosition.normalized * mRadius;
SetContentAnchoredPosition(contentPosition);
}
// 搖桿內(nèi)部按鈕旋轉(zhuǎn)
//if (content.anchoredPosition.y != 0)
//{
// content.eulerAngles = new Vector3(0, 0,
// Vector3.Angle(Vector3.right, content.anchoredPosition) * content.anchoredPosition.y /
// Mathf.Abs(content.anchoredPosition.y) - 90);
//}
}
private void FixedUpdate()
{
if (joyIsCanUse)
{
JoystickMoveHandle?.Invoke(this.content);
offsetValue = this.content.anchoredPosition3D;
}
}
public override void OnEndDrag(PointerEventData eventData)
{
base.OnEndDrag(eventData);
joyIsCanUse = false;
offsetValue = Vector2.zero;
JoystickEndHandle?.Invoke(this.content);
}
// 隨手落下設(shè)置搖桿位置
private void OnPointerDown(PointerEventData eventData)
{
Vector2 LocalPosition;
RectTransformUtility.ScreenPointToLocalPointInRectangle(this.GetComponent<RectTransform>(),
eventData.position, eventData.pressEventCamera, out LocalPosition);
this.viewport.localPosition = LocalPosition;
}
// 抬起還原位置
private void OnPointerUp(PointerEventData eventData)
{
this.viewport.anchoredPosition3D = Vector3.zero;
}
}
3.3 實(shí)現(xiàn)效果
按鈕素材圖片:
實(shí)現(xiàn)效果:文章來源:http://www.zghlxwxcb.cn/news/detail-796342.html
工程下載:源碼和步驟都在上面分享過了,若還有什么不明白的,可以 點(diǎn)擊鏈接下載 ,積分不夠的童鞋關(guān)注下方卡片,回復(fù):“搖桿” 即可獲得開篇Demo源碼~文章來源地址http://www.zghlxwxcb.cn/news/detail-796342.html
到了這里,關(guān)于Unity 之 使用原生UGUI實(shí)現(xiàn)隨手移動(dòng)搖桿功能經(jīng)典實(shí)例的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!