ボス戦
CoddyのUnityジャーニー「Unityのゲームアーキテクチャ」セクションの一部。レッスン 64/64。
石のゴーレムが闘技場から出る門を守っています。ゴーレムはあなたに向かって歩いてきます。近づくと、拳を一瞬振り上げて地面を叩き、まだ近くにいるとダメージを受けます。叩いた後は休み、その間だけ剣でダメージを与えられます。歩いている間や攻撃を繰り出す構えをしている間は、石の皮膚があらゆる攻撃をはね返します。色で行動がわかります。歩いている間は灰色、攻撃を繰り出す構えをしている間は赤、休んでいる間はシアンです。体力を0にすると、門が開きます。画面上部のバーは、攻撃を受けるたびに更新されます。
状態ごとにクラスを用意したステートマシンとして、ゴーレムの脳を作成します。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プレイグラウンド