首页 Learn How To Make A 2D Platformer In Unreal Engine 5学习笔记#6&7关卡设计和最后的优化
文章
取消

Learn How To Make A 2D Platformer In Unreal Engine 5学习笔记#6&7关卡设计和最后的优化

6.1Designing A Level

  1. 去修改之前创建的tileset_tilemap,大小60*20

  2. layer命名main

  3. fill类似油漆桶,很方便,设计main的tile

  4. 创建一个layer,命名Treebackground,放几棵树,如果发现有些地方框选不到,那就到tileset里调整tilesize

  5. 再创建一个layer,bushbackground

  6. 在地图边缘创建空气墙,放一个cube,调整大小,在details中搜索hid,勾选actor hidden in game

  7. 放一些小怪

    jFdyVg.jpg

6.2Creating A Main Menu

  1. 拖入UI资源

  2. 在UI文件夹,右键->user interface->widget blueprint,命名mainmenu_wb

  3. 拖入image,anchors选最右下角那个填满的,接着image的offset全设置为0

  4. image设置为刚拖入的资源

  5. 拖入vertical box,anchors锚点设置为中心,命名start menu,并勾选is variable

  6. 向box中拖入两个button,再拖两个text到button上,一个是开始,一个是推出游戏

  7. 拖入一个text,锚点设置在top

  8. 调整image的tint,让画面暗点

  9. 设置button的style

  10. 给button添加on click事件

  11. 退出按钮直接就指向quit game节点

  12. 拖入一个水平盒命名level menu,勾选 is variable,锚点依然是中心,放入几个按钮用来表示level

  13. 在level menu的details中搜索visibility,设置为hidden

  14. 在屏幕左下角放置一个button,命名back button,也设置为hidden,锚点在左下角

    jFDNef.jpg

  15. 点击开始游戏显示关卡菜单和返回菜单

  16. 为开始游戏按钮添加on pressed事件

  17. 把levelmenu和backButton拖入蓝图(上面已经设置成了variable)

  18. on pressed节点后,设置开始菜单的visibility为hidden,另外两个显示

  19. back button添加on click事件,上面的事反着来

  20. 按 alt + 左键可以快速取消连接

    jFDYOP.jpg

6.3Creating The Main Menu Level

  1. 点击窗口左上角file -> new level -> default level

  2. save为level menu

  3. 点击上方blueprint按钮,选择open level bluprint

  4. brgin play节点指向create widget,选择main menu,指向add to view port

  5. 右键创建get player controller 节点,指向 set show mouse cursor节点

  6. get player controller 节点指向set input mode ui only节点

    jFc1M9.jpg

  7. 创建一个game mode base蓝图,命名mainMenuGameMode

  8. 点击上方window->world settings,设置game mode

  9. 前往主菜单的控件蓝图去,给level 1按钮添加click事件,指向open level节点,输入level名字

  10. 前往角色蓝图,begin play节点后面设置鼠标隐藏,并set game mode only

    jFc3rR.jpg

6.4Creating A Pause Screen

  1. Edit -> project settings -> input添加action mappings,命名Pause game,使用按键P

  2. 创建控件蓝图(widget),paused_wb

  3. 拖入image,跟上个一样,填充屏幕,然后透明度降低点

  4. 拖入text,锚点中央,paused

  5. 进入角色蓝图,右键创建pausegame节点(开始创建的action mapping),pressed指向create widget节点,选择pause_wb

  6. return value生成一个变量pause UI,指向 add to viewPort

  7. 指向set game paused节点

  8. 为了能取消暂停,pressed指向一个branch节点,condition为is game paused

  9. 如果false就暂停否则,先判断pauseUI 是否is valid,就是如果现在pauseUI确实显示在屏幕上,就解除暂停,即指向remove from parent,再指向 set pauseUI节点,这样就会设置为unvalid(应该是为了防止快速连按),最后设置为非暂停

  10. 点击最开始的输入节点,勾选execute when paused(一定要勾选这个!!)

    jFgBfU.jpg

6.5Creating Game Over Screen

  1. 创建一个widget,GameOver_WB

  2. 拖入image,像上面一样

  3. 拖入text,game over

  4. 进入蓝图模式,在event construt节点后指向delay节点,延迟4s后,指向open level by name,回到主菜单

  5. 去角色蓝图,死亡后直接创建game over的widget即可

7.1Creating A Save Game Pt 1

  1. 创建蓝图类,搜索save game,创建并命名PlatformerSave

  2. 创建变量coins(float),NoOfAxe(float),Lives(float)

  3. 进入mainmeui_wb蓝图,event construct节点指向Dose Save Game Exist,slot name设置为1,return value指向一个branch(condition)

  4. 如果false就执行create save game object,选择platformer game save(刚才建的)

  5. 然后执行set coins(0)、NoOfAxe(0)、Lives(5)、save game to slot

    jkeSGd.jpg

  6. 进入角色蓝图,在beginPlay节点后,指向Load Game from slot节点,slot name设为1,return value指向cast to platformerSave

  7. 再通过这个cast to platformerSave节点的as platformersave来get三个变量

  8. 接着设置玩家的三个变量

7.2Creating A Save Game Pt 2

  1. 在角色蓝图中,当lives减少时,更新存档

  2. 将Platformersave创建成变量(去之前的cast to Platformersave节点处右键创建)

  3. 设置完lives,就指向save game to slot

  4. 当 game over的时候,前往gameover_wb,event construct指向load game from slot节点,再cast to platformersave,设置lives为5,最后指向save game to slot1

    jkepRA.jpg

  5. 前往coin蓝图,当收集到金币时,就设置存档的金币(金币clamp到0-100的范围内),存档类用角色类的变量引用

  6. 在存完档后检测是否等于100,否的话就存档,是的话命+1,再设置存档

    jke9xI.jpg

  7. enemy conin也做类似的处理

  8. 当投掷完斧子后也存下档

  9. 前往axe pickup蓝图,捡到斧子时也要存档

  10. 发现了一个非常严重的bug,就是关于存档,在begin play事件读存档的话,最后的值会被默认值覆盖,但我把读存档放在按攻击键之后的话,就能读取成功了,总之就是很怪,这begin play感觉它后面还有个default事件,给我把前面赋得值全给擦了,甚至把初始化的变量也给擦了,导致后面更新存档时,说Psave这个变量是空值,总之就很怪,设置成读存档按键好了(合理逃避),不然也太费时间了,还有就是,开局必须按G,不然退出会报错psave为none,哎~

  11. 我试了个新方法,把存档功能整理成一个存档事件,然后再beginPlay事件最后delay个0.5s再执行,就可以了,而且0.5s很难察觉出来哈哈哈哈

    jkenRs.jpg

7.3Updating The UI

  1. 没啥好说的,就是改了改布局,加了个图片

    jkmt78.jpg

7.4Updating The Pause Menu

  1. 给暂停界面加个返回主菜单和继续的按钮

    jkMV8e.jpg

  2. 记得在暂停的时候set show mouse cursor(要先创建get player controller节点才行),并set input mode ui only,解除暂停时也要set input mode game only

    jkQiss.jpg

  3. 需要注意的是,在没碰撞获取2dCharacter时,需要get player character来获取2dCharacter类,而不是 get player controller

7.5Creating The End Level Box

  1. 创建一个actor,命名level change

  2. 拖入flag资源,制作flipbook

  3. 添加beginoverlap事件(给box加)

    jkt1IA.jpg

7.6Level Unlock System

  1. 进入platformersave蓝图,创建变量levelUnlocked?(boolean-array)

  2. 复制一份level1,变成level2

  3. 复制一份tilemap,成level2tilemap

  4. 设计level2map并更换

  5. 前往mainmenu_wb,复制一份level1,变成level2,添加on click事件,open level2

  6. 接下来是锁关系统:在上面的on click节点后,先判断是否有存档1,有的话就加载slot1,投射platformersave类,get levelunlocked?,get(a copy)(设置为1),指向branch,如果解锁,就解锁第二关

    jk58Fs.jpg

  7. 前往第一关的level change蓝图中,在碰撞节点的cast to 2dcharacter节点后加载slot1, 投射platformersave类,get levelunlocked?,指向set array elem节点,将index生成一个变量levelnum,勾选item

  8. 设置完了,就save game to slot

    jk5GYn.jpg

  9. 我发现一旦涉及到tilemap就容易crash,

7.7Adding Invisible Collision To The Level

  1. 由于关卡开始的空气墙也可以被玩家爬,所以fix this bug

  2. 选择cube,设置collision presets为custom,勾选visibility的ignore

7.8Updating The Wall Slide

  1. 前往角色蓝图

  2. 再beginplay节点后指向get all actors with tag,tag设置为nowallslide,out actors生成一个变量,命名nowallslideactors

  3. 到滑墙系统板块,line trace by channel节点的arrays to ignore指向刚创建的nowallslideactors变量

  4. 最后将墙设置为nowallslide即可防止角色话去滑设定的墙(但我不需要哈)

7.9Updating The Enemies

  1. 小怪在空中移动距离过大,前往enemy蓝图,选择character movement,搜索lateral(横向的),设置falling lateral frict为2.5

  2. 由于小怪被玩家在身后打了后的受伤动画是朝着玩家动的,很不自然(被打了也不回头也很不自然好吧233)

  3. 前往enemy蓝图,在伤害板块,select节点的return value生成一个变量,命名HitDirection,并set这个值放在set enemy health后

  4. 前往动作处理模块:在sequence的then0后加一个branch判断是否受伤害了,如果受伤了,就根据HitDirection来设置转身

    jk7YEF.jpg

7.10Updating The Projectile Attack

  1. 前往axe蓝图,添加标签projectile

  2. 给小怪的子弹也加上标签projectile

  3. 回到axe蓝图,在apply damage节点签添加actor has tag节点,tag设为projectile

  4. 作为branch的条件,branch加在destroy前,如果有这个tag就两种子弹都destroy

  5. 怪物的子弹也加上这个

    jkHSbT.jpg

7.11Final level Touches

  1. 拖入campfire unlit资源,并创建flip book

  2. 将检查点的动画设置成这个,然后在碰撞事件的最后加上设置动画,设置成着火的状态

  3. 再丰富下地图

  4. 创建一个tiemap,可以跳的那种

  5. 给tileset添加box后,点击refresh map可以直接更新

    jkqX2d.jpg

  6. 又出bug了,说是range enmey的launch velocity节点由于之前的damage causer为none,导致报错,但明明enemy就没事,很怪,强行设置了玩家为damage causer就不报错了。

    jkLA2j.jpg

7.12Packaging The Project

  1. Edit -> project setting -> maps & modes,找到default maps,设置里面game default map为menu

  2. 回到编辑器,点击play旁边的platforms->windows->(选择shipping)package project(vs要安装NET.SDK)

完结撒花啦~

本文由作者按照 CC BY 4.0 进行授权