引言
最近的項目中需要開發虛拟搖杆功能,由于曆史原因對于FingerGesture較為熟悉,故沒有采用EasyTouch。
NGUI中的UIDragObject
NGUI中有一個UIDragObject.cs元件,添加到GameObject,即可實作簡單的拖拽動作。
其中的Target需要設定被拖拽的對象,代碼注釋如下:
/// <summary>
/// Target object that will be dragged.
/// </summary>
public Transform target;
僅僅添加該元件是不夠的,想要捕獲滑鼠事件還需要在對象上添加Box Collider元件。
運作項目,就可以拖拽對象了。
分析虛拟搖杆需求
首先要虛拟搖杆分為兩部分,中間一小部分為中間的滑塊,周圍一圈是背景層。(資源是EasyTouch裡的)
操作同時也分為兩種情況:
1.拖拽中間的滑塊;
2.直接點選周圍的背景部分,滑塊直接跳轉到對應位置。
傳回什麼?
操作虛拟搖杆隻需傳回一個Vector3向量即可(從原點指向滑塊被拖拽位置,其實是一個二維向量,z值沒有用到。)
代碼實作
對于滑塊部分的操作可以借鑒NGUI中的UIDragObject的實作,隻需保留最基本的功能,隻用到了NGUI中的OnPress和OnDrag事件。
滑塊部分代碼如下:
using UnityEngine;
using System.Collections;
public class JoyStickDragObject : MonoBehaviour
{
public Transform target;
Vector3 mTargetPos; // 目标目前位置
Vector3 mLastPos;
int mTouchID = 0;
bool mStarted = false;
bool mPressed = false;
[SerializeField]
protected Vector3 scale = new Vector3(1f, 1f, 0f);
protected Vector3 originPos = Vector3.zero;
protected Vector3 offsetFromOrigin = Vector3.zero; // 原點到拖拽位置的向量
public Vector3 OffsetFromOrigin
{
set { offsetFromOrigin = value; }
get { return offsetFromOrigin; }
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnPress(bool pressed)
{
if (enabled && NGUITools.GetActive(gameObject) && target != null)
{
if (pressed)
{
if (!mPressed)
{
mTouchID = UICamera.currentTouchID;
mPressed = true;
mStarted = false;
CancelMovement();
}
}
else if (mPressed && mTouchID == UICamera.currentTouchID)
{
mPressed = false;
target.position = Vector3.zero;
}
}
}
void OnDrag(Vector2 delta)
{
Ray ray = UICamera.currentCamera.ScreenPointToRay(UICamera.currentTouch.pos);
float dist = 0f;
Vector3 currentPos = ray.GetPoint(dist);
///< 更新目前坐标到上一時刻坐标的向量
Vector3 offset = currentPos - mLastPos;
///< 更新目前坐标到原點的向量
UpdateVector3FromOrigin(currentPos);
mLastPos = currentPos;
if (!mStarted)
{
mStarted = true;
offset = Vector3.zero;
}
Debug.LogWarning("offset: " + offset + " OffsetFromOrigin: " + OffsetFromOrigin);
Move(offset);
}
void Move(Vector3 moveDelta)
{
mTargetPos += moveDelta;
target.position = mTargetPos;
}
void CancelMovement()
{
if (target != null)
{
Vector3 pos = target.localPosition;
target.localPosition = pos;
}
mTargetPos = (target != null) ? target.position : Vector3.zero;
}
///< 更新目前坐标到原點的向量
void UpdateVector3FromOrigin(Vector3 pos)
{
OffsetFromOrigin = pos - originPos;
}
}
背景層的處理與滑塊部分略有不同,主要在于點選背景層,滑塊需要直接移動到點選位置
背景層代碼如下:
using UnityEngine;
using System.Collections;
public class JoyStickBackground : MonoBehaviour
{
public Transform thumb;
private bool isReset = true;
[SerializeField]
protected Vector3 originPos = Vector3.zero; // 原點
protected Vector3 offsetFromOrigin = Vector3.zero; // 原點到拖拽位置的向量
public Vector3 OffsetFromOrigin
{
set { offsetFromOrigin = value; }
get { return offsetFromOrigin; }
}
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
}
void OnPress(bool pressed)
{
if (pressed)
{
Ray ray = UICamera.currentCamera.ScreenPointToRay(UICamera.currentTouch.pos);
float dist = 0f;
Vector3 currentPos = ray.GetPoint(dist);
thumb.position = currentPos;
isReset = false;
///< 更新目前坐标到原點的向量
UpdateVector3FromOrigin(currentPos);
}
else
{
thumb.position = Vector3.zero;
isReset = true;
}
}
void OnDrag(Vector2 delta)
{
Ray ray = UICamera.currentCamera.ScreenPointToRay(UICamera.currentTouch.pos);
float dist = 0f;
Vector3 currentPos = ray.GetPoint(dist);
thumb.position = currentPos;
}
///< 更新目前坐标到原點的向量
void UpdateVector3FromOrigin(Vector3 pos)
{
OffsetFromOrigin = pos - originPos;
}
}
效果圖:
拖拽滑塊:
點選背景: