嘿欢迎点开小熊的博客,让我们继续前行吧! 40行实现主要内容。
*提供工程样例,在本文最后。
效果图片:
原理解析:
布局思路:
Canvas:是整个屏幕的图层,其中这个Canvas会设置“按照屏幕大小缩放”。* JoyBac:是一张图片,一个背景图。(使用PS作图)
*在后文还会提及。 ———— 请将这三个物体对应的拖拽到后文的代码Inspection中以此初始化。(您可以看完后面的再来看这里) 而Handle就是我们传说的摇杆,也是一张图片。 Handle: 注意:真实的图片中是png格式,周围或圈内是透明的,这里为了演示将图片染色。
触发思路:
判断用户的点击,是不是在上面的”JoyBac“里面。如果用户在这个区域进行点击,那么就将图片的Handle移动到那个位置。以此好像是,我们拖动了摇杆的感觉一样。
当我们停止触控的话,那么就立马将Handle设置为原点。
这里面还需要注意一个坑点,那就是,小心Canvas的缩放。这会导致在拖动的时候,感觉Handle好像不跟手一样。
您应该掌握的知识有EventSystems(不是事件驱动系统,在这里指的是UGUI的那一套EventSystems)。
同时您也应该明白“将脚本拖拽到物体上面”的这个行为,这里的行为是使得这个物体拥有了脚本所能处理到的能力。也就是,脚本的this.gameObject(注意,这里的gameObject是小写代表一个变量,而大写的GameObject则代表着一个类。)指的是被拖拽的这个物体。
好的,说完了前面的这些,我们来看看代码。其实很简单。
代码分析:
将代码放在JoyBac上面*(正如我们前面所述,这些接口需要在被点击的物体生效)
首先,由于我们需要处理一些触摸操作,比如按下,抬起,拖拽,所以我们需要集成这些接口。
IPointerDownHandler, IDragHandler, IPointerUpHandler
然后我们需要实现这些接口,当我们“按下”的时候,之间执行我们“拖拽”时候执行的代码: (注意,为什么是OnPointerDown这些是接口要求的东西,您可以复习一下您手头的计算机教材。)
public void OnPointerDown(PointerEventData eventData) {
OnDrag(eventData);
}
当我们在移动的时候:
public void OnDrag(PointerEventData eventData) {
Vector2 to = ((Vector2)eventData.position - (Vector2)background.position) / canvas.scaleFactor;
if (to.magnitude <= radious)
handle.anchoredPosition = to;
else {
Vector2 to2;
to2 = (Vector2)to / (float)(to.magnitude / radious);
handle.anchoredPosition = to2;
}
}
这里就是核心的部分了。 to代表着Handle的中心点(anchoredPosition)在哪里。 而eventData是EventSystems返回给我们的事件数据,其中包含了触摸的位置,是否在托转dragged等参数。 background是我们的背景图片。 canvas.scaleFactor是图层的缩放尺度,请务必考虑在内,因为这会使得滑动屏幕的时候,Handle不跟手指。您可以移步至UGUI教程学习。
其实就一个to就是所有的核心内容啦! 通过to,我们就能知道相对于background中心点的偏移了。
然后,if (to.magnitude <= radious) 一个逻辑分支判断,判断我们的触摸点是否已经被拖拽到了别的地方去了(超出了bac)
如果超出去了,那么就通过简单的数学运算:to2 = (Vector2)to / (float)(to.magnitude / radious); 将to的长度改回最长的限制。
然后最后更正Handle的位置handle.anchoredPosition = to2;
当我们抬起手指的时候:
public void OnPointerUp(PointerEventData eventData) {
handle.anchoredPosition = Vector2.zero;
}
将Handle更正,至此,您的简单代码已经全部实现完成啦!
那么,我们该怎么去,判断方向呢。
其实根据to向量就可以了,这部分留给读者思考。
本熊代码:
最近在写一款小游戏,只需要上下左右四个维度。
所以我的判断方法如下: 通过Handle靠近哪个点,那么就是用户想往哪个方向移动。
完整代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class JoyStickControl: MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler {
enum Mode { None, Up, Down, Left, Right };
Mode mode;
public Vector2 input = Vector2.zero;
public RectTransform background = null;
public RectTransform handle = null;
public Canvas canvas;
float radious;
Vector2 up, down, left, right;
void Start() {
mode = Mode.None;
radious = background.rect.width / 2.0f;
up = new Vector2(0, radious);
down = new Vector2(0, -radious);
left = new Vector2(-radious, 0);
right = new Vector2(radious, 0);
}
void Update() {
MessageSend();
}
public void OnDrag(PointerEventData eventData) {
Vector2 to = ((Vector2)eventData.position - (Vector2)background.position) / canvas.scaleFactor;
if (to.magnitude <= radious)
handle.anchoredPosition = to;
else {
Vector2 to2;
to2 = (Vector2)to / (float)(to.magnitude / radious);
handle.anchoredPosition = to2;
CalcDis();
}
}
void MessageSend() {
switch (mode) {
case Mode.None:
break;
case Mode.Up:
break;
case Mode.Left:
break;
case Mode.Down:
break;
}
}
void CalcDis() {
float dis = 0f;
if (Vector2.Distance(up, handle.anchoredPosition) < dis || dis == 0) {
dis = Vector2.Distance(up, handle.anchoredPosition);
mode = Mode.Up;
}
if (Vector2.Distance(down, handle.anchoredPosition) < dis) {
dis = Vector2.Distance(down, handle.anchoredPosition);
mode = Mode.Down;
}
if (Vector2.Distance(left, handle.anchoredPosition) < dis) {
dis = Vector2.Distance(left, handle.anchoredPosition);
mode = Mode.Left;
}
if (Vector2.Distance(right, handle.anchoredPosition) < dis) {
dis = Vector2.Distance(right, handle.anchoredPosition);
mode = Mode.Right;
}
}
void EventSender(int mes) {
}
public void OnPointerDown(PointerEventData eventData) {
OnDrag(eventData);
}
public void OnPointerUp(PointerEventData eventData) {
handle.anchoredPosition = Vector2.zero;
mode = Mode.None;
}
void OnGUI() {
GUI.Label(new Rect(20, 20, 150, 80), "Mode : " + mode);
}
}
项目工程链接下载:
https://download.csdn.net/download/qq_34013247/81949365
免积分。
参考资料:
【推荐阅读,有实现其他效果的摇杆】 https://zhuanlan.zhihu.com/p/266077243
【亮点之间距离计算】 https://blog.csdn.net/moonlightpeng/article/details/89949615
小广告:
本熊写了一个小游戏,正在进行手机端适配,到时候请给位CSDN友来捧场哦!!!
|