20.EventTrigger事件触发器

  1. 20.UGUI进阶-EventTrigger事件触发器
    1. 20.1 知识点
      1. EventTrigger事件触发器
      2. 如何使用事件触发器
        1. 拖曳脚本进行关联事件
        2. 代码添加
          1. 要先声明EventTrigger成员 外部关联控件上挂着的EventTrigger组件
          2. 申明一个希望监听的事件对象 EventTrigger.Entry
          3. EventTrigger.Entry.eventID 设置事件类型
          4. EventTrigger.Entry.callback.AddListener 当事件触发时添加函数
          5. EventTrigger.triggers.Add 把申明好的事件对象添加到EventTrigger中
          6. 连续加相同类型entry不会报错
          7. 运行结果
      3. 总结
    2. 20.2 知识点代码
    3. 20.3 练习题
      1. 在上节课的练习题基础上,请用现在所学知识,制作一个这样的功能:制作一个UGUI摇杆可以控制场景上的对象移动
        1. 添加两个图片,作为摇杆控件和摇杆点,修改图片为圆形图。
        2. 给摇杆点添加EventTrigger事件触发器组件
        3. 在GamePanel脚本中添加摇杆点位置变量和摇杆上的事件触发器变量,并在外面关联
        4. 在PlayerObject脚本中,添加移动转向速度和当前移动方向变量。定义一个移动方法,用于设置当前移动方向。在Update中当前移动方向不是0向量的时候,向前移动,并且调用Quaternion的Slerp方法不断朝目标方向转向
        5. 在GamePanel脚本中创建摇杆拖动和结束拖动函数,新创建EventTrigger的Entry设置好对应的类型和回调,添加到EventTrigger变量的事件列表中。摇杆拖动函数中将传入的事件数据转换为PointerEventData类型, 根据PointerEventData类型参数的移动值更新摇杆的位置。用摇杆点位置变量的anchoredPosition变量判断摇杆的位置是否超过临界值,anchoredPosition是表示元素相对于其父级容器的位置。超过临界值把他固定在临界位置。最后调用玩家的移动方法,传入摇杆位置。结束摇杆拖动函数中,将摇杆位置重置为中心点,调用玩家移动方法传入0向量,让玩家不移动。
    4. 20.4 练习题代码
      1. PlayerObject
      2. GamePanel

20.UGUI进阶-EventTrigger事件触发器


20.1 知识点

EventTrigger事件触发器

EventTrigger是事件触发器组件,集成了上节课中学习的所有事件接口的脚本。它可以让我们更方便地为控件添加事件监听。

可以右键选择编辑脚本,查看EventTrigger事件触发器的源码,它继承了所有UGUI事件接口。

如何使用事件触发器

拖曳脚本进行关联事件

关联的函数需要有一个BaseEventData参数:

public void TestPointerEnter(BaseEventData data)
{
    //可以转换成子类PointerEventData
    PointerEventData eventData = data as PointerEventData;
    print("鼠标进入 " + eventData.position);
}

一般是拖拽面板对象进来,选择面板脚本上的函数。

代码添加

要先声明EventTrigger成员 外部关联控件上挂着的EventTrigger组件
//外部关联eventTrigger脚本
public EventTrigger eventTrigger;

