先新建一个Canvas,然后再在里面新建两张图作为我们的摇杆背景和摇杆中间的圆点
把其中的一个Image拖到另一个Image的下面
上面的作为背景,使用时是不动的,下面做为要拖动的摇杆
然后改一改参数:
我这边背景的宽高都是200,小圆点的宽高是100
然后调试下形状:
换个圆形的比较好看,两个Image都要换
当然,你要是自己有素材可以直接拖到Source Image上,拖之前记得改一下图片的格式
选中图片,在图片的Texture Type的下拉框中选择Sprite(2D and UI)
更改好之后直接就可以拖入到摇杆的Source Image里了.
代码我会放到文章的结尾.
新建一个摇杆的脚本,把它挂载到小黑点的上面
接下来在真正写摇杆之前要了解三个接口,它们分别是:
IBeginDragHandler, IEndDragHandler, IDragHandler
IBeginDragHandler:在鼠标点击时执行回调函数
IEndDragHandler:在鼠标拖动时执行回调函数
IDragHandler:在鼠标松开时执行回调函数
下面是这三个回调函数,在写接口的时候按下Alt+Enter补全接口就能得到:
完成这一步后,接下来就要定义几个变量:
就和注释中写的一样,因为RectTransform继承自Transform,所以RectTransform可以直接用as转型为Transform.
先写Start中的内容,按照思路一步一步来
Start中的内容主要就是初始化,初始化orStart和RectTransform
然后接下来写拖动结束,拖动结束时,摇杆会回归原位
拖动结束写完后再写拖动中的函数
首先需要判断摇杆拖动的距离,如果是在大圆的范围内,那么直接让摇杆跟随鼠标的位置就好
但是如果超出了范围,那么我们就需要获得鼠标的方向,这里直接用鼠标的位置减去初始的位置之后再进行归一化就获得了方向
所以最后摇杆的位置就是归一化后的方向乘以距离在加上初始位置,
加上初始位置是因为,如果不加他的话,摇杆就会跑到Canvas的左下角
做到这里,运行游戏的话,摇杆就能够被正常拖动了
那么剩下的事就是把摇杆的数据放出来让其他类调用
这里的RectTransform和Transform是差不多的用法,点出来Position后再点出来x轴或者y轴,拿到轴映射
写到这里就差不多写完了,以下附上使用例
和Input类中的GetAxis方法是一样的用法,直接写到玩家移动的脚本里就可以了
摇杆代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class ETC : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
{
//半径的大小
public float r = 100;
//开始时,摇杆小圆点的位置
Vector3 orStart;
//摇杆移动的距离
float dis;
//摇杆的方向
Vector3 dir;
//RectTransform和Transform差不多,一个是用于Ui场景,一个用于3D场景
RectTransform them;
/// <summary>
/// 拖动开始
/// </summary>
/// <param name="eventData"></param>
public void OnBeginDrag(PointerEventData eventData) { }
/// <summary>
/// 拖动中
/// </summary>
/// <param name="eventData"></param>
public void OnDrag(PointerEventData eventData)
{
//摇杆的距离就是鼠标的距离和起始点距离的差距
//用Vector3.Distance来得到这个差距
dis = Vector3.Distance(Input.mousePosition, orStart);
//如果摇杆的没有拖出范围
if (dis < r)
{
//摇杆的位置跟随鼠标的位置一起移动
transform.position = Input.mousePosition;
}
else //如果摇杆拖出了范围
{
//先求出方向
dir = Input.mousePosition - orStart;
//摇杆的位置就是方向*最大距离,加上初始位置
transform.position = dir.normalized * r + orStart;
}
}
/// <summary>
/// 拖动结束
/// </summary>
/// <param name="eventData"></param>
public void OnEndDrag(PointerEventData eventData)
{
transform.position = orStart;
}
// Start is called before the first frame update
void Start()
{
//小圆点一开始的位置就是orStart的位置
orStart = transform.position;
//transform 直接用as转型RectTransform就可以了
them = transform as RectTransform;
}
// Update is called once per frame
void Update()
{
}
/// <summary>
/// 摇杆轴映射
/// </summary>
/// <param name="name">轴名称</param>
/// <returns>0到1的float值</returns>
public float GetAxis(string name)
{
//先判断是横向轴还是纵向轴
//横向轴
if (name == "Horizontal")
{
//RectTransform点出来Position的x轴,再除以半径的长度
return them.anchoredPosition.x / r;
}
else if (name == "Vertical")
{
//RectTransform点出来Position的y轴,再除以半径的长度
return them.anchoredPosition.y / r;
}
//什么都没有就返回0
return 0;
}
}
玩家移动代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerMove : MonoBehaviour
{
public ETC ETC;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (ETC.GetAxis("Horizontal") != 0 || ETC.GetAxis("Vertical") != 0)
{
transform.position += new Vector3(ETC.GetAxis("Horizontal") * 10 * Time.deltaTime, 0, ETC.GetAxis("Vertical") * 10 * Time.deltaTime);
transform.LookAt(transform.position + new Vector3(ETC.GetAxis("Horizontal"), 0, ETC.GetAxis("Vertical")));
}
}
}
需要注意的是:玩家脚本中的ETC是需要在外面把摇杆中的小黑点拖上去的
最后希望我的代码能够给你带来参考