IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity虚拟摇杆(事件分发器实现) -> 正文阅读

[游戏开发]Unity虚拟摇杆(事件分发器实现)

目录

搭建UI

编写代码

搭建UI

?①创建一个image 命名为?ControlArea 作为按钮识别的检测范围 并将透明度设置为1(透明度为0不触发事件检测)

②如下图的父子关系添加 image 并命名 找到合适的素材拖给相应的image? 设置合适的大小(根据自己的喜好和素材的大小自行设置)

③注意选中joystick 的 锚点(花)放到左下角 防止因为分辨率改变使得按钮位置改变? 中心点(pivot)的位置设置为(0.5,0.5)如下图

?

实现脚本

①使用单例UIManger 对某些公共方法进行管理

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;

public class UIManger : MonoBehaviour
{
    public static UIManger Instance;

    public static UIManger GetInstance()
    {
        if (Instance == null) 
        {
            Instance = new UIManger();
        }
        return Instance;
    }

    public static void AddCustomEnventListener(UIBehaviour contral, EventTriggerType type, UnityAction<BaseEventData> callback) 
    {
        EventTrigger trigger = contral.GetComponent<EventTrigger>();
        if (trigger == null)
            trigger = contral.gameObject.AddComponent<EventTrigger>();

        EventTrigger.Entry entry = new EventTrigger.Entry();

        entry.eventID = type;
        entry.callback.AddListener(callback);
        trigger.triggers.Add(entry);
    }

}

②事件分发器

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

//事件分发器
public class EventCenter : MonoBehaviour
{
    //声明一个带参数的委托
    public  delegate void CallBack<T>(T t);
    //声明一个字典 事件码与事件进行绑定
    public static Dictionary<string, Delegate> m_EventTable = new Dictionary<string, Delegate>();

    /// <summary>
    /// 添加监听的方法
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    /// <param name="str">事件码</param>
    /// <param name="callBack">泛型为委托</param>
    public static void Addlistener<T>(string str , CallBack<T> callBack)
    {
        //
        if (!m_EventTable.ContainsKey(str))
        {
            m_EventTable.Add(str,null);
        }
        Delegate d = m_EventTable[str];
        if (d != null && d.GetType() != callBack.GetType()) 
        {
            throw new Exception("监听添加错误!!");
        }
        //订阅事件
        m_EventTable[str] = (CallBack<T>)m_EventTable[str] + callBack;

    }
    /// <summary>
    /// 移除监听的方法
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    /// <param name="str">事件码</param>
    /// <param name="callBack">泛型委托</param>
    public static void RemoveListener<T>(string str, CallBack<T> callBack) 
    {
        if (m_EventTable.ContainsKey(str))
        {
            Delegate d = m_EventTable[str];
            if (d == null)
            {
                throw new Exception(string.Format("监听移除失败,事件{0}没有委托", str));
            }
            else if (d.GetType() != callBack.GetType())
            {
                throw new Exception(string.Format("监听移除失败,事件类型不对应{0},{1}", str.GetType(), callBack.GetType()));
            }

        }
        else
        {
            throw new Exception(string.Format("监听移除失败,没有事件码{0}", str));
        }
        //取消订阅
        m_EventTable[str] = (CallBack<T>)m_EventTable[str] - callBack;
        if (m_EventTable[str] == null) 
        {
            m_EventTable.Remove(str);
        }
    }
    /// <summary>
    /// 广播
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    /// <param name="str">事件码</param>
    /// <param name="arg">T 的参数</param>
    public static void BroadCast<T>(string str,T arg) 
    {
        Delegate d;
        if (m_EventTable.TryGetValue(str, out d))
        {
            CallBack<T> callBack = d as CallBack<T>;

            if (d != null)
            {
                callBack(arg);
            }
            else { throw new Exception("广播错误!!!"); }
        }
    }
}

③将下面的脚本该再到?ControlArea 上去

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

public class JoystickContral : UIManger
{
    
    public float MaxL;

    private Image ControlBK;
    private Image Joystick;
    private Image Handle;
    // Start is called before the first frame update
    void Start()
    {
        //根据按钮的中心到按钮父物体边界的距离
        MaxL = 75;
        //控制按钮监听的范围
        ControlBK = this.GetComponent<Image>();
        
        Joystick = transform.Find("Joystick").GetComponent<Image>();
        
        Handle =  transform.GetChild(0).GetChild(0).GetComponent<Image>();
        
        //添加自定义事件监听的方法 把对应的函数和 事件 关联起来
        UIManger.AddCustomEnventListener(ControlBK, EventTriggerType.PointerDown, PointerDown);
        UIManger.AddCustomEnventListener(ControlBK, EventTriggerType.PointerUp, PointerUp);
        UIManger.AddCustomEnventListener(ControlBK, EventTriggerType.Drag, Drag);
    }


    private void PointerDown(BaseEventData data) 
    {
        //Debug.Log("我被按下了");
    }
    private void PointerUp(BaseEventData data)
    {
        Handle.transform.localPosition = Vector3.zero;
        //Debug.Log("我抬起来了");
        EventCenter.BroadCast<Vector2>("JC", Vector2.zero);
    }
    private void Drag(BaseEventData data)
    {
        Vector2 localPos;
        //将一个屏幕空间点转换为 RectTransform 的本地空间中位于其矩形平面上的一个位置(将其转换为ControlBK 范围内的位置)
        RectTransformUtility.ScreenPointToLocalPointInRectangle(
            Joystick.rectTransform,//你想改变位置对象(handle)的 父对象(joystick)
            (data as PointerEventData).position,//得到当前鼠标的位置
            (data as PointerEventData).enterEventCamera,//UI用的摄像机
            out localPos);//的到一个转换来的 相对坐标
        Handle.transform.localPosition = localPos;

        if (localPos.magnitude > MaxL)
            Handle.transform.localPosition = localPos.normalized * MaxL;

        //EventCenter.Addlistener<Vector2>("yaogan", localPos.normalized);
        EventCenter.BroadCast<Vector2>("JC", localPos.normalized);
    }
}

④测试脚本 挂载到要移动的物体上

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

public class text : MonoBehaviour
{
    private Vector3 dir;
    // Start is called before the first frame update
    private void Awake()
    {
        EventCenter.Addlistener<Vector2>("JC", CheckDirChange);
    }
    private void OnDestroy()
    {
        EventCenter.RemoveListener<Vector2>("JC", CheckDirChange);
    }
    // Update is called once per frame
    void Update()
    {
        this.transform.Translate(dir*Time.deltaTime, Space.World);
    }

    private void CheckDirChange(Vector2 dir) 
    {
        this.dir.x = dir.x;
        this.dir.z = dir.y;

    } 
}

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-03-13 22:09:00  更:2022-03-13 22:09:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/24 10:02:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计