申明一个希望监听的事件对象 EventTrigger.Entry
// 申明一个希望监听的事件对象 EventTrigger.Entry
// EventTrigger.Entry包含一个事件的类型ID eventID
// 和一个事件回调 callback
EventTrigger.Entry entry = new EventTrigger.Entry();
EventTrigger.Entry.eventID 设置事件类型
// 申明事件的类型为 PointerUp 拖拽事件
entry.eventID = EventTriggerType.PointerUp;
EventTrigger.Entry.callback.AddListener 当事件触发时添加函数
// 监听函数关联,当拖拽事件被触发时,打印"抬起"
entry.callback.AddListener((data) =>
{
    print("抬起");
});
EventTrigger.triggers.Add 把申明好的事件对象添加到EventTrigger中
// 把申明好的事件对象加入到 EventTrigger 当中叫triggers的entry列表中
eventTrigger.triggers.Add(entry);
连续加相同类型entry不会报错
// 创建一个新的事件对象
entry = new EventTrigger.Entry();
// 申明事件的类型为 BeginDrag 开始拖拽事件
entry.eventID = EventTriggerType.BeginDrag;
// 监听函数关联,当开始拖拽事件被触发时,打印"开始拖拽"
entry.callback.AddListener((data) =>
{
    print("开始拖拽1");
});
// 把申明好的事件对象加入到 EventTrigger 当中当中叫triggers的entry列表中
eventTrigger.triggers.Add(entry);
//连续加相同类型的时候不会报错
// 创建又一个新的事件对象
entry = new EventTrigger.Entry();
// 申明事件的类型为 BeginDrag 开始拖拽事件
entry.eventID = EventTriggerType.BeginDrag;
// 监听函数关联,当开始拖拽事件被触发时,打印"抬起"
entry.callback.AddListener((data) =>
{
    print("开始拖拽2");
});
// 把申明好的事件对象加入到 EventTrigger 当中
eventTrigger.triggers.Add(entry);

可以遍历eventTrigger.triggers集合,看看有没有相同类型的事件,有的话就不用新创建了

运行结果

总结

EventTrigger可以让我们写更少的代码,可以在面板类中处理面板控件的事件逻辑,更加面向对象,便于管理。


20.2 知识点代码

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

public class Lesson20_UGUI进阶_EventTrigger事件触发器 : MonoBehaviour
{
    //外部关联eventTrigger脚本
    public EventTrigger eventTrigger;

    void Start()
    {
        #region 知识点一 EventTrigger事件触发器
        //事件触发器是EventTrigger组件
        //它是一个集成了上节课中学习的所有事件接口的脚本
        //它可以让我们更方便的为控件添加事件监听
        #endregion

        #region 知识点二 如何使用事件触发器

        //1.拖曳脚本进行关联

        //2.代码添加


        // 申明一个希望监听的事件对象 EventTrigger.Entry
        // EventTrigger.Entry包含一个事件的类型ID eventID
        // 和一个事件回调 callback
        EventTrigger.Entry entry = new EventTrigger.Entry();

        // 申明事件的类型为 PointerUp 拖拽事件
        entry.eventID = EventTriggerType.PointerUp;

        // 监听函数关联,当拖拽事件被触发时,打印"抬起"
        entry.callback.AddListener((data) =>
        {
            print("抬起");
        });

        // 把申明好的事件对象加入到 EventTrigger 当中叫triggers的entry列表中
        eventTrigger.triggers.Add(entry);

        // 创建一个新的事件对象
        entry = new EventTrigger.Entry();







        // 申明事件的类型为 BeginDrag 开始拖拽事件
        entry.eventID = EventTriggerType.BeginDrag;

        // 监听函数关联,当开始拖拽事件被触发时,打印"开始拖拽"
        entry.callback.AddListener((data) =>
        {
            print("开始拖拽1");
        });

        // 把申明好的事件对象加入到 EventTrigger 当中当中叫triggers的entry列表中
        eventTrigger.triggers.Add(entry);




        //连续加相同类型的时候不会报错

        // 创建又一个新的事件对象
        entry = new EventTrigger.Entry();

        // 申明事件的类型为 BeginDrag 开始拖拽事件
        entry.eventID = EventTriggerType.BeginDrag;

        // 监听函数关联,当开始拖拽事件被触发时,打印"抬起"
        entry.callback.AddListener((data) =>
        {
            print("开始拖拽2");
        });

        // 把申明好的事件对象加入到 EventTrigger 当中
        eventTrigger.triggers.Add(entry);





        #endregion

        #region 总结
        //EventTrigger可以让我们写更少的代码
        //可以在面板类中处理面板控件的事件逻辑,更加的面向对象,便于管理
        #endregion
    }

