Unreal GamePlay 框架
Unreal GamePlay 框架
Edmend ZhangUnreal GamePlay 框架
一个游戏由一个GameMode和一个GameState构成。加入游戏的人类玩家与PlayerController关联。 这些PlayerController允许玩家持有游戏中的Pawn,以便在关卡中有物理表示。 PlayerController还为玩家提供了输入功能按钮、平视显示器(简称HUD)和用于处理摄像机视图的PlayerCameraManager。
虚幻引擎中的Gameplay框架提供了多个类和组件,可用作项目的构建块。
- Actor是可以在关卡中放置或生成的对象的基类。Actor可以包含一系列Actor组件,这些组件用于控制Actor的移动方式和渲染方式。Actor支持在游戏期间在网络上复制属性和函数调用。
- 摄像机表示玩家的视角,例如世界在玩家眼里的样子。PlayerController指定摄像机类并实例化摄像机Actor,用于计算玩家查看世界的位置和方向。
- Pawn类是可以由玩家或AI控制的所有Actor的基类。Pawn是世界中的玩家或AI实体的物理呈现。角色是能够四处行走的一种特殊类型的Pawn。默认情况下,控制器和Pawn之间存在一一对应关系,即每个控制器在任何给定时间仅控制一个Pawn。
- 控制器是可持有Pawn或从Pawn派生的类(例如角色)以控制其操作的非物理Actor。玩家控制器由人类玩家用于控制Pawn,而AI控制器为它们控制的Pawn实现人工智能。控制器使用Possess函数控制Pawn,并使用UnPossess函数放弃对Pawn的控制。
- Gameplay定时器创建对特定函数指针的异步回调,以在延迟后或一段时间内触发要执行的事件。
- 游戏框架的基类是GameMode。AGameModeBase Actor在为Gameplay初始化关卡时实例化。GameMode设置游戏的规则,它仅在服务器上实例化,从不存在于客户端。
- 游戏功能和模块化Gameplay插件可帮助开发人员为其项目创建独立功能。这些插件能使项目的代码库保持整洁、易于阅读,并避免不相关的功能之间出现意外的交互或依赖性。
- 用户界面(UI)和平视显示器(HUD)用于向玩家提供有关游戏的信息,并且在一些情况下允许玩家与游戏交互。
1 | class UInputComponent; |
C++ 代理(Delegate)和 Unreal Delegate
C++ 代理模式
代理模式是一种结构型模式
允许在运行时动态地绑定和调用一个或多个函数,这对于事件驱动的编程非常有用。在 Unreal Engine 中,代理主要有三种类型:单播代理、多播代理和动态代理。它们各自有不同的应用场景和特性。
优点:
可以实现对原对象的访问控制。代理对象可以在访问原对象之前执行一些额外操作,例如检查权限、记录日志等。
可以提供额外的功能。代理对象可以在不修改原对象的情况下,为原对象提供额外的功能。
可以减少客户端代码的复杂性。客户端代码只需要与代理对象进行交互,而不需要直接与原对象进行交互。
缺点:
可能会增加系统的复杂性。需要为每个原对象创建一个对应的代理对象。
可能会降低系统的性能。每次访问原对象时,都需要经过代理对象,这可能会增加访问延迟。
满足的设计原理:
开闭原则(Open-Closed Principle, OCP):代理模式允许您在不修改原对象的情况下,为原对象提供额外的功能。这样,您可以在不修改现有代码的情况下,扩展系统的功能。
单一职责原则(Single Responsibility Principle, SRP):代理模式将访问控制和其他额外功能从原对象中分离出来,封装到代理对象中。这样,原对象只需要负责其核心职责,而不需要关心访问控制和其他额外功能。
常用实例:
当需要实现对原对象的访问控制时,可以使用代理模式。代理对象可以在访问原对象之前执行一些额外操作,例如检查权限、记录日志等。
当需要为原对象提供额外的功能时,可以使用代理模式。代理对象可以在不修改原对象的情况下,为原对象提供额外的功能。
当需要减少客户端代码的复杂性时,可以使用代理模式。客户端代码只需要与代理对象进行交互,而不需要直接与原对象进行交互。
例如,在网络编程中,可以使用代理模式来实现远程代理。远程代理允许客户端代码通过网络访问位于远程服务器上的对象。客户端代码只需要与本地的代理对象进行交互,而不需要直接与远程服务器进行通信。此外,在图形界面开发中,可以使用代理模式来实现虚拟代理。
虚拟代理允许您延迟创建复杂的图形对象,直到真正需要时才创建。这可以减少内存占用和初始化时间。
UE 代理模式
真实实现对象以指针形式指给了用户,用户这边只有一个任何操作都给真实实现对象的代理对象 编译也只会涉及这个代理对象 真实的实现以预编译的lib方式提供,最后直接链接
在 Unreal Engine (UE) 中,代理(Delegate)是一种强大的事件处理机制,类似于 C++ 中的函数指针或 C# 中的委托(Delegate)。代理允许你在运行时动态地绑定和调用一个或多个函数,这对于事件驱动的编程非常有用。在 Unreal Engine 中,代理主要有三种类型:单播代理、多播代理和动态代理。它们各自有不同的应用场景和特性。
1. 单播代理(Single-cast Delegate)
单播代理是最简单的代理类型,它只能绑定一个目标函数。当该代理被调用时,仅调用这个绑定的函数。单播代理通常用于一个事件只需要一个处理器的情况。
用法:
1 | cppCopy codeDECLARE_DELEGATE(FMyDelegate); |
关键点:
- 只能绑定一个函数。
- 如果代理没有绑定函数,调用时会导致崩溃,因此通常使用
ExecuteIfBound()
检查是否已绑定。
2. 多播代理(Multi-cast Delegate)
多播代理允许绑定多个目标函数。当代理被调用时,所有绑定的函数都会按顺序依次被调用。多播代理非常适合需要通知多个监听者的事件,例如广播事件或通知多个系统更新。
用法:
1 | cppCopy codeDECLARE_MULTICAST_DELEGATE(FMyMulticastDelegate); |
关键点:
- 可以绑定多个函数。
- 调用时,所有绑定的函数都会依次执行。
Broadcast()
是用于调用多播代理的函数。
3. 动态代理(Dynamic Delegate)
动态代理是可以在 Unreal Engine 的反射系统(UObject系统)中使用的代理。它们可以绑定到 UObject 的方法,并且可以在蓝图中暴露和使用。动态代理在蓝图和 C++ 代码之间的交互中非常有用。
用法:
1 | cppCopy codeDECLARE_DYNAMIC_MULTICAST_DELEGATE(FMyDynamicMulticastDelegate); |
关键点:
- 支持蓝图绑定,因此通常用于在蓝图中实现的事件响应。
- 只能在继承自
UObject
的类中使用。 BlueprintAssignable
允许蓝图绑定这个代理。DECLARE_DYNAMIC_MULTICAST_DELEGATE
支持多播代理,如果需要单播,可以使用DECLARE_DYNAMIC_DELEGATE
。
区别总结
- 绑定数量:
- 单播代理:只能绑定一个函数。
- 多播代理:可以绑定多个函数,所有绑定的函数都会依次执行。
- 动态代理:也支持单播和多播,且可以在蓝图中使用,适合与蓝图交互。
- 蓝图支持:
- 单播代理和多播代理:通常用于纯 C++,不支持直接暴露给蓝图。
- 动态代理:支持与蓝图交互,可以在蓝图中绑定、解绑和调用。
- 使用场景:
- 单播代理:适合一个事件只需要一个处理函数的情况。
- 多播代理:适合广播事件,多个监听者都需要响应的情况。
- 动态代理:适合需要在蓝图中响应事件的情况,常用于需要跨越 C++ 和蓝图的项目。
代理是 Unreal Engine 中处理事件的重要机制,不同类型的代理适合不同的应用场景。单播代理适合简单的事件处理,多播代理适合广播通知,动态代理则是桥接 C++ 和蓝图的工具。理解并合理选择代理类型可以显著提升代码的灵活性和可维护性。