Unity基础 - 封装一个好用的事件系统

这篇具有很好参考价值的文章主要介绍了Unity基础 - 封装一个好用的事件系统。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介

在游戏开发过程中,我们会大量使用事件系统。很多时候,比起直接调用对象组件的方法,使用事件触发将很大程度上降低系统的耦合度,从而实现更为优雅的系统设计。

封装一个好用的事件系统将对我们的开发起到很大的帮助。

本文将基于Unity提供的ScriptableObject和UnityEvent来封装一个我们自己的事件系统。随后,我们可以自定义事件,并在监听器监听到事件后执行对应的程序逻辑。

我们将基于一个实际的需求来更好地说明这个事件系统是如何进行工作的。假设我们现在正在开发关卡选择页面,这个页面上将出现数量不定的关卡按钮(关卡数量随着开发的进行需要不断增加),点击关卡按钮后,需要加载对应关卡的Scene。这个需求适合用事件系统来解决。我们将在按钮UI的组件上绑定"StartScene"的GameEvent,点击按钮后将触发这个事件,然后由MapSelectManager上的GameEventListener进行监听,并执行加载关卡的逻辑。

正文

GameEvent类

GameEvent类将继承ScriptableObject类,这样做可以让我们能够在Unity中为每个自定义事件创建一个数据对象。ScriptableObject是全局的,在跨场景的需求中尤其好用。

Unity基础 - 封装一个好用的事件系统,unity,游戏引擎
代码

[CreateAssetMenu(menuName = "Scriptable/GameEvent")]
public class GameEvent : ScriptableObject
{
    [HideInInspector] public List<GameEventListener> listeners = new List<GameEventListener>();
    
    // Raise event through different methods signatures
    public void Raise(Component sender, object data)
    {
        for (int i = 0; i < listeners.Count; i++)
        {
            listeners[i].OnEventRaised(sender, data);
        }
    }

    public void RegisterListener(GameEventListener listener)
    {
        if (!listeners.Contains(listener))
        {
            listeners.Add(listener);
        }
    }
    
    public void UnregisterListener(GameEventListener listener)
    {
        if (listeners.Contains(listener))
        {
            listeners.Remove(listener);
        }
    }
}

GameEvent负责做3件事:触发事件、注册监听器、取消注册监听器。触发事件时,所有注册本事件的监听器都会调用OnEventRaised(sender, data)来响应此事件。我们可以通过data参数来传递所需要的数据,比如需要加载的关卡名称。

GameEventListener类

GameEventListener负责监听GameEvent并执行后续逻辑。

代码

public class GameEventListener : MonoBehaviour
{
    public GameEvent gameEvent;

    public CustomGameEvent response;

    private void OnEnable()
    {
        gameEvent.RegisterListener(this);
    }

    private void OnDisable()
    {
        gameEvent.UnregisterListener(this);
    }

    public void OnEventRaised(Component sender, object data)
    {
        response.Invoke(sender, data);
    }
}

GameEventListener被Enable时在需要监听的GameEvent上进行注册,被Disable时取消注册。GameEvent事件触发时,OnEventRaised(Component sender, object data)被调用,执行response.Invoke(sender, data)。response是外部传入的,一个CustomGameEvent对象。

CustomGameEvent

它是Unity提供的UnityEvent的一个封装,让我们能将参数传入UnityEvent。

代码

public class CustomGameEvent : UnityEvent<Component, object> { }

使用监听器并绑定对应执行逻辑

创建一个GameObject用于挂载GameEventListener。

Unity基础 - 封装一个好用的事件系统,unity,游戏引擎
将自定义创建的StartGameScene传入GameEvent变量。Response也可以传入外部脚本并调用脚本中的方法,需要注意的是调用的方法必须要能够接收Component和object参数。

加载场景代码

public class MapSelectionManager : MonoBehaviour
    {
        private IEnumerator OnStartGameCoroutine(string sceneName)
        {
            ...
        }

        public void LoadScene(Component sender, object data)
        {
            if (data is string sceneName)
            {
                StartCoroutine(OnStartGameCoroutine(sceneName));
            }
        }
    }

Unity基础 - 封装一个好用的事件系统,unity,游戏引擎

事件的触发

假设我们使用MapItemController来负责关卡按钮的逻辑,那么当按下按钮时,将调用StartGameScene()方法,随后触发onStartGameScene的Raise(Component sender, object data)方法,完成事件的触发。

public class MapItemController: MonoBehaviour
{
	[SerializeField] private GameEvent onStartGameScene;
	