    public void TestPointerEnter( BaseEventData data )
    {
        //可以转换成子类PointerEventData
        PointerEventData eventData = data as PointerEventData;

        print("鼠标进入 " + eventData.position);
    }
}

20.3 练习题

在上节课的练习题基础上,请用现在所学知识,制作一个这样的功能:制作一个UGUI摇杆可以控制场景上的对象移动

添加两个图片,作为摇杆控件和摇杆点,修改图片为圆形图。

给摇杆点添加EventTrigger事件触发器组件

在GamePanel脚本中添加摇杆点位置变量和摇杆上的事件触发器变量,并在外面关联

// 摇杆的位置
public RectTransform imgJoy;

// 摇杆上的事件相关
public EventTrigger et;

在PlayerObject脚本中,添加移动转向速度和当前移动方向变量。定义一个移动方法,用于设置当前移动方向。在Update中当前移动方向不是0向量的时候,向前移动,并且调用Quaternion的Slerp方法不断朝目标方向转向

public float moveSpeed = 10; // 移动速度
public float roundSpeed = 40; // 转向速度

private Vector3 nowMoveDir = Vector3.zero; // 当前移动方向

/// <summary>
/// 移动方法,用于控制玩家对象的移动方向
/// </summary>
/// <param name="dir">移动方向</param>
public void Move(Vector2 dir)
{
    nowMoveDir.x = dir.x; // 设置水平方向移动
    nowMoveDir.y = 0; // Y轴不移动(竖直方向)
    nowMoveDir.z = dir.y; // 设置垂直方向移动
}

private void Update()
{
    if (nowMoveDir != Vector3.zero)
    {
        // 根据当前移动方向进行移动
        this.transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);

        // 不断朝目标方向转向
        this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.LookRotation(nowMoveDir), roundSpeed * Time.deltaTime);
    }
}

在GamePanel脚本中创建摇杆拖动和结束拖动函数,新创建EventTrigger的Entry设置好对应的类型和回调,添加到EventTrigger变量的事件列表中。摇杆拖动函数中将传入的事件数据转换为PointerEventData类型, 根据PointerEventData类型参数的移动值更新摇杆的位置。用摇杆点位置变量的anchoredPosition变量判断摇杆的位置是否超过临界值,anchoredPosition是表示元素相对于其父级容器的位置。超过临界值把他固定在临界位置。最后调用玩家的移动方法,传入摇杆位置。结束摇杆拖动函数中,将摇杆位置重置为中心点,调用玩家移动方法传入0向量,让玩家不移动。

// 开始时调用
void Start()
{
    // 为摇杆注册事件
    // 拖动中
    EventTrigger.Entry en = new EventTrigger.Entry();
    en.eventID = EventTriggerType.Drag;
    en.callback.AddListener(JoyDrag);
    et.triggers.Add(en);

    // 结束拖动
    en = new EventTrigger.Entry();
    en.eventID = EventTriggerType.EndDrag;
    en.callback.AddListener(EndJoyDrag);
    et.triggers.Add(en);
}

// 摇杆拖动事件
private void JoyDrag(BaseEventData data)
{
    // 将传入的事件数据转换为PointerEventData类型
    PointerEventData eventData = data as PointerEventData;

    // 更新摇杆的位置,将其位置增加拖动距离
    imgJoy.position += new Vector3(eventData.delta.x, eventData.delta.y, 0);

    // 判断摇杆的位置是否超过临界值 anchoredPosition是表示元素相对于其父级容器的位置
    if (imgJoy.anchoredPosition.magnitude > 170)
    {
        // 将摇杆拉回到临界位置
        // 单位向量乘以长度等于临界位置
        imgJoy.anchoredPosition = imgJoy.anchoredPosition.normalized * 170;
    }

    // 通过传入的摇杆位置,让玩家对象移动


    player.Move(imgJoy.anchoredPosition);
}

