只需要把脚本交给画布下的空物体,自行自定义以下内容,运行即可生成虚拟摇杆。

提供了检测区域大小的自定义。

提供了摇杆检测区域的图片自定义。

提供了摇杆底盘以及摇杆的图片自定义。

提供了摇杆灵敏度的自定义。-----值越大 ----灵敏度越小

提供了摇杆移动百分比,以及移动方向信息,可直接用于接入移动模块。

生成的是仿照Moba类的虚拟摇杆,具体分析看对应的设计分析_【测试分析】手机游戏虚拟摇杆设计分析-By Terrell21

代码中某些数字部分没提供自定义,可根据个人需要修改或设置成自定义。

枚举为  虚拟摇杆的组成部分,摇杆盘底,摇杆。

 

主要功能:

不做出检测区域外的响应。

盘底位置根据在检测区域内的响应进行位置更新。松手后返回初始位置。

盘底不回超出检测区域,不会超出屏幕边缘。

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

enum E_JoystickComponent
{
    chassis,
    joystick
}

public class VirtualJoyStick : MonoBehaviour {
    //图片组件
    private Image click_limit;              //点击区域限制,,跟其RectTransform上的长宽 位置有关
    private GameObject chassis;          //操纵杆底盘
    private GameObject joystick;         //操纵杆

    public Sprite chassis_sprite;
    public Sprite joystick_sprite;
    public Sprite limit_sprite;

    //记录信息
    private  Vector2 prePos;                 //上一个点击位置
    private Touch nowTouch;                 //当前触摸信息
    private  Vector2 iniPos;                 //初始位置
    public float sensitivity = 2;          //灵敏度  ---这里越大 灵敏度越小
    private float m_radius;                 //盘子半径

    public float moveInfo;                  //摇杆移动的百分比
    public Vector2 moveDir;                 //摇杆移动的方向

    public float trigger_width;
    public float trigger_height;
    // Use this for initialization
    void Start () {
        //图形部分
        click_limit = gameObject.AddComponent(typeof(Image)) as Image;
        click_limit.sprite = limit_sprite;
        click_limit.color = new Color(0, 0, 0, 0.1f);
        RectTransform triggerRect = GetComponent<RectTransform>();
        triggerRect.anchorMax = Vector2.zero;
        triggerRect.anchorMin = Vector2.zero;
        triggerRect.pivot = Vector2.one;
        triggerRect.anchoredPosition = new Vector2(trigger_width, trigger_height);
        triggerRect.sizeDelta = new Vector2(trigger_width, trigger_height);
        chassis = CreateChild("Chassis",this.transform,E_JoystickComponent.chassis);
        joystick = CreateChild("Joystick", chassis.transform,E_JoystickComponent.joystick);

       
    }

    //1)触发区域
    //2)触发情况
    //3)放置摇杆
    //4)摇杆拖动
    //5)限制摇杆摆放位置
    //6)边缘位置 直接拖动
    public void Update()
    {
        if (Input.touches.Length > 0)
        {
            Touch touch = Input.GetTouch(0);
            //检测上一次的触发是否结束
            //结束->检验此次按压的位置是否处于检测区域->放置摇杆
            //非结束->拖动给杆心
            if (nowTouch.phase == TouchPhase.Ended)
            {
                Vector2 edge = transform.GetComponent<RectTransform>().anchoredPosition;
                if (touch.position.x < edge.x && touch.position.y < edge.y)
                {
                    nowTouch = touch;
                    chassis.transform.position = touch.position;
                    prePos = touch.position;
                    CheckIsEdge();
                }
            }
            else
            {
                joystick.GetComponent<RectTransform>().anchoredPosition = (touch.position - prePos) / sensitivity;
                if(joystick.GetComponent<RectTransform>().anchoredPosition.magnitude > m_radius)
                {
                    joystick.GetComponent<RectTransform>().anchoredPosition = joystick.GetComponent<RectTransform>().anchoredPosition.normalized * m_radius;
                }
            }
            //检测抬手
            //摇杆杆心返回
            //摇杆返回初始点
            //将上一状态的触摸信息设置成触摸离开
            if (touch.phase == TouchPhase.Ended)
            {
                nowTouch.phase = TouchPhase.Ended;
                chassis.GetComponent<RectTransform>().anchoredPosition = Vector2.zero;
                joystick.GetComponent<RectTransform>().anchoredPosition = iniPos;
            }
            //刷新当前按压位置的信息
            //s = touch.position.ToString();

        }
        if ((joystick.GetComponent<RectTransform>().anchoredPosition.normalized * m_radius).magnitude > 0)
            moveInfo = joystick.GetComponent<RectTransform>().anchoredPosition.magnitude / (joystick.GetComponent<RectTransform>().anchoredPosition.normalized * m_radius).magnitude;
        else
            moveInfo = 0;
        moveDir = joystick.GetComponent<RectTransform>().anchoredPosition.normalized;
    }