	public void StartGameScene()
    {	
    	string sceneName = GetSceneName(); // 伪代码,获取需要加载的场景名称
   		onStartGameScene.Raise(this, sceneName);
    }

Unity基础 - 封装一个好用的事件系统,unity,游戏引擎
onStartGameScene变量中传入的对象要与先前我们创建的GameEventListener中传入的对象保持完全一致。

至此,我们就实现了一个松耦合的开始关卡的需求。

总结

我们基于ScriptableObject和UnityEvent封装了一个自己的好用且便于理解的事件系统。

基于事件可以松耦合地实现各类游戏开发需求。文章来源地址https://www.toymoban.com/news/detail-785433.html

到了这里,关于Unity基础 - 封装一个好用的事件系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Unity3D游戏魔坦之争】游戏结束流程封装实现【七】

    👨‍💻个人主页 :@元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏 : unityUI专题篇 🅰️ 😶‍🌫️:步骤实现 1.坐标三个转化 2.GUI的原点和屏幕的原点 3.结构体的特点回顾——涉及Rect_结构体类型 4.血条的

    2024年02月11日
    浏览(61)
  • 【用unity实现100个游戏之18】从零开始制作一个类CSGO/CS2、CF第一人称FPS射击游戏——基础篇2(附项目源码)

    本节就先实现添加武器,一些射击基本功能实现。 这里我找了一个人的手臂和武器动画素材 https://sketchfab.com/3d-models/cz-scorpion-evo3-a1-ultimate-fps-animations-f2bdfac775344004ad38d0318f0664a4 将他拖入到为摄像机的子集,然后调整到合适位置即可 你会发现手臂有一部分没法正常显示,那是因

    2024年04月10日
    浏览(50)
  • 【用unity实现100个游戏之18】从零开始制作一个类CSGO/CS2、CF第一人称FPS射击游戏——基础篇4(附项目源码,完结)

    免责声明:因为文章附带 源码 ,所以我上锁了,整理不易,但是推荐大家自己手动跟敲代码理解更加深入

    2024年02月04日
    浏览(50)
  • 【Unity3D游戏魔坦之争】敌方逻辑封装实现【六】

    👨‍💻个人主页 :@元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏 : unityUI专题篇 🅰️ 😶‍🌫️:步骤实现 1.炮台的行为逻辑封装:旋转,触发检测,发射炮弹及特效 2.检测玩家后自动瞄准攻击 3.玩家扣

    2024年02月11日
    浏览(49)
  • Unity实现一个3D塔防游戏

    Unity是一款游戏引擎,可以用来开发各种类型的游戏。在这篇文章中,我们将使用Unity来创建一个3D塔防游戏。本文将从游戏设计开始,一步一步地讲解如何实现一个基本的塔防游戏。 对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白,也有一些正在

    2023年04月26日
    浏览(48)
  • 【Unity】给游戏添加一个背景图

    一、选择一张高清背景图jpg,拖到Unity的Project面板下,设置Texture Type为Sprite。 二、在场景中创建一个空物体并命名为background,点击add component添加一个sprite renderer组件,设置Sprite为想要的背景图片,把Layer设置为新图层Background。 三、设置相机的Clear Flags为Depth only,Culling Mas

    2024年02月11日
    浏览(52)
  • 【Unity】Unity开发学习和项目实践02——创建第一个Unity项目和游戏物体

    创建第1个Unity项目 打开Unity hub,点击新项目 以下有四处地方需要注意选择: 1.Unity编辑器版本 2.项目模板 3.项目名称 4.项目保存位置 点击创建项目 ok,进入编辑器了 把编辑器界面布局稍微改一下,改成2by3 点击Edit 点击 project settings,这是对我们所创建工程的设置 此外还有对

    2024年01月25日
    浏览(52)
  • 初识Unity(十步做好你的第一个unity小游戏)

    一、unity的整体认识 1、创建项目工程文件以及unity布局介绍 (1)打开unityhub,新建项目工程(Project)选择保存路径。 (2)unity的多种布局(窗口的排列)。 认识了tall布局下各个view的功能,四个开发视图(Scene,Project,Hierarchy,Inspector)以及一个game视图。 Scene(场景)视图

    2024年01月24日
    浏览(53)
  • 【Unity】教你如何使用Unity制作一个简单的跑酷游戏

    其实用Unity制作游戏并不难,如果你想学习,那我就建议你想从制作一个简单的跑酷游戏来找到兴趣,因为如果你一开始就一直学习一些没什么必要的语法,这样就会让你一开始就失去了信心,失去了学习Unity的动力,所以如果你先学习如何制作一个简单的跑酷地图,然后你就

    2024年02月21日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包