Boss 战
本课属于 Coddy Unity 学习旅程的“Unity 游戏架构”单元。第 64 课,共 64 课。
一只石头魔像守着竞技场出口的大门。它朝你跺步而来,靠近时会短暂举起拳头,然后猛砸地面,如果你还在附近,就会受伤。砸击后它会休息,只有这时你的剑才能伤到它:它行走或蓄力时,石质皮肤能挡住所有攻击。它的颜色表示当前状态:行走时是灰色,蓄力时是红色,休息时是青色。把它的生命值降到 0,大门就会打开。屏幕顶部的血条会随每次攻击变化。
用状态机编写魔像的 AI,为每种状态创建一个类:Boss,以及 BossStates.cs 中的 ChaseState、WindupState 和 RestState。玩家、血条、大门、IState、StateMachine 和 IDamageable 都已准备好,Boss 也已经创建了各个状态,并会逐帧更新状态机。
挑战
困难在 BossStates.cs 中编写魔像的状态。
ChaseState:调用Tint(Color.gray);以speed的速度朝玩家移动;进入slamRange范围后,开始蓄力。WindupState:调用Tint(Color.red);经过windupTime后,记录Slam!,对范围内的玩家造成slamDamage点伤害,然后休息。RestState:调用Tint(Color.cyan);经过restTime后,开始追击。Boss.TakeDamage只在rest状态下生效:扣除相应数值,提高HealthChanged事件;生命值降至 0 时调用Fall()。
按下“开始”,趁它休息时攻击。然后按“检查”。
亲手试试
using System;
using UnityEngine;
using UnityEngine.Events;
public class Boss : MonoBehaviour, IDamageable
{
public Transform player;
public float speed = 2f;
public float slamRange = 2.5f;
public float windupTime = 1f;
public float restTime = 2f;
public int slamDamage = 2;
public int maxHealth = 6;
public event Action<int, int> HealthChanged;
public UnityEvent onDefeated;
public StateMachine machine;
public IState chase;
public IState windup;
public IState rest;
private int health;
void Awake()
{
health = maxHealth;
machine = new StateMachine();
chase = new ChaseState(this);
windup = new WindupState(this);
rest = new RestState(this);
}
void Start()
{
HealthChanged?.Invoke(health, maxHealth);
machine.ChangeState(chase);
}
void Update()
{
machine.Tick();
}
public void TakeDamage(int amount)
{
// 只有它休息时受到的攻击才算数:扣除 amount 点生命值,触发 HealthChanged,生命值降到 0 时调用 Fall()。
}
// 已完成:石魔倒下,大门打开,石魔离开竞技场。
void Fall()
{
Debug.Log("The golem falls");
onDefeated.Invoke();
gameObject.SetActive(false);
}
// 玩家在地面方向上的距离。
public float PlayerDistance()
{
Vector3 d = player.position - transform.position;
d.y = 0f;
return d.magnitude;
}
// 行走时显示灰色,蓄力时显示红色,休息时显示青色。
public void Tint(Color color)
{
GetComponent<Renderer>().material.color = color;
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
Unity 游戏架构中的所有课
自己练习: Unity 在线编辑器