提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
hello大家好久没见,之所以隔了这么久才更新并不是因为我又放弃了这个项目,而是接下来要制作的工作太忙碌了,每次我都花了很长的时间解决完一个部分,然后就没力气打开CSDN写文章就直接睡觉去了,现在终于有时间整理下我这半个月都做了什么内容
废话少说,接下来我将介绍我做的第一个BOSS苍蝇之母,其实你看到这个名字可能想不到对应的是游戏里的哪一个BOSS,没事你往下看就知道了,因为我忘了它叫什么名字了好像叫格鲁兹啥的,那么本期内容分为两个部分:一是制作战斗场景Battle Scene,二是制作游戏第一个BOSS苍蝇之母。
另外,我的Github已经更新了,想要查看最新的内容话请到我的Github主页下载工程吧:
GitHub - ForestDango/Hollow-Knight-Demo: A new Hollow Knight Demo after 2 years!
一、制作战斗场景Battle Scene相关逻辑处理
1.制作防止玩家走出战斗场景的门
我们在玩空洞骑士的时候会遇到一些遭遇战,除了进入BOSS房间的时候会有这种门的关闭,我们在一些特定关卡也会遇到这种关,所以在介绍第一个BOSS之前,我们先来做这个战斗场景的逻辑处理:
OK首先我们把门的素材导入tk2dSprtie和tk2dSpriteAnimator当中,
然后我们来先创建好那个特定的场景,每个萌新都知道就是会打两波阿斯匹德的场景:
现在我们做好了场景就该把我们的敌人拖入指定的位置,我们创建一个名字叫Battle Scene的,先给它制作好collider2d,根据设定当玩家进入这个trigger后就相当于进入战斗场景
然后它还有两个子对象Wave1,Wave2分别代表两波攻势
Wave1自然就是场景中央的这只阿斯匹德了:
Wave2则是我们提前生成好放在地图外边的阿斯匹德:
或许你看到上张图就会提问:你怎么创建了一个空的阿斯匹德,原因是在空洞骑士中这里第二波会有两个小蜜蜂看似从场景外飞进来的,说以需要制作从颜色黑色到白色这种视觉效果,而真正的本地则是地图外的这两只阿斯匹德:在完成视觉动画后我们就瞬间让它们进入动画结尾的位置,达到完美的视觉过渡效果:
然后我们先来把门的逻辑处理给完成了:
如图所示做好碰撞箱,音效器,sprite和animator,然后我们还要做一些粒子系统啥的:
然后制作playmakerFSM来处理相关逻辑行为:
初始阶段这些门肯定都是Opened,不然你关上了玩家咋进去:
Collider关掉,等待Battle Scene发送BG Opened,Closed的事件后切换阶段:
关上第一阶段Close 1:这时候就要打开Collider和播放动画和音效了:
第二阶段:
等待发送BG OPEN进入Open阶段后:
还有没有延迟的迅速关闭Quick Close和Quick Open的:
直接摧毁:
完成后做好预制体,拖到地图相应的位置,这里我们需要四个门:
2.制作一个简单的战斗场景
然后就到了制作战斗场景Battle Scene的时候了,还是用我们最爱的playmakerFSM来制作:
激活阶段就是说这个战斗场景玩家已经战胜了,就不会执行重复的战斗关卡 了:
检测玩家是否就位:
第一波攻势阶段:Battle Enemies就是我们总共要战胜多少个敌人,然后向我们上面制作的门的playmakerFSM发送BG CLOSE事件,直到 Battle Enemies少了一个也就是第一波敌人清理干净了就进入到下一波
等个1.5秒到下一波:
第二波阶段:向第二波的敌人发送事件SUMMON产生视觉效果,直到Battle Enemies为0就进入下一个阶段
等个2秒中:
取消场景摄像机锁定,设置为激活状态,向门播放事件BG OPEN
怎么样?什么是不是感觉还挺简单的,逻辑也好理解,但是有个疑问,这个battle scene怎么知道battle enemies已经死了呢,这就要留给enemies公共的脚本:也就是HealthManager.cs来实现了:我们在Die函数被调用后定位到battle scene的playmakerFSM,然后找到变量battle enemies给它减一下,这样就实现了:
using System;
using System.Collections;
using HutongGames.PlayMaker;
using UnityEngine;
using UnityEngine.Audio;
public class HealthManager : MonoBehaviour, IHitResponder
{
[Header("Scene")]
[SerializeField] private GameObject battleScene;
public void Die(float? attackDirection, AttackTypes attackType, bool ignoreEvasion)
{
if (isDead)
{
return;
}
if (sprite)
{
sprite.color = Color.white;
}
FSMUtility.SendEventToGameObject(gameObject, "ZERO HP", false);
if (hasSpecialDeath)
{
NonFatalHit(ignoreEvasion);
return;
}
isDead = true;
if(damageHero != null)
{
damageHero.damageDealt = 0;
}
if(battleScene != null && !notifiedBattleScene)
{
PlayMakerFSM playMakerFSM = FSMUtility.LocateFSM(battleScene, "Battle Control");
if(playMakerFSM != null)
{
FsmInt fsmInt = playMakerFSM.FsmVariables.GetFsmInt("Battle Enemies");
if(fsmInt != null)
{
fsmInt.Value--;
notifiedBattleScene = true;
}
}
}
if (deathAudioSnapshot != null)
{
deathAudioSnapshot.Tran