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