// 结束摇杆拖动事件
private void EndJoyDrag(BaseEventData data)
{
    // 将摇杆位置重置为中心点
    imgJoy.anchoredPosition = Vector2.zero;

    // 停止玩家对象的移动,传入0向量
    player.Move(Vector2.zero);
}

20.4 练习题代码

PlayerObject

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

public class PlayerObject : MonoBehaviour
{
    public AudioClip ac; // 音效
    public float moveSpeed = 10; // 移动速度
    public float roundSpeed = 40; // 转向速度
    private Vector3 nowMoveDir = Vector3.zero; // 当前移动方向

    void Start()
    {
        // 在游戏开始时执行的方法
        // 此处为空,可以添加一些初始化逻辑
    }

    /// <summary>
    /// 开火方法,用于触发开火行为
    /// </summary>
    public void Fire()
    {
        // 播放音效
        if (MusicData.SoundIsOpen)
        {
            AudioSource audioSource = this.gameObject.AddComponent<AudioSource>();
            audioSource.clip = ac;
            audioSource.Play();
            // 改变音效的大小
            audioSource.volume = MusicData.SoundValue;

            Destroy(audioSource, 0.8f); // 播放完毕后销毁音效对象
        }

        // 动态创建子弹对象
        Instantiate(Resources.Load<GameObject>("Bullet"), this.transform.position, this.transform.rotation);
    }

    /// <summary>
    /// 移动方法,用于控制玩家对象的移动方向
    /// </summary>
    /// <param name="dir">移动方向</param>
    public void Move(Vector2 dir)
    {
        nowMoveDir.x = dir.x; // 设置水平方向移动
        nowMoveDir.y = 0; // Y轴不移动(竖直方向)
        nowMoveDir.z = dir.y; // 设置垂直方向移动
    }

    private void Update()
    {
        if (nowMoveDir != Vector3.zero)
        {
            // 根据当前移动方向进行移动
            this.transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);

            // 不断朝目标方向转向
            this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.LookRotation(nowMoveDir), roundSpeed * Time.deltaTime);
        }
    }
}

GamePanel

// 引入命名空间
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

// 游戏面板类
public class GamePanel : MonoBehaviour
{
    // 光源
    public Light light;
    // 面板实例
    public static GamePanel panel;
    // 攻击按钮
    public Button btnAtk;
    // 音效开关
    public Toggle togOn;
    public Toggle togOff;
    public ToggleGroup tg;
    // 音效大小滑动条
    public Slider sliderSound;
    // 玩家名称文本
    public Text txtName;
    // 改变名称按钮
    public Button btnChangeName;
    // 玩家对象
    public PlayerObject player;
    // 背包按钮
    public Button btnBag;
    // 白天黑夜切换下拉菜单
    public Dropdown ddChange;
    // 关联长按功能按钮
    public LongPress longPress;
    // 进度条和对象,用于控制显隐
    public GameObject imgRoot;
    // 进度条对象,用于控制进度
    public RectTransform imgBk;
    // 是否按下
    private bool isDown = false;
    // 计时
    private float nowTime = 0;
    // 增加速度
    public float addSpeed = 10;
    // 当前血量
    private int hp = 10;
    // 摇杆的位置
    public RectTransform imgJoy;
    // 摇杆上的事件相关
    public EventTrigger et;

    // 初始化
    private void Awake()
    {
        panel = this;
    }

