首先展示一下本文章实现的效果:
创建两个UI图像,一个用于表示背景,作为父物体,命名为JoyStick,一个表示摇杆,命名为Center。
背景图像选择一个圆,最好加点半透明的属性,最终完成图如下图所示。
创建一个脚本,命名为Joystick,然后将脚本挂载到JoyStick物体上,我们将通过这个脚本来实现摇杆。
我们首先需要在Awake() 方法中,获取摇杆背景的 RectTransform 组件和手柄的RectTransfomr组件。
background = GetComponent<RectTransform>();
handle = transform.GetChild(0).GetComponent<RectTransform>(); // 摇杆手柄是背景的子元素
background 变量保存了背景的 RectTransform 组件,handle 变量保存了摇杆手柄的 RectTransform 组件。
接下来,编写一个方法,用于处理拖动事件,代码如下所示。
public void OnDrag(PointerEventData eventData)
{
Vector2 touchPosition = Vector2.zero;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(background, eventData.position, eventData.pressEventCamera, out touchPosition))
{
// 获取触摸位置相对于摇杆背景的百分比
touchPosition.x = (touchPosition.x / background.sizeDelta.x)*2;
touchPosition.y = (touchPosition.y / background.sizeDelta.y)*2;
touchPosition = (touchPosition.magnitude > 1f) ? touchPosition.normalized : touchPosition;
// 更新摇杆手柄的位置
handle.anchoredPosition = new Vector2(touchPosition.x * (background.sizeDelta.x / 2), touchPosition.y * (background.sizeDelta.y / 2));
// 更新输入方向
inputDirection = touchPosition;
}
}
OnDrag(PointerEventData eventData) 方法用于处理拖动事件。在该方法中,首先通过 RectTransformUtility.ScreenPointToLocalPointInRectangle() 方法将触摸位置从屏幕坐标系转换为摇杆背景的本地坐标系。然后将触摸位置转换成相对于摇杆背景的百分比,这样摇杆手柄就能够根据触摸位置的百分比调整自己的位置。最后更新输入方向变量。
using UnityEngine;
using UnityEngine.EventSystems;
public class Joystick : MonoBehaviour, IDragHandler, IPointerUpHandler, IPointerDownHandler
{
private RectTransform background; // 摇杆背景
private RectTransform handle; // 摇杆手柄
private Vector2 inputDirection; // 输入方向
private void Awake()
{
background = GetComponent<RectTransform>();
handle = transform.GetChild(0).GetComponent<RectTransform>(); // 摇杆手柄是背景的子元素
}
public void OnDrag(PointerEventData eventData)
{
Vector2 touchPosition = Vector2.zero;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(background, eventData.position, eventData.pressEventCamera, out touchPosition))
{
// 获取触摸位置相对于摇杆背景的百分比
touchPosition.x = (touchPosition.x / background.sizeDelta.x)*2;
touchPosition.y = (touchPosition.y / background.sizeDelta.y)*2;
touchPosition = (touchPosition.magnitude > 1f) ? touchPosition.normalized : touchPosition;
// 更新摇杆手柄的位置
handle.anchoredPosition = new Vector2(touchPosition.x * (background.sizeDelta.x / 2), touchPosition.y * (background.sizeDelta.y / 2));
// 更新输入方向
inputDirection = touchPosition;
}
}
public void OnPointerDown(PointerEventData eventData)
{
OnDrag(eventData);
}
public void OnPointerUp(PointerEventData eventData)
{
// 重置摇杆位置和输入方向
handle.anchoredPosition = Vector2.zero;
inputDirection = Vector2.zero;
}
// 返回输入方向
public Vector2 GetInputDirection()
{
return inputDirection;
}
}
接下来就可以在其他所需获取输入的地方调用我们的GetInputDirection方法,来获取玩家的输入了,具体示例代码如下所示;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : Ball
{
public Joystick joystick;
// Start is called before the first frame update
protected override void Start()
{
base.Start();
GameObject canvas = GameObject.FindGameObjectWithTag("UI");
joystick = canvas.transform.Find("Input/JoyStick").GetComponent<Joystick>();
}
// Update is called once per frame
void Update()
{
Vector2 joystickInput=joystick.GetInputDirection();
Move(new Vector3(joystickInput.x,joystickInput.y,transform.position.z));
//Debug.Log(Weight);
}
}
运行程序,效果如下所示: