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

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

【Unity9】UNETでゾンビに攻撃させる!【UNET15】

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


スポンサーリンク

Unity5.1.1p3 Personal(2015年7月)


前回の続きです〜


今回は、ゾンビにPlayerを攻撃させてダメージを与えていきたいと思います〜



UNET Part 15 - Zombies Bite Back! - YouTube

【目標】ゾンビにPlayerを攻撃させる!

①Zombie_Attackスクリプトを新規作成

まずはMaterialを新規作成します〜「Zombie Red」という名前で、赤色にして下さい〜


f:id:hiyotama:20150716205844p:plain
Zombie Redを新規作成


次にZombie_Targetスクリプトを1箇所変更します〜

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

public class Zombie_Target : NetworkBehaviour {

	private NavMeshAgent agent;
	private Transform myTransform;
//********** 開始 **********//
//	private Transform targetTransform;
	public Transform targetTransform;
//********** 終了 **********//
	private LayerMask raycastLayer;
	private float radius = 100f;
	
	void Start ()
	{

          〜省略〜

Zombie_Target.cs


targetTransform変数をpublic変数に変更しました〜


それではZombie_Attackスクリプトを新規作成していきます〜
完成したスクリプトは、Zombieプレハブにつけましょう〜

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

public class Zombie_Attack : NetworkBehaviour {
	
	//次の攻撃までの間隔(秒)
	private float attackRate = 3;
	//次に攻撃する時間
	private float nextAttack;
	private int damage = 10; //ダメージ量
	private float minDistance = 2; //攻撃の射程距離
	//現在のゾンビとPlayerとの距離
	private float currentDistance;
	private Transform myTransform; //現在位置
	private Zombie_Target targetScript; //ターゲットの位置
	
	[SerializeField] private Material zombieGreen; //通常時の色
	[SerializeField] private Material zombieRed; //攻撃時の色

	void Start ()
	{
		//現在位置とZombie_Targetスクリプトをキャッシュ
		myTransform = transform;
		targetScript = GetComponent<Zombie_Target>();
		//自分がサーバーだったらコルーチン実行
		if (isServer) {
			StartCoroutine (Attack ());
		}
	}
	
	void CheckIfTargetInRange ()
	{
		//ターゲットが決まっていたら
		if (targetScript.targetTransform != null) {
			//ターゲットと自分の距離を計算
			currentDistance = Vector3.Distance (targetScript.targetTransform.position, myTransform.position);
			//ターゲットが射程距離内&ゲーム開始からの経過時間がnextAttackより大きかったら
			if (currentDistance < minDistance && Time.time > nextAttack) {
				//nextAttackに3秒足す
				nextAttack = Time.time + attackRate;
				
				//Playerにダメージを与える
				targetScript.targetTransform.GetComponent<Player_Health>().DeductHealth(damage);
				StartCoroutine(ChangeZombieMat()); //ホストサーバー向け
				RpcChangeZombieAppearance(); //クライアントサーバー向け
			}
		}
	}
	
	IEnumerator ChangeZombieMat()
	{
		//攻撃を実行したら1.5秒間赤くなり、緑に戻る
		GetComponent<Renderer>().material = zombieRed;
		yield return new WaitForSeconds(attackRate / 2);
		GetComponent<Renderer>().material = zombieGreen;
	}
	
	[ClientRpc]
	void RpcChangeZombieAppearance ()
	{
		//クライアントサーバー向け
		StartCoroutine(ChangeZombieMat());
	}

	IEnumerator Attack ()
	{
		//無限ループ 0.2秒に1回メソッド実行
		for (;;) {
			yield return new WaitForSeconds(0.2f);
			CheckIfTargetInRange();
		}
	}
}

Zombie_Attack.cs


まずはSerialize Fieldに各Materialを指定していきます〜


f:id:hiyotama:20150716210025p:plain


StartメソッドにてAttackコルーチンを呼び出し、0.2秒に1度CheckIfTargetInRangeメソッドを呼び出します〜
1秒に5回攻撃できるかどうか確認している感じです〜


CheckIfTargetInRangeメソッド内では、まずTargetが決まっているか確認し、決まっていたら射程距離内にいるか&攻撃するタイミングかを確認しています〜

Time.timeがゲームの経過時間を表すので、nextAttackを過ぎていたら攻撃します〜
nextAttackは攻撃の度にattackRate分(デフォルトは3秒)加算されていきます〜


次にPlayer_HealthスクリプトのDeductHealthメソッドを呼び出し、ダメージを与えます〜


次にChangeZombieMatメソッドを呼び出し、攻撃後1.5秒間ゾンビを赤くしています〜

ChangeZombieMatメソッドはホストサーバーからとクライアントサーバーからで別々のルートから呼び出されています〜理由はよく分かりません〜

②なぜかうまくいかなかった点を修正

動画では特別問題なく進んでいたのですが、僕がやったら1つ問題が出てしまいました〜
ゾンビのターゲットに、Player以外にCubeが指定されるパターンがあり、その場合NullReferenceExceptionエラーとなってしまいます〜


f:id:hiyotama:20150716211423p:plain
Cubeがターゲットに指定される


f:id:hiyotama:20150716211500p:plain
エラー発生


ゾンビがPlayer_HealthスクリプトのDeductHealthメソッドを呼び出そうとした時、メソッドが付いているのはCubeオブジェクトではなくPlayerオブジェクトなので、NullReferenceExceptionエラーとなったと思われます〜


とりあえずPlayerプレハブをHierarchyビューに戻してCubeを選択し、


f:id:hiyotama:20150716211817p:plain


CubeのレイヤーをDefaultに戻し、Applyボタンを押し、HierarchyからPlayerを削除します〜


f:id:hiyotama:20150716211947p:plain
レイヤーを戻してApply


これでエラーは発生しなくなりました〜

③結果


それでは結果を見ていきましょう〜


f:id:hiyotama:20150716211023p: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】