TalesRunner超级跑跑UE复刻版(抄袭版)构建过程
序
最近要做一个Demo
, 思来想去不知道做什么类型的好.
突然想到了初中时代玩的一款游戏超级跑跑.
一来游戏比较简单, 需要的资产也相对容易找到. 敲定目标之后,
就开始着手准备了.
本文章主要用来记录自己整个Demo
的设计过程.
游戏类型: 多人竞速网络游戏
GitHub Repository: https://github.com/D1anHua/D_TalesRunner_Replica
思维导图
在游戏开始设计之前,
我打算先分析一下所要实现的Demo
的最终效果.
主要从功能、架构两方面出发.
功能列表
分析本游戏所需要实现的功能思维导图, 方便后续各部分设计.
架构设计
分析该游戏为了实现上述功能, 应该在架构方面如何布置和设置:
MultiPlayer设计
服务器类型: 这个游戏是多人联机竞速游戏,
因此选择Dedicated Server
.
Authentication Functions
UE Doucmentation: https://docs.unrealengine.com/5.1/en-US/online-subsystem-identity-interface-in-unreal-engine/
FrontendState
Lyra
使用了FControlFlow
来进行自己的登录前的设置.
具体流程如下:
注:
这里Lyra
使用的是其自建的CommonGame
插件.
该插件其主要就是添加一个使用 CommonUI
的Activatable Widget Containers
作为“图层”的系统,并提供将小部件推送到某些图层的功能。
由于我自己搭建的网络架构名字取得和Lyra
的不一样,
因此这里就不使用这个插件了.
LyraExperience模块解读.
Lyra
添加了新的Experience
模块,
其官方包括网上的一些资料都介绍说它是GameMode
的高级版本.
今天, 将首先从LyraExperience
这个模块来讲解这个项目.
注:个人也是UE新手, 如果文章中有错误, 希望大家可以批评指出, 我会尽量改正, 避免给大家造成误解.
(PS: 纯看这个项目的话,
确实感觉可以从LyraExperience
这个模块开始看,
但是我个人感觉这个项目在各个模块之间的耦合度、以及对Tag && Assets Data
的使用超乎我的想象.
要是想要重新复刻这个项目的话,
我建议从Character && Modular Gameplay
看起)
先说一些碎碎念吧: 我本身并不是
UE
老手, 最近想做一个DEMO
项目好让自己在求职季多点姿色. 当时想通过学习Lyra
项目来学习一些Epic
官方的代码风格, 以及学习一下他们是如何构建项目的.结果不出所料地是, 我完全低估了
Lyra
项目的难度, 结果不可避免的让自己的Demo
没有办法按期完成了(🤨), 让自己当初的想法显得天真了一些.不过必须要说的是: 虽然自己的
Demo
是要错过暑期实习的时间了, 不过秋招还是可以努努力的. 另外就是,lyra
这个项目还是可以让人学到很多东西的.剩下的就不多念叨了. 提前感谢大家的观看了.
我的参考链接放在开头, 因为我感觉我自己的文章本身出自别人,
并且自己写的质量也不一定有别人高. 感兴趣的可以直接看别人的文章呀.
1. 知乎---UE5
新项目Gameplay框架设计(以Lyra为例)
2. 知乎---UE5
Lyra的数据驱动之数据加载与引用
3. 知乎---《InsideUE5》GameFeatures架构(一)发展由来
4. Youtube---Modular
Game Features in UE5: plug ‘n play, the Unreal way
5. 官方文档:
Game Featrues and Modular Gameplay
What is Experience
我个人的理解的话, 故名思意, 就可以理解为是一种游玩的体验,
不用的Experience
可能就是不同的游戏风格,
其中包含有角色相关的、控制映射相关的、也有和功能(GameFeature)相关的.
至于它和以前的Gamemode
的区别以及优势.
我个人其实对Gamemode
的理解也并不深刻.
所以我也就不在这里大放厥词了.
具体的功能以及方便与否还是由个人自己区分的(或者有大佬愿意讲讲哈哈哈)
注: 在介绍之前,
方便的同学可以先看看参考链接4或者5以简单的了解一下GameFeatrue
.
GameFeatrue
在Lyra
中也是深度集成的.
不了解也行,
就知道它是一种在不影响游戏原有Component运行过程之外,
所添加的一些额外的功能.
这里我简单举例就像加入我现在只有一个能行走的角色.
我可以将其他任何的逻辑都通过GameFeatrue
在不影响游戏本身以及各个部件之间运行的前提下去增加诸如UI、新的功能等等,
可以丰富这个游戏.(大钊老师的举例很形象. 往主板上拓展的思路)
LyraExperienceDefinition
ExperienceDefinition
定义如下:
在UE5中展示如下: 其设置位置在
World Setting-->GameMode
下:
注: 这里设置的位置其实是
Lyra
继承了AWorldSettings
(可以在以后的工作中也尝试尝试):
1
2
3
4 class LYRAGAME_API ALyraWorldSettings : public AWorldSettings{
UPROPERTY(EditDefaultsOnly, Category=GameMode)
TSoftClassPtr<ULyraExperienceDefinition> DefaultGameplayExperience;
... }
Experience
总共由四个成员变量组成,
其中除了第一个之外全是Lyra的自定义类型. 这里我简单介绍一下,
有个概念就行.(这四部分就是整个Experience
所提供的服务的全部了,
可以说):
1. GameFeaturesToEnable:
将要使用的是哪一系列的GameFeatures
. 2.
LyraModularGameplay && ModularGameplayActor && Enhanced Input(Tag)模块解读
Lyra
项目在整个Character
的构建过程中,
都运用了ModularGameplay
这个插件. 刚入手一个项目的第一步,
我个人觉得还是应该先看看Lyra
角色是怎么设置的.
本文章主要包含Lyra
的以下几个部分:
1. ModularGameplay
2. Enhanced Input Mapping(同Tag
绑定)
3. LyraPawnExtensionComp && LyraHeroComp 之间的Initialization
State System.
本部分不会涉及GAS
系统相关的部分,
GAS
会放后面讲.
注:我本人也是UE学习的新手, 对基础概念掌握并不深, 如果有分析错误的地方, 还请大家批评指正, 也避免误导大家.
参考链接如下:
1. 官方文档:
Game Framework Component Manager
ModularGameplayActor
Lyra
插件目录中有一个插件:ModularGameplayActor
,
其中包含了常用的Actor的MudoularGameplay
的实现, 为在参考链接1中的第一部分Extension Handler System
提供了默认的实现.
在每一个ModularGameplayActor
的实现中,
最主要的在PreInitalizeComponents()
中注册成为了Reveiver,
并在EndPlay()
中RemoveReceiver
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 // ModularCharacter.cpp
void AModularCharacter::PreInitializeComponents()
{
Super::PreInitializeComponents();
UGameFrameworkComponentManager::AddGameFrameworkComponentReceiver(this);
}
void AModularCharacter::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
UGameFrameworkComponentManager::RemoveGameFrameworkComponentReceiver(this);
Super::EndPlay(EndPlayReason);
}
void AModularCharacter::BeginPlay()
{
//! 注册了时间名为NAME_GameActorReady的Default Event(这个事件声明在GameFrameworkComponentManager.h的头文件中), 方便其他插件使用. 比如做同步控制时
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(this, UGameFrameworkComponentManager::NAME_GameActorReady);
Super::BeginPlay();
}
// ModularGameMode.cpp
AModularGameMode::AModularGameMode(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
GameStateClass = AModularGameState::StaticClass();
PlayerControllerClass = AModularPlayerController::StaticClass();
PlayerStateClass = AModularPlayerState::StaticClass();
DefaultPawnClass = AModularPawn::StaticClass();
}
以后可以直接继承这个插件来实现自己GameFeaturePlugins
的实现.
Input System
Lyra的Input System
可与GAS
、GameplayTag
以及不同的控制器协调工作,
其在EnhancedInput
的基础上进行了封装.
Input System Data Stucture
下面放一张正常的使用Enhanced Input System
的代码截图,
从代码中可以看出来,
关于Enhanced Input System
主要有两部分:
- InputMappingContext's Bind
- InputActor's Bind
因此呢, 对应的Lyra
分别定义了这两部分的数据结构.
首先是InputMappingContext,
Lyra
中直接使用了UPlayerMappableInputConfig
,
其中维护了一个含有InputMappingContext
的Map.
Lyra系统为这个Config
封装了CommonInputType
(这个枚举类型用来说明所使用的控制器的类型)信息.
并通过HeroComponent来设置.
而另一方面InputActions则对齐封装了GameplayTag
信息形成了LyraInputAction
.
并根据其时候是Ability
而分为了Native
和Ability
之分.
并通过PawnData
进行设置. (注:
这里的PawnData
并不是简单的在PawnExtensionComp
中进行设置的,
在Lyra
其是在Experience
的初始化过程中由GameState
完成的)