当前位置:   article > 正文

Unity简单实现JoyStick摇杆,小学生能看懂系列_unity joystick教程

unity joystick教程

嘿欢迎点开小熊的博客,让我们继续前行吧!
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
  • 1

然后我们需要实现这些接口,当我们“按下”的时候,之间执行我们“拖拽”时候执行的代码:
(注意,为什么是OnPointerDown这些是接口要求的东西,您可以复习一下您手头的计算机教材。)

    public void OnPointerDown(PointerEventData eventData) {
        OnDrag(eventData);
    }
  • 1
  • 2
  • 3

当我们在移动的时候:

    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;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这里就是核心的部分了。
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;
    }
  • 1
  • 2
  • 3

将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() {
        //The Label shows the current Rect settings on the screen
        GUI.Label(new Rect(20, 20, 150, 80), "Mode : " + mode);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87

项目工程链接下载:

https://download.csdn.net/download/qq_34013247/81949365

免积分。

参考资料:

【推荐阅读,有实现其他效果的摇杆】
https://zhuanlan.zhihu.com/p/266077243

【亮点之间距离计算】
https://blog.csdn.net/moonlightpeng/article/details/89949615

小广告:

本熊写了一个小游戏,正在进行手机端适配,到时候请给位CSDN友来捧场哦!!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/146355
推荐阅读
相关标签
  

闽ICP备14008679号