Unity3D基于UGUI實現(xiàn)虛擬搖桿
虛擬搖桿在移動游戲開發(fā)中,是很常見的需求,今天我們在Unity中,使用UGUI來實現(xiàn)一個簡單的虛擬搖桿功能。
1.打開Unity,新創(chuàng)建一個UIJoystick.cs腳本,代碼如下:
using UnityEngine;
using UnityEngine.EventSystems;
public class UIJoystick : MonoBehaviour, IDragHandler, IEndDragHandler
{
/// <summary>
/// 被用戶拖動的操縱桿
/// </summary>
public Transform target;
/// <summary>
/// 操縱桿可移動的最大半徑
/// </summary>
public float radius = 50f;
/// <summary>
/// 當前操縱桿在2D空間的x,y位置
/// 搖桿按鈕的值【-1,1】之間
/// </summary>
public Vector2 position;
//操縱桿的RectTransform組件
private RectTransform thumb;
void Start()
{
thumb = target.GetComponent<RectTransform>();
}
/// <summary>
/// 當操縱桿被拖動時觸發(fā)
/// </summary>
public void OnDrag(PointerEventData data)
{
//獲取搖桿的RectTransform組件,以檢測操縱桿是否在搖桿內(nèi)移動
RectTransform draggingPlane = transform as RectTransform;
Vector3 mousePos;
//檢查拖動的位置是否在拖動rect內(nèi),
//然后設置全局鼠標位置并將其分配給操縱桿
if (RectTransformUtility.ScreenPointToWorldPointInRectangle (draggingPlane, data.position, data.pressEventCamera, out mousePos)) {
thumb.position = mousePos;
}
//觸摸向量的長度(大?。?
//計算操作桿的相對位置
float length = target.localPosition.magnitude;
//如果操縱桿超過了搖桿的范圍,則將操縱桿設置為最大半徑
if (length > radius) {
target.localPosition = Vector3.ClampMagnitude (target.localPosition, radius);
}
//在Inspector顯示操縱桿位置
position = target.localPosition;
//將操縱桿相對位置映射到【-1,1】之間
position = position / radius * Mathf.InverseLerp (radius, 2, 1);
}
/// <summary>
/// 當操縱桿結束拖動時觸發(fā)
/// </summary>
public void OnEndDrag(PointerEventData data)
{
//拖拽結束,將操縱桿恢復到默認位置
position = Vector2.zero;
target.position = transform.position;
}
}
2.如圖創(chuàng)建UGUI,所用資源可在網(wǎng)上自行下載。

效果圖如下:

3.打包運行即可。這樣一個簡單的虛擬搖桿就實現(xiàn)了。
下面是對以上虛擬搖桿代碼的擴展(ps:只是多了一些事件,便于其他腳本訪問使用)廢話不多說來代碼了
using System;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
//
// Joystick component for controlling player movement and actions using Unity UI events.
// There can be multiple joysticks on the screen at the same time, implementing different callbacks.
//
public class UIJoystick : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
///
/// Callback triggered when joystick starts moving by user input.
///
public event Action onDragBegin;
///
/// Callback triggered when joystick is moving or hold down.
///
public event Action onDrag;
///
/// Callback triggered when joystick input is being released.
///
public event Action onDragEnd;
///
/// The target object i.e. jostick thumb being dragged by the user.
///
public Transform target;
///
/// Maximum radius for the target object to be moved in distance from the center.
///
public float radius = 50f;
///
/// Current position of the target object on the x and y axis in 2D space.
/// Values are calculated in the range of [-1, 1] translated to left/down right/up.
///
public Vector2 position;
//keeping track of current drag state
private bool isDragging = false;
//reference to thumb being dragged around
private RectTransform thumb;
//initialize variables
void Start()
{
thumb = target.GetComponent();
//in the editor, disable input received by joystick graphics:
//we want them to be visible but not receive or block any input
#if UNITY_EDITOR
Graphic[] graphics = GetComponentsInChildren();
// for(int i = 0; i < graphics.Length; i++)
// graphics[i].raycastTarget = false;
#endif
}
///
/// Event fired by UI Eventsystem on drag start.
///
public void OnBeginDrag(PointerEventData data)
{
isDragging = true;
if(onDragBegin != null)
onDragBegin();
}
///
/// Event fired by UI Eventsystem on drag.
///
public void OnDrag(PointerEventData data)
{
//get RectTransforms of involved components
RectTransform draggingPlane = transform as RectTransform;
Vector3 mousePos;
//check whether the dragged position is inside the dragging rect,
//then set global mouse position and assign it to the joystick thumb
if (RectTransformUtility.ScreenPointToWorldPointInRectangle(draggingPlane, data.position, data.pressEventCamera, out mousePos))
{
thumb.position = mousePos;
}
//length of the touch vector (magnitude)
//calculated from the relative position of the joystick thumb
float length = target.localPosition.magnitude;
//if the thumb leaves the joystick's boundaries,
//clamp it to the max radius
if (length > radius)
{
target.localPosition = Vector3.ClampMagnitude(target.localPosition, radius);
}
//set the Vector2 thumb position based on the actual sprite position
position = target.localPosition;
//smoothly lerps the Vector2 thumb position based on the old positions
position = position / radius * Mathf.InverseLerp(radius, 2, 1);
}
//set joystick thumb position to drag position each frame
void Update()
{
//in the editor the joystick position does not move, we have to simulate it
//mirror player input to joystick position and calculate thumb position from that
#if UNITY_EDITOR
target.localPosition = position * radius;
target.localPosition = Vector3.ClampMagnitude(target.localPosition, radius);
#endif
//check for actual drag state and fire callback. We are doing this in Update(),
//not OnDrag, because OnDrag is only called when the joystick is moving. But we
//actually want to keep moving the player even though the jostick is being hold down
if(isDragging && onDrag != null)
onDrag(position);
}
///
/// Event fired by UI Eventsystem on drag end.
///
public void OnEndDrag(PointerEventData data)
{
//we aren't dragging anymore, reset to default position
position = Vector2.zero;
target.position = transform.position;
//set dragging to false and fire callback
isDragging = false;
if (onDragEnd != null)
onDragEnd();
}
}
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
VS2013創(chuàng)建Windows服務與調(diào)試服務的圖文方法
這篇文章主要介紹了VS2013創(chuàng)建Windows服務與調(diào)試服務的圖文方法,需要的朋友可以參考下2017-02-02
C# OleDbDataReader快速數(shù)據(jù)讀取方式(3種)
這篇文章主要介紹了C# OleDbDataReader快速數(shù)據(jù)讀取方式(3種),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-12-12
C# 字符串string和內(nèi)存流MemoryStream及比特數(shù)組byte[]之間相互轉(zhuǎn)換
本文主要介紹字符串string和內(nèi)存流MemoryStream及比特數(shù)組byte[]之間相互轉(zhuǎn)換的方法,需要的小伙伴可以參考一下。2016-05-05