    // 开始时调用
    void Start()
    {
        // 攻击按钮点击事件
        btnAtk.onClick.AddListener(() =>
        {
            // 得到玩家对象,进行开火
            player.Fire();
        });

        // 改变名称按钮点击事件
        btnChangeName.onClick.AddListener(() =>
        {
            // 显示改名面板
            ChangeNamePanel.panel.gameObject.SetActive(true);
        });

        // 音效开关事件监听
        togOn.onValueChanged.AddListener(TogChangeValue);
        togOff.onValueChanged.AddListener(TogChangeValue);

        // 初始化滑动条的值
        sliderSound.value = MusicData.SoundValue;
        // 监听滑动条改变事件
        sliderSound.onValueChanged.AddListener((v) =>
        {
            // 处理音效的大小
            MusicData.SoundValue = v;
        });

        // 背包按钮点击事件
        btnBag.onClick.AddListener(() =>
        {
            // 打开背包面板
            BagPanel.panel.gameObject.SetActive(true);
        });

        // 白天黑夜切换下拉菜单事件监听
        ddChange.onValueChanged.AddListener((index) =>
        {
            switch (index)
            {
                case 0:
                    light.intensity = 1;
                    break;
                case 1:
                    light.intensity = 0.3f;
                    break;
            }
        });

        // 注册长按按钮事件
        longPress.downEvent += BtnDown;
        longPress.upEvent += BtnUp;

        // 初始隐藏蓄能条
        imgRoot.gameObject.SetActive(false);

        // 为摇杆注册事件
        // 拖动中
        EventTrigger.Entry en = new EventTrigger.Entry();
        en.eventID = EventTriggerType.Drag;
        en.callback.AddListener(JoyDrag);
        et.triggers.Add(en);

        // 结束拖动
        en = new EventTrigger.Entry();
        en.eventID = EventTriggerType.EndDrag;
        en.callback.AddListener(EndJoyDrag);
        et.triggers.Add(en);
    }

    // 摇杆拖动事件
    private void JoyDrag(BaseEventData data)
    {
        // 将传入的事件数据转换为PointerEventData类型
        PointerEventData eventData = data as PointerEventData;

        // 更新摇杆的位置,将其位置增加拖动距离
        imgJoy.position += new Vector3(eventData.delta.x, eventData.delta.y, 0);

        // 判断摇杆的位置是否超过临界值 anchoredPosition是表示元素相对于其父级容器的位置
        if (imgJoy.anchoredPosition.magnitude > 170)
        {
            // 将摇杆拉回到临界位置
            // 单位向量乘以长度等于临界位置
            imgJoy.anchoredPosition = imgJoy.anchoredPosition.normalized * 170;
        }

        // 通过传入的摇杆位置,让玩家对象移动
        player.Move(imgJoy.anchoredPosition);
    }

    // 结束摇杆拖动事件
    private void EndJoyDrag(BaseEventData data)
    {
        // 将摇杆位置重置为中心点
        imgJoy.anchoredPosition = Vector2.zero;

        // 停止玩家对象的移动,传入0向量
        player.Move(Vector2.zero);
    }


    // 长按按钮按下事件
    private void BtnDown()
    {
        isDown = true;
        nowTime = 0;
        // 蓄能条清空
        imgBk.sizeDelta = new Vector2(0, 40);
    }

    // 长按按钮松开事件
    private void BtnUp()
    {
        isDown = false;
        imgRoot.gameObject.SetActive(false);
    }

    // 更新函数
    private void Update()
    {
        if (isDown)
        {
            // 计时
            nowTime += Time.deltaTime;
            if (nowTime >= 0.2f)
            {
                imgRoot.gameObject.SetActive(true);
                // 蓄能条增加
                imgBk.sizeDelta += new Vector2(addSpeed * Time.deltaTime, 0);
                if (imgBk.sizeDelta.x >= 800)
                {
                    // 血量增加,条清空
                    hp += 10;
                    print("当前hp" + hp);
                    imgBk.sizeDelta = new Vector2(0, 40);
                }
            }
        }
    }

    // 音效开关值改变事件
    private void TogChangeValue(bool v)
    {
        // 得到当前激活的Toggle
        foreach (Toggle item in tg.ActiveToggles())
        {
            if (item == togOn)
            {
                MusicData.SoundIsOpen = true;
            }
            else if (item == togOff)
            {
                MusicData.SoundIsOpen = false;
            }
        }
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