Unity チュートリアルのタワーディフェンステンプレートを触ってみる(44)

Unity チュートリアルのタワーディフェンステンプレートを触ってみる(43)では Agent の Wave を登録する Wave の継承関係にある TimedBehaviour について解説を行った。。今回は Agent の Wave を登録する Wave について解説を行っていく。

1.タワーディフェンステンプレートのステージの設定編 – Wave.cs

Wave.cs について稚拙ながら解説

「Wave.cs」は「Assets/Scripts/TowerDefense/Level/Wave.cs」の指しておりスクリプトについては以下の通り。内容としては Wave のスポーン処理を行っている。

[cce_csharp]using System;
using System.Collections.Generic;
using Core.Extensions;
using Core.Utilities;
using TowerDefense.Agents;
using TowerDefense.Agents.Data;
using TowerDefense.Nodes;
using UnityEngine;

namespace TowerDefense.Level
{
	/// <summary>
	/// A Wave is a TimedBehaviour, that uses the RepeatingTimer to spawn enemies
	/// </summary>
	public class Wave : TimedBehaviour
	{
		/// <summary>
		/// A list of instructions on how to spawn enemies
		/// </summary>
		public List<SpawnInstruction> spawnInstructions;

		/// <summary>
		/// The index of the current enemy to spawn
		/// </summary>
		protected int m_CurrentIndex;

		/// <summary>
		/// The RepeatingTimer used to spawn enemies
		/// </summary>
		protected RepeatingTimer m_SpawnTimer;

		/// <summary>
		/// The event that is fired when a Wave is completed
		/// </summary>
		public event Action waveCompleted;

		public virtual float progress
		{
			get { return (float) (m_CurrentIndex) / spawnInstructions.Count; }
		}

		/// <summary>
		/// Initializes the Wave
		/// </summary>
		public virtual void Init()
		{
			// If the wave is empty then warn the level designer and fire complete event
			if (spawnInstructions.Count == 0)
			{
				Debug.LogWarning("[LEVEL] Empty Wave");
				SafelyBroadcastWaveCompletedEvent();
				return;
			}

			m_SpawnTimer = new RepeatingTimer(spawnInstructions[0].delayToSpawn, SpawnCurrent);
			StartTimer(m_SpawnTimer);
		}

		/// <summary>
		/// Handles spawning the current agent and sets up the next agent for spawning
		/// </summary>
		protected virtual void SpawnCurrent()
		{
			Spawn();
			if (!TrySetupNextSpawn())
			{
				SafelyBroadcastWaveCompletedEvent();
				// this is required so wave progress is still accurate
				m_CurrentIndex = spawnInstructions.Count;
				StopTimer(m_SpawnTimer);
			}
		}

		/// <summary>
		/// Spawns the current agent
		/// </summary>
		protected void Spawn()
		{
			SpawnInstruction spawnInstruction = spawnInstructions[m_CurrentIndex];
			SpawnAgent(spawnInstruction.agentConfiguration, spawnInstruction.startingNode);
		}

		/// <summary>
		/// Tries to setup the next spawn
		/// </summary>
		/// <returns>true if there is another spawn instruction, false if not</returns>
		protected bool TrySetupNextSpawn()
		{
			bool hasNext = spawnInstructions.Next(ref m_CurrentIndex);
			if (hasNext)
			{
				SpawnInstruction nextSpawnInstruction = spawnInstructions[m_CurrentIndex];
				if (nextSpawnInstruction.delayToSpawn <= 0f)
				{
					SpawnCurrent();
				}
				else
				{
					m_SpawnTimer.SetTime(nextSpawnInstruction.delayToSpawn);
				}
			}

			return hasNext;
		}

		/// <summary>
		/// Spawns the agent
		/// </summary>
		/// <param name="agentConfig">The agent to spawn</param>
		/// <param name="node">The starting node that the agent uses</param>
		protected virtual void SpawnAgent(AgentConfiguration agentConfig, Node node)
		{
			Vector3 spawnPosition = node.GetRandomPointInNodeArea();

			var poolable = Poolable.TryGetPoolable<Poolable>(agentConfig.agentPrefab.gameObject);
			if (poolable == null)
			{
				return;
			}
			var agentInstance = poolable.GetComponent<Agent>();
			agentInstance.transform.position = spawnPosition;
			agentInstance.Initialize();
			agentInstance.SetNode(node);
			agentInstance.transform.rotation = node.transform.rotation;
		}

		/// <summary>
		/// Launch the waveCompleted event
		/// </summary>
		protected void SafelyBroadcastWaveCompletedEvent()
		{
			if (waveCompleted != null)
			{
				waveCompleted();
			}
		}
	}
}[/cce_csharp]

45行目 : 「public virtual void Init()」は初期化処理を行っている。内容としてはスポーンするリストに設定がなければ警告メッセージを表示後、SafelyBroadcastWaveCompletedEvent 処理を行っている。設定があれば Timer を作成し、TimedBehaviour の StartTimer 処理を行っている。

TimedBehaviour については、前回解説させていただいたのでこちらを参照してほしい。

62行目 : 「protected virtual void SpawnCurrent()」は Agent の生成と次の Agent の生成準備を行っている。内容としては Spawn 処理後、TrySetupNextSpawn が成功していなければ、SafelyBroadcastWaveCompletedEvent 処理を行い、TimedBehaviour の StopTimer 処理を行っている。

77行目 : 「protected void Spawn()」は Agent の生成処理を行っている。内容としてはスポーンリストからスポーンさせる Agent を選択し、SpawnAgent の処理を行っている。

87行目 : 「protected bool TrySetupNextSpawn()」は次の Agent の生成準備を行っている。内容としてはグローバル変数の m_CurrentIndex の次がスポーンリストにあれば、スポーン時間の設定を行っている。

111行目 : 「protected virtual void SpawnAgent(AgentConfiguration agentConfig, Node node)」は Agent の生成処理を行っている。引数の AgentConfiguration があれば Poolable から Agent を取得し、Agent の初期値を設定している。

130行目 : 「protected void SafelyBroadcastWaveCompletedEvent()」は Agent のリストが設定されていなかった処理を行っている。内容としては外部から登録された waveCompleted の処理を行っている。

%d人のブロガーが「いいね」をつけました。