一:效果演示
二:使用
——创建一个可操作的区域Joystick作为父物体,调整Joystick大小以控制可以操作的区域
——在可操作区域下创建摇杆背景Background
——在摇杆背景下创建摇杆控制柄Thumb
——将脚本挂载到可操作的区域Joystick上
三:代码实现
using UnityEngine.EventSystems;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 虚拟摇杆
/// </summary>
public class VirtualJoystick : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
{
[Header("摇杆类型")]
public JoystickType type;
[Header("摇杆背景")]
public RectTransform background;
[Header("摇杆控制柄")]
public RectTransform thumb;
bool inDrag;//是否在拖拽中
float maxDragDist;//最大拖拽距离
private Vector2 v;//方向+位移
#region external interfaces
/// <summary>
/// 得到方向+位移
/// </summary>
public Vector2 GetDirAndDist()
{
return v;
}
/// <summary>
/// 得到方向
/// </summary>
public Vector2 GetDir()
{
return v.normalized;
}
#endregion
private void Start()
{
background.GetComponent<Image>().raycastTarget = false;
thumb.GetComponent<Image>().raycastTarget = false;
maxDragDist = background.rect.width / 2;
if (type == JoystickType.PosCanChange
|| type == JoystickType.FollowMove)
{
UpdateShow(false);
}
}
public void OnBeginDrag(PointerEventData eventData)
{
inDrag = true;
if (type == JoystickType.PosCanChange
|| type == JoystickType.FollowMove)
{
background.localPosition = Screen2UI(eventData.position, background.parent as RectTransform, eventData.pressEventCamera);
UpdateShow(true);
}
}
public void OnDrag(PointerEventData eventData)
{
Vector2 targetLocalPos = Screen2UI(eventData.position, thumb.parent as RectTransform, eventData.pressEventCamera);
Vector2 targetDir = targetLocalPos.normalized;
float dist = Vector2.Distance(targetLocalPos, Vector2.zero);
if (dist > maxDragDist)
{
if (type == JoystickType.FollowMove)
{
float offset = dist - maxDragDist;
background.transform.localPosition += (Vector3)targetDir * offset;
}
thumb.localPosition = targetDir * maxDragDist;
}
else
{
thumb.localPosition = targetDir * dist;
}
v = targetDir * dist;
}
public void OnEndDrag(PointerEventData eventData)
{
v = Vector2.zero;
inDrag = false;
if (type == JoystickType.PosCanChange
|| type == JoystickType.FollowMove)
{
UpdateShow(false);
}
}
private void Update()
{
if (!inDrag)
{
thumb.anchoredPosition = Vector2.Lerp(thumb.anchoredPosition, Vector2.zero, 0.1f);
}
}
/// <summary>
/// 更新显示
/// </summary>
void UpdateShow(bool isShow)
{
background.gameObject.SetActive(isShow);
thumb.gameObject.SetActive(isShow);
}
/// <summary>
/// 屏幕坐标转UI坐标
/// </summary>
Vector2 Screen2UI(Vector2 v, RectTransform rect, Camera camera = null)
{
Vector2 pos;
RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, v, camera, out pos);
return pos;
}
}
/// <summary>
/// 摇杆类型
/// </summary>
public enum JoystickType
{
Normal,//固定位置
PosCanChange,//可变位置
FollowMove,//跟随移动
}