    //判断是否触碰触发区边缘,并作相应调整
    private void CheckIsEdge()
    {
        float y = Mathf.Abs(transform.position.y - chassis.transform.position.y);
        float x = Mathf.Abs(transform.position.x - chassis.transform.position.x);
        //判断摇杆盘底是否触碰触发区上下边缘
        if (y > transform.position.x - m_radius)
        {
            chassis.transform.position = new Vector3(chassis.transform.position.x, m_radius, chassis.transform.position.z);
        }
        else if (y < m_radius)
        {
            chassis.transform.position = new Vector3(chassis.transform.position.x, chassis.transform.position.y - m_radius, chassis.transform.position.z);
        }
        //判断摇杆底盘是否触碰触发区域左右边缘
        if (x > transform.position.x - m_radius)
        {
            chassis.transform.position = new Vector3(m_radius, chassis.transform.position.y, chassis.transform.position.z);
        }
        else if (x < m_radius)
        {
            chassis.transform.position = new Vector3(chassis.transform.position.x - m_radius, chassis.transform.position.y, chassis.transform.position.z);

        }
    }


    /// <summary>
    /// 生成对象并建立关系
    /// </summary>
    /// <param name="name"></param>
    /// <param name="parent"></param>
    /// <returns></returns>
    GameObject CreateChild(string name,Transform parent,E_JoystickComponent joystickComponent)
    {
        GameObject gameObject = new GameObject(name);
        gameObject.transform.SetParent(parent);
        Image image;
        RectTransform rectTransform;
        Vector2 triggerRect = this.GetComponent<RectTransform>().sizeDelta;
        switch (joystickComponent)
        {
            case E_JoystickComponent.chassis:
                image = gameObject.AddComponent(typeof(Image)) as Image;
                image.sprite = chassis_sprite;
                image.color = Color.black;
                rectTransform = image.gameObject.GetComponent<RectTransform>();
                rectTransform.anchoredPosition = Vector2.zero;
                rectTransform.sizeDelta = new Vector2(triggerRect.x * 2 / 7, triggerRect.y * 2 / 7);
                m_radius = triggerRect.x * 2 / 7 / 2;
                prePos = rectTransform.position;
                break;
            case E_JoystickComponent.joystick:
                image = gameObject.AddComponent(typeof(Image)) as Image;
                image.sprite = joystick_sprite;
                image.color = Color.red;
                rectTransform = image.gameObject.GetComponent<RectTransform>();
                rectTransform.anchoredPosition = Vector2.zero;
                rectTransform.sizeDelta = new Vector2(triggerRect.x  / 7, triggerRect.y / 7);
                iniPos = rectTransform.anchoredPosition;
                break;
        }
        return gameObject;
    }

}

演示:

魅蓝 note5  Unity Remote 5 的录屏情况

android 实现虚拟摇杆 安卓模拟摇杆_Image