敵が攻撃を受けた時に管理クラスがそれを他の敵に伝えるようにしてみました。
まず各敵につけるスクリプトでは、ボールが衝突したときに管理クラスのメソッドを呼びます。動きを止めたりマテリアルの色も変えています。管理クラスのオブジェクトは、管理クラスが敵を作るときに渡されます。
protected NavMeshAgent agent;
protected TestAgentFactory agentManager;
protected bool isStopped;
// ...
private void OnCollisionEnter(Collision collision)
{
// ボールが当たった時
if(collision.collider.tag == "Ball")
{
// 攻撃された
Attacked();
}
}
// 自分が攻撃された
void Attacked()
{
Debug.Log($"{gameObject.name}が攻撃された");
// 管理クラスのメソッドを呼ぶ
agentManager.Attacked(this);
// 立ち止まる
agent.speed = 0f;
isStopped = true;
// 黒くなる
Material mat = GetComponent<MeshRenderer>().material;
mat.SetColor("_BaseColor", Color.black);
}
管理クラスのメソッドでは、各敵が登録されている辞書を見ていって、攻撃された敵以外の敵のメソッドを呼びます。攻撃された敵は引数に渡されるので、誰が攻撃されたかわかります。
// 誰かが攻撃された時
public void Attacked(TestAgent attackedAgent)
{
// 攻撃されてない人のメソッドを呼ぶ
foreach(var agent in agents)
{
if(agent.Value != attackedAgent)
{
agent.Value.OtherAgentAttacked();
}
}
}
各敵のスクリプトには、他の敵が攻撃されたときのメソッドも定義されています。敵は普段徘徊していますが、攻撃を知ると赤くなってプレイヤーを追いかけるようにしてみました。
protected bool isTracking;
protected Transform player;
// ...
// 他の人が攻撃された
public virtual void OtherAgentAttacked()
{
Debug.Log($"{gameObject.name}が攻撃を知った");
if (!isStopped)
{
// プレイヤーを追う
player = GameObject.FindGameObjectWithTag("Player").transform;
isTracking = true;
// 赤くなる
Material mat = GetComponent<MeshRenderer>().material;
mat.SetColor("_BaseColor", Color.red);
}
}
void Update()
{
if(isTracking)
{
agent.destination = player.position;
}
// ...
}
これで誰かが攻撃されると他の敵がプレイヤーを追いかけるようになりました。
攻撃された敵以外の敵だけに通知されています。
今度は、Cubeに付けるクラスを敵のクラスの派生クラスにして、他の敵が攻撃されたときのメソッドをオーバーライドしてみました。
using UnityEngine;
public class TestAgentCube : TestAgent
{
// 他の人が攻撃された
public override void OtherAgentAttacked()
{
Debug.Log($"{gameObject.name}は攻撃を知って逃げた");
// 逃げる
agent.speed = 10f;
agent.destination = agentManager.GetPoint(0).position;
// 黄色くなる
Material mat = GetComponent<MeshRenderer>().material;
mat.SetColor("_BaseColor", Color.yellow);
}
}
オーバーライドするために、基底クラスのメソッドにはvirtualキーワードを付けています。
これで、Sphereだけは黄色くなって逃げるようになりました。