Unity5(C#)初心者・入門者向けチュートリアル ひよこのたまご

AndroidやiOS向けアプリを簡単に作れるゲーム開発環境Unity(ユニティ)の使い方を、チュートリアル方式で一緒に学びましょう!

【Unity9】UNETでゾンビAIを出現させる!【UNET12】

いつもひよこのたまごをご利用下さいましてありがとうございます!
おかげ様でチュートリアル数も10ゲーム目となりました!
チュートリアル一覧は
こちら からどうぞ!


スポンサーリンク

Unity5.1.1p3 Personal(2015年7月)


前回の続きです〜


今回はゾンビAIを作成していきます〜



UNET Part 12 - Zombies! - YouTube

【目標】ゾンビAIを出現させる

①ゾンビオブジェクトを作成する

まずはゾンビAIを作っていきましょう〜HierarchyビューからCreate > 3DObject > Cubeを選択し、名前を「Zombie」にし、Transformを以下のように設定します〜


f:id:hiyotama:20150716092905p:plain
Zombieオブジェクト作成


続いてMaterialを作成し、Zombieオブジェクトに取り付けます〜
名前は「Zombie Green」で、色は緑色です〜


f:id:hiyotama:20150716093241p:plain
Material作成


続いてZonbieオブジェクトにNav Mesh Agentコンポーネントを取り付けていきます〜Add ComponentからNavigation > Nav Mesh Agentを選択して下さい〜


Nav Mesh Agentは、指定した範囲内でAIを移動させるための機能です〜
移動範囲が限定されているため、障害物を自動的に避けさせたりしたい時に便利です〜


Agent SizeのRadius(半径)を0.6にし、AIの半径を若干大きくします〜
また、Stopping Distanceを2.5にし、ターゲット(Player)の手前で止まるようにします〜


f:id:hiyotama:20150716094745p:plain
Nav Mesh Agent設定


続いてZombieオブジェクトをプレハブ化します〜


f:id:hiyotama:20150716095059p:plain
ドラッグ&ドロップ! 元オブジェクトは削除


最後にAIの移動範囲を設定します〜Window > Navigationを選択し、


f:id:hiyotama:20150716095540p:plain
Window > Navigation


NavigationビューにてMesh Rendererを選択します〜すると、HierarchyビューにMesh Rendererのついたオブジェクトのみが表示されます〜
表示されたオブジェクトを全て選択し、Navigation Staticにチェックを入れて下さい〜


f:id:hiyotama:20150716095724p:plain
Navigation Staticにチェック


次にBakeビューに切り替え、デフォルト設定のままBakeボタンを押します〜すると、Navigationビュー下にExporting Tilesというバーが出てきます〜
Mesh RendererにAIが動ける範囲を焼いているところなので、バーが満タンになるまで待ちましょう〜


f:id:hiyotama:20150716100106p:plain
Bakeボタンをクリック


②AI用のスクリプトを作成する
ゾンビAIの元となるオブジェクトの作成と、AIが移動できる範囲指定が完了しました〜


続いてAI用のスクリプトを作成していきます〜
名前はZombie_Targetにします〜以下ソースです〜

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class Zombie_Target : NetworkBehaviour {

	private NavMeshAgent agent;
	private Transform myTransform;
	private Transform targetTransform;
	//ゾンビが探知するレイヤー
	private LayerMask raycastLayer;
	//ゾンビがPlayerを探知する半径
	private float radius = 100f;
	
	// Use this for initialization
	void Start () {
		agent = GetComponent<NavMeshAgent>();
		myTransform =transform;
		raycastLayer = 1<<LayerMask.NameToLayer("Player");
	}
	
	// Update is called once per frame
	void FixedUpdate () {
		SearchForTarget();
		MoveForTarget();
	}
	
	void SearchForTarget ()
	{
		//サーバーじゃなければメソッド終了
		if (!isServer) {
			return;
		}
		
		//Playerをまだ取得していない時
		if (targetTransform == null) {
			//Physics.OverlapSphere: ある地点を中心に球を作り、衝突したオブジェクトを取得する
			//第1引数: 中心点 第2引数: 半径 第3引数: 対象のレイヤー
			Collider[] hitColliders = Physics.OverlapSphere (myTransform.position, radius, raycastLayer);
			if (hitColliders.Length > 0) {
				int randomInt = Random.Range(0, hitColliders.Length);
				targetTransform = hitColliders[randomInt].transform;
			}
		}
		//Playerは取得しているがBox Colliderが非アクティブの時 = isDeadがtrueの時
		if(targetTransform != null && targetTransform.GetComponent<BoxCollider>().enabled == false){
			targetTransform = null;
		}
	}
	
	void MoveForTarget ()
	{
		//Playerオブジェクト取得済みで、自分がサーバーの時
		if (targetTransform != null && isServer) {
			SetNavDestination(targetTransform);
		}
	}
	
	void SetNavDestination (Transform dest)
	{
		//ゾンビAIの目的地設定
		agent.SetDestination(dest.position);
	}
}

Zombie_Target.cs


FixedUpdateメソッド内で、2つのメソッドを呼び出しています〜


1つ目はSearchForTargetメソッドで、Playerを探しています〜

まずは自分がサーバーで無い場合はメソッドを抜けます〜

続いてOverlapSphereを使い、ゾンビの位置からradiusを半径とした球を作り、その範囲内のPlayerオブジェクトを取得します〜

取得できたら、複数取得した場合はPlayer1体に絞り込みます〜

取得したPlayerオブジェクトのBoxColliderが非アクティブの時、つまり殺されてisDeadがtrueになった時は、ターゲットから外します〜


2つ目はMoveForTargetメソッドです〜

Playerオブジェクト取得済みで自分がサーバーの時、SetNavDestinationメソッドを呼び、AIが進む目的地としてPlayerの位置が指定されます〜

③ゾンビを発生させるポイントを作成

ゾンビを発生させるポイントを作っていきます〜Mainシーンで、HierarchyビューからCreate > Create Emptyを選択し、名前を「ZombieSpawn」に変更して下さい〜
Position.yだけ1に変更しておきます〜


f:id:hiyotama:20150716123426p:plain


続いてZombieプレハブに先ほど作成したZombie_Targetスクリプトを取り付けて下さい〜すると、Network系のスクリプトのため自動的にNetwork Identityコンポーネントが取り付けられます〜


ついでにAdd Component > Network > Network Transformも取り付けて下さい〜
また、Rotation Axisのみ「Y (Top-Down 2D)」に変更しておいて下さい〜


f:id:hiyotama:20150716123745p:plain
Network Transformを取り付ける

④ゾンビ生成用スクリプトを作成

ZombieSpawnができたので、そこからゾンビを発生させるスクリプトを作っていきます〜


今回はGameManagerにつけていくので、「GameManager_ZombieSpawner」という名前にします〜

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class GameManager_ZombieSpawner : NetworkBehaviour {

	[SerializeField] GameObject zombiePrefab;
	[SerializeField] GameObject zombieSpawn;
	
	private int counter;
	private int numberOfZombie = 10;
	
	public override void OnStartServer ()
	{
		for (int i = 0; i < numberOfZombie; i++) {
			SpawnZombies();
		}
	}
	
	void SpawnZombies()
	{
		//counter(後ほど何かを実装)
		
		GameObject go = GameObject.Instantiate(zombiePrefab, zombieSpawn.transform.position, Quaternion.identity) as GameObject;
		NetworkServer.Spawn(go);
	}
	
	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

GameManager_ZombieSpawner.cs


まずはGameManagerオブジェクトに取り付けます〜
すると、先程と同様にNetwork Identityが自動的に付くのを確認して下さい〜


f:id:hiyotama:20150716132535p:plain


SerializeFieldの変数2つも、Inspectorビューから指定してあげましょう〜


f:id:hiyotama:20150716132725p:plain
ドラッグ&ドロップ!


Hostサーバーがログインした時にOnStartServerメソッドが実行され、SpawnZombiesメソッドが10回繰り返されます〜


SpawnZombiesメソッドではzombiePrefabをInstantiateによって生成し、NetworkServer.Spawnメソッドにてゾンビを全てのクライアントと同期します〜


NetworkServer.Spawnの対象となったプレハブは、Network Managerにて登録しておかなければなりません〜

というわけでMenuシーンを開き、NetworkManagerのSpawn Info一番下にあるRegistered Spawnable PrefabにZombieプレハブを登録して下さい〜


f:id:hiyotama:20150716133436p:plain
ドラッグ&ドロップ!


これでゾンビが発生してくれるはずです〜

⑤結果

実行する前にZombieSpawnオブジェクトの位置を遠くにしておきます〜


f:id:hiyotama:20150716134028p:plain


f:id:hiyotama:20150716134036p:plain
遠くに離す


それでは実行してみましょう〜


f:id:hiyotama:20150716134100p:plain
近い


結構離したつもりですが、あっという間に間合いを詰められました〜

とにかくゾンビを出現させることに成功しました!


今回はここまでです〜

ありがとうございました〜


【Unity9】UNETでマルチプレイヤーなオンラインゲーム開発【UNET1】
【Unity9】UNETでプレイヤーの動きを補間し、なめらかな動きを実現する【UNET1-2】
【Unity9】UNETでネットワーク越しに傾き(Rotation)を同期させる【UNET2】
【Unity9】UNETでオンライン開始時のプレイヤー生成位置を変更する【UNET2-2】
【Unity9】UNETのネットワークトラフィックを軽減し、効率化する【UNET3】
【Unity9】UNETのlatency(遅延時間)を改善する【UNET4】
【Unity9】UNETのlatency(遅延時間)を表示して、ちょっとだけ改善する【UNET4-2】
【Unity9】UNETのSyncVarのhookの使用例と、前時代の同期方法【UNET5】
【Unity9】UNETを使ってRotationを同期させる【UNET6】
【Unity9】UNETで各プレイヤーにPlayerIDを設定する【UNET7】
【Unity9】UNETで敵プレイヤーにダメージを与える!【UNET8】
【Unity9】UNETでHPを画面に表示し、Playerへダメージを与える【UNET9】
【Unity9】UNETでHPが0以下になった時、Playerを破壊する!【UNET10】
【Unity9】UNETで死んだPlayerを生き返らせる!【UNET11】
【Unity9】UNETでゾンビAIを出現させる!【UNET12】
【Unity9】UNETでゾンビ生成時にユニークなIDを付ける!【UNET13】
【Unity9】UNETでゾンビを撃つ!【UNET14】
【Unity9】UNETでゾンビに攻撃させる!【UNET15】
【Unity9】UNETでゾンビの動きをスムーズにシンクロさせる!【UNET16】
【Unity9】UNETでゾンビ発生地点を増やす【UNET17】
【Unity9】UNETで発生したバグを取り除く【UNET18】
【Unity9】Unity MultiPlayerを使ってネットワーク越しにマッチメイキング!【UNET19】
【Unity9】GUIを改善して、Network Managerを見やすくする!【UNET20】
【Unity9】表示したGUI(Network Manager)を機能させる!【UNET20-2】
【Unity9】UNETでAnimationを同期させる!【UNET21】