Choose your operating system:
Windows
macOS
Linux
本示例已停止维护,虚幻引擎4.24后的版本将不再支持此示例。在加载此项目前,请确保你已经安装了正确的引擎版本。 如需了解如何更新项目并用于最新的引擎版本,请参阅根据Epic最新更改进行升级。
本文档引用了名为 战略游戏(Strategy Game) 的游戏项目示例。你可以按照如下操作找到该示例:
点击Epic启动程序中的 学习(Learn) 选项卡,然后向下翻到 历史示例(Legacy Samples) 分段。
点击 战略游戏(Strategy Game) 的缩略图打开项目主页。点击黄色的 免费(Free) 按钮。
稍作等待后,按钮名称会变成 创建工程(Create Project)。点击按钮后,启动程序会提示你输入项目名称并选择安装路径。
点击 创建(Create) 后,你就可以将该项目下载到指定的目录。
塔防(Tower Defense) 示例展示即时战略游戏(RTS)/塔防游戏示例。
特性的完整列表如下:
简单AI逻辑
自动生成的Pawns
环绕式摄像机
建造建筑
主菜单
组合了画布描画和Slate控件的游戏内HUD
游戏内菜单
在塔防游戏中,玩家必须通过建造劲弩、自动弩以及喷火炮塔来防卫酿酒厂,同时还会有我方的士兵Pawn来协助防卫。 如果购买了酿酒厂升级, 这些士兵就会拥有大锤和盾牌。炮塔、士兵以及升级都需要花费金币,可以从金币节点中收集,也可以通过击败敌人来获得。 如果玩家能从5 波敌人的进攻中幸存,包括最终BOSS的攻击,而没有失去全部三条生命,就可以赢得胜利!
AI逻辑和自动生成的Pawn
塔防中的AI逻辑是简单的有限自动机(FSM)。两种可能的状态为向敌人基地移动以及攻击敌人,两种状态均为
继承于 StrategyAIAction
的单独类。 状态位于优先数组内,最为重要的操作排在最前面。这个数组被进行迭代,并且会选择最为适合执行的
操作,如果需要执行具有更高优先级的操作,则可以终止当前操作。
敌方Pawn和我方Pawn都根据AI逻辑运行,向对方基地移动,并且如果遇到对方则开始攻击对方的Pawn。玩家无法控制我方Pawn的移动
或行为,但是他们可以购买新的单位以供生成。
同时,我们使用了蓝图为士兵Pawn添加逻辑。友军和敌军都可以装备盾牌;如果你为酿酒厂购买了兵工厂升级,则友军可以获得盾牌, 如果在 关卡蓝图 中调用SpawnHeavyFunction或SpawnEndBossFunction,则敌军的Pawn将会获得盾牌。如果Pawn拥有盾牌,则自动弩射弹将会被销毁并且不会造成伤害。 这个逻辑使用 蓝图接口(Blueprint Interfaces) 来实现。 名称为 Minion (士兵)的蓝图也包含了网络,可以在敌军Pawn被火焰炮塔蓄力击中时令其减速。
建造建筑
在塔防游戏中,有两种建筑类 - StrategyBuilding
和 StrategyBuilding_Brewery
。塔防中所有的炮塔类型以及空白建筑栏都使用
父类为 StrategyBuilding
的蓝图。玩家可以点击任意空白建筑格来显示快捷菜单并选择建造新建筑。在建造建筑时,空白建筑栏会被销毁,同时生成新建筑。
同时还有一个升级建筑的机制。StrategyBuilding_Brewery
类被用于此例中,因此在酿酒厂基地附近的关联空格中可以建造升级建筑。
再次重申,塔防中的代码会创建基础建筑类。塔防游戏中建筑的所有逻辑和设计都由关卡设计师在蓝图中制作。
酿酒厂
Brewery(酿酒厂) 蓝图具有父类 StrategyBuilding_Brewery
,并且还包含了AIDirector组件。在塔防地图(TowerDefenseMap)中放置了两个酿造厂,一个是敌人
Pawm生成的地方,另一个是我方的酿酒厂,你可以在此处搭建兵工厂并升级铁匠铺,并且可以生成我方的Pawns。在 酿酒厂(Brewery) 蓝图中没有图表逻辑,只有建造属性的
默认设置以及包含AIDirector\触发器盒体以及 静态网格物体 的组件列表。
升级
我方酿酒厂有两格升级栏。它们是继承自 StrategyBuilding
类的 蓝图类(Blueprint Classes) 。如果在酿酒厂菜单中选择一项升级,
则升级内容将会占据一格空白栏。你只能购买一项铁匠铺升级和一项兵工厂升级。
购买铁匠铺升级后,建造开始,在 Wall_Smithy 蓝图中触发OnBuildStarted事件。该蓝图还会在建造完成时告知系统升级已经完成。此时,任何我方Pawn都会获得盾牌附着,该盾牌是来自 StrategyAttachment
类中的蓝图。在兵工厂
报告其构建完成之后,指派"shield-attaching"操作的网络
出现于 TowerDefenseMap 关卡蓝图 的PlayerBaseUpgrades折叠图表中。 StrategyAttachment
类包含一个 骨骼网格体组件(SkeletalMeshComponent)
;附加的网格体和附加点在 Attachment_Armorer 蓝图的默认值中进行设置。
兵工厂蓝图包含了使用OnBuildStarted和OnBuildFinished事件设置的相同逻辑。建造兵工厂后,生成的任何我方Pawn都会拥有大锤,也是继承
自 StrategyAttachment
类。在铁匠铺升级报告其建造完成之后,指派"hammer-attaching"操作的网络也出现于 TowerDefenseMap 关卡蓝图 的PlayerBaseUpgrades折叠图表中。
炮塔
空白栏
空白栏也是具有 StrategyBuilding
父类的蓝图Wall_EmptySlot。在蓝图图表中没有逻辑。这是一个 蓝图类 ,其建造
属性、静态网格体以及作为组件设置的触发器盒体设置默认值。
所有可能的炮塔升级都在建造分段升级部分中Wall_EmptySlot蓝图的默认值部分进行设置。
劲弩
Wall_arbalest 蓝图包含了劲弩的逻辑,劲弩是一种基本的炮塔类型。劲弩使用中等强度的射弹射击最近距离的敌人,在其默认模式中自动射箭。玩家 也可以手动发射弩,他可以点击弩,然后拖曳至想要发射的方向。鼠标拖曳的距离越长,发射弩的强度就越大。
劲弩的射弹被存储在继承于具有 StrategyProjectile
的蓝图TestProjectile的另一蓝图Projectile_arbalest中。Wall_arbalest蓝图具有一定数量的子网络,都包含在事件图表内。在构造脚本(ConstructionScript)中没有蓝图逻辑。
自动弩
Wall_arbalest_auto 蓝图包含了自动弩的逻辑。自动弩从墙壁处直线发射射弹,对射弹穿过的每个单位造成 少量伤害。自动弩只有在击中墙壁或敌人的盾牌时才会被销毁。你可以通过点击和拖曳,让自动发射的弩瞄准所需方向; 当你按下鼠标时,自动弩将会持续向瞄准的方向射击,但松开鼠标按钮后将会返回其默认发射位置。
和劲弩一样,这个炮塔发射的射弹弓箭包含于单独的蓝图中。名称为Projectile_arbalest_auto的自动发射的弓箭只有在撞击具有盾牌的敌人Pawn或墙壁时才会被销毁,而且这个操作 是通过 蓝图接口 ,Interface_Auto_Arbalest和Interface_Auto_Projectile的辅助来执行的。
喷火器
喷火器并不像其他类型的炮塔那样发射射弹。它对喷火区域中的对所有敌人喷火。玩家可以点击并按住鼠标不放来积攒喷火器的能量; 根据按下的时间不同,释放鼠标后产生的能量可以达到最高三倍的伤害,并减缓受损伤的敌军Pawn的速度。如果玩家积聚喷火器的能量, 随后会需要很短的冷却时间,然后继续开始常规的火焰攻击。
摄像机
塔防的摄像机具有固定的视角,并能根据鼠标滚轮的滑动来缩放视角。摄像机的运算在 StrategyPlayerController
类的 CalcCamera
函数中进行,
你可以在 DefaultGame.ini
中计算常量,例如摄像机最小和最大偏移、角度以及摄像机速度。
我们使用观察者Pawn来创建不具有可见Pawn的玩家。
游戏内HUD
游戏内HUD是通过混合使用画布描画(Canvas drawing)和Slate控件创建的。
在右上角,游戏计时器为游戏计算热身倒计时,使用类 SStrategySlateHUDWidget
中的函数 GetGameTime
。游戏开始后,倒计时从屏幕上消失,
并显示剩余的生命数(1) 。"剩余生命数"显示的属性在 AStrategyHUD
类的 DrawLives
函数中进行设置;生命值的初始数值
在TowerDefenseMap 关卡蓝图 中的PlayerBaseUpgrades子图表中进行设置。
当前的金币资源显示在屏幕的顶部中心位置(2)。游戏计时器和资源显示都使用 SStrategySlateHUDWidget
中的基础控件进行定义。同一个类
被用于创建所有顶层的控件,但并不默认显示所有控件。
迷你地图位于HUD的左下角(3)。它是从不可见的Slate控件覆层中构建的,该覆层处理输入和实际地图图像,而此图像使用画布来描画。SStrategyMiniMapWidget
负责在按下按钮或在缩略地图区域按住按钮不放时移动摄像机。
点击建筑空白栏时,会显示 SStrategyActionGrid
菜单。只存在此控件的一个实例;其位置由激活的建筑空白栏决定。计算菜单的
屏幕位置是以 DrawHUD
方式来完成的,它会投射选定的Actor位置到二维坐标。此菜单的动作按钮的外观和事件
在 ShowActionMenu
或 ShowCustomAction
方式的 AStrategyBuilding
类中进行定义。 按钮`控件在
SStrategyButtonWidget 类中进行定义,任意绑定到
动作按钮的额外信息都存储在
FActionButton` 信息结构中。
Pawn和建筑的生命条都使用 DrawActorsHealth
方式在画布上进行描画。每个队伍都有不同的生命条纹理。
在HUD的右下角位置处,有一个 PauseButton
(暂停按钮)(4),它可以切换暂停游戏和游戏中菜单的可视性。
游戏时间用尽或其中一个基地被摧毁后,游戏将会暂停,同时在屏幕中心位置会出现"胜利"或"失败"文本动画。动画会随时间而改变字体大小。
文本使用简单的 STextBlock
控件来创建,具有可视度、字体和文本的代理。
菜单
主菜单
主菜单位于 StrategyMenu 地图内,它会载入主菜单的特定HUD。菜单是基于Slate的,SStrategyMenuWidget`负责主菜单的动画、
布局甚至处理。
SStrategyMenuItem 类继承于游戏内HUD中的
SStrategyButtonWidget,并且描述了单个菜单选项。每个菜单选项(以及附着于选项的事件)
都在
StrategyMenuHUD` 中进行定义。
如需返回到上一菜单,菜单共享指针的数组都被存储在 MenuHistory
变量中。这个变量如同堆栈,存储之前查看过的菜单,这样在返回时很方便,
同时能移除存储菜单父类的需求,这样菜单可以在多个场合中重新使用。
菜单动画使用在 SStrategyMenuWidget::SetupAnimations
中定义的插值曲线。每条曲线都定义了起始时间、持续时间和插值方式,而且可以正反向播放。
如需在特定时间播放动画属性,则使用`GetLerp()`,它会返回在0.0f和1.0f之间的值。
游戏中菜单
当游戏中的菜单为激活状态时,会显示半透明的全屏Slate覆层,并且游戏被暂停。 PauseMenuButtons
在 SStrategySlateHUDWidget
中进行定义。游戏中的暂停菜单有两个按钮:
一个是退出游戏,第二个返回主菜单。 如需退出游戏中菜单,玩家应再次按下右下方的暂停按钮。
关卡蓝图
关卡蓝图 具有生成每波攻击的模块化结构,以及初始化和胜利/失败条件。
敌人生成
使用三个 蓝图宏 来构建每波进攻:可以生成快速敌军(spawn fast)、生成正常敌军(spawn normal)以及生成重型敌军(spawn heavy)。每次生成都使用所需的单位参数和附件,并随后等待 StrategyAIDirector
中的
SpawnMinions
函数触发。宏会等待敌军酿酒厂的 StrategyAIDirector
返回已经生成一波攻击的报告,然后允许在退出子网络的情况下执行。
每个生成的宏需要两个执行输入,一个用于开始宏,一个用于在OnWaveSpawned事件触发后打开 大门 ,并对生成的Pawns数量进行整数输入。
来自类 StrategyAIDirector
的函数被调用,同时对每种类型的Pawn进攻波指定输入。三个函数为 SetDefaultWeapon
、SetDefaultArmor
以及 SetBuffModifier
。
SetDefaultWeapon
和 SetDefaultArmor
将蓝图作为输入并指派这些蓝图为生成时的新默认武器或默认装甲。举例来说,所有由SpawnFastMacro生成的
敌军Pawn将Attachment_Smithy锤子蓝图作为默认武器,所有由SpawnHeavyMacro生成的敌军Pawn将Attachment_Armorer盾牌蓝图作为其默认装甲。
最后由生成蓝图函数调用的 StrategyAIDirector
函数是 SetBuffModifier
,它具有多个数据输入,包括Pawn的攻击能力、生命值加成、速度和大小。
这些输入都在蓝图中进行显示,所以关卡设计师可以直接创建要生成的敌军Pawn的新类。最后,每个生成的蓝图函数都会设置敌军酿酒厂的
StrategyAIDirector
的 WaveSize
属性。
一共有五波敌人的攻击,每波都组合了不同的敌军Pawn,有快速、普通以及重型敌军。在每波攻击的起始处,显示每波进攻标题(Show Wave Title)节点都会显示波数。然后,调用首波 敌人的生成。在生成后有两种类型的延迟:一个是由延迟节点设置的计时器延迟,一个是由WaitForWaveMacro设置的基于Pawn的延迟。WaitForWaveMacro宏继续检查有多少敌军Pawn仍存活, 并且除非延迟时间过期或所有敌军Pawn均被摧毁,否则不会退出执行宏。在一波攻击的所有生成都完成,并且该波的所有敌军Pawn都被消灭后(或者过了两分钟), 使用 远程事件 节点对下一波进攻调用 自定义事件 。
输赢条件
在游戏中,你的基地有三条命。如果有一个敌军Pawn到达了我方的酿酒厂,则扣除一条命,所有命都扣除后,游戏失败。如果敌军的首领到达了我方的酿酒厂,
则游戏失败。要赢得游戏,你必须在损失所有三条命前击败所有的五波敌军。该网络同时设置了输赢条件,它们位于 TowerDefenseMap 的 关卡蓝图 中,并会调用
在类 StrategyGameMode
中设置的函数,该函数来自于 AGameModeBase
类。StrategyGameMode
类还包含诸如 InitGame
的函数,它会初始化游戏,并且在Actor的预初始化组件 SetGamePaused
和 SetGameDifficulty
被调用前进行调用。
在第五波生成的最终首领被消灭后,使用 远程事件 节点来调用胜利 自定义事件 。该 自定义事件 位于 胜利条件 评论框内,然后触发子网络WaitForWin的执行,
该子网络会检查是否有其它仍存在的敌军Pawn。如果该值为 true ,则在WinningTeam输入被设置为"玩家"的情况下调用 Finish Game
函数。
在 失败条件 评论框中有两个节点,它们会调用胜利队伍输入设置为"Enemy"的 Finish Game
函数,这会导致玩家游戏失败。第一个节点会在全部三条命都
损失后触发,三条生命会在敌军Pawn到达我方酿酒厂时被扣除。每次敌军Pawn到达我方酿酒厂时都会触发 MultiGate 节点。MultiGate节点的第一个和第二个输出执行引脚都与更新
我方酿酒厂的剩余生命量(NumberOfLives)值的节点相连接,从而每次将值降低1。最后的输出执行引脚将我方酿酒厂的生命值量设为0,并随后触发WinningTeam值为"Enemy"的
Finish Game
函数。敌方首领生成后,BossSpawned 自定义事件 关闭Gate节点,会造成"3条命版本"的MultiGate,并打开另一个GateNode,从而使得第二个 Finish Game
函数的WinningTeam设置为
"Enemy"。这样可以创建开放的网络,如果最终敌方首领到达我方酿酒厂,FinishGame函数会被激活并且游戏失败。
资源节点 - 金币
金币节点为具有父类 StrategyResourceNode
的蓝图。这个类包含公共函数 GetAvailableResources
和 GetInitialResources
、受保护的函数 OnDepleted
、
资源用尽时的报告函数 BlueprintImplementableEvent
、以及设置节点中资源数量的受保护属性 NumResources
。
金币节点的蓝图包含子网络,从而让节点按照计时器出现和消失。蓝图中的 构造脚本 在蓝图被放置在关卡时设置节点为自动隐藏。
当金币节点出现时,AppearFX粒子特效和声音一起播放。如果由于节点被成功收集而触发了 OnDepleted 事件,则在节点中出现的金币数量被添加到
玩家的总金币池中。播放CollectFX粒子特效和CoinSound,随后节点被再次隐藏。如果玩家未能及时通过点击金币来收藏节点,
则播放FadeFX粒子特效和相应的声音。