UnityNetworkでオンライン対応6-敵キャラクターを出現させる-

今回はプレイヤーキャラクターとは別にNPC(ノンプレイヤーキャラクター)である敵をインスタンス化し登場させてみたいと思います。

前回はキャラクターの登場位置の設定とHPが0以下になった時に再度登場させる機能を作成しました。

UnityNetworkでプレイヤーキャラクターの登場位置の設定と、キャラクターのHPが0以下になった時に再登場させる機能を作成していきます。
スポンサーリンク

あらかじめシーンに敵を配置する

まずは敵をプレハブからインスタンス化するのではなく、あらかじめシーン上に配置しておくようにしましょう。

シーン上に敵を配置しておき、NetworkIdentityコンポーネントを取り付けておくと、この敵はサーバー管理のゲームオブジェクトとなります。

その為、自身がホストの時にアプリケーション上の敵のHPが0以下になった時にDestoryでゲームオブジェクトを消すと、自身のシーン上から削除され、自身がクライアントであれば敵は非アクティブとなります。

シーン上に元々あるゲームオブジェクトはシーンオブジェクトと言うらしいです。

Unity のマニュアルは、Unityの使い方を学ぶ手助けとなります。Unityを使って 2D や 3D ゲームを作成したり、ゲーム以外のアプリを作成したりして多くの経験を積みましょう。

敵キャラクターの作成

シーン上に敵を配置し、

Add ComponentからNetwork→NetworkIdentityを取り付けます。
Add ComponentからNetwork→NetworkTransformを取り付けます。
Add ComponentからNetwork→NetworkAnimatorを取り付けます。

Network TransformのTransform Sync ModeはSync Transformを選択します。

NetworkIdentityはネットワーク上で取り扱う為に取り付け、NetworkTransformは他のアプリケーションと位置を同期する為、NetworkAnimatorはアニメーションを同期する為に取り付けます。

NetworkTransformやNetworkAnimatorを取り付けなくてもクライアントで位置やアニメーションが同期されているような気がしましたが、やはり少しづつズレていきますね。

試しに付けない状態でEnable Matchを押してCreate InternetMatchを選択し、他のアプリケーションからEnable MatchからFind Internet Matchボタンを押し確認すると、途中から同期が取れなくなっていくのを確認出来ました。

実際に試してみるとわかりやすいかもしれません。

敵キャラクターのAnimatorには敵用のAnimatorControllerを取り付け、IdleとWalk状態を作ります。

アニメーションパラメータにFloat型のSpeedを作成します。

Idle→WalkへはSpeedが0.1以上、
Walk→IdleへはSpeedが0.1以下、

で遷移するように条件を設定します。

ここら辺はオンラインでもオフラインでも同じなので問題はないと思います。

NetworkAnimatorのAnimatorに自身のAnimatorをドラッグ&ドロップして、Speedのチェックを入れます。

敵にはナビゲーション機能を取り付け、近くにいるプレイヤーキャラクターを追いかけるようにします。

Add ComponentからNavigation→NavMeshAgentを取り付けます。

次に敵が攻撃を受けた時ように敵の当たり判定のコライダを追加します。

Add ComponentからPhysics→Capsule Colliderを取り付け、コライダのサイズを調整し、Is Triggerにチェックを入れます。

プレイヤー検知機能の作成

敵キャラクターはナビゲーション機能を使ってプレイヤーキャラクターを追いかける為、敵キャラクターの子要素に空のゲームオブジェクトを作り、名前をSearchAreaとします。

プレイヤーキャラクターを検知するサーチエリア

SearchAreaにはSpherer Colliderを取り付け、プレイキャーキャラクターを検知する範囲に合わせてコライダの調整をし、Is Triggerにチェックを入れます。

サーチエリアに検知するコライダを設定する

SearchPlayerスクリプトを作成しSearchAreaに設定します。

プレイヤーキャラクターにはPlayerタグを設定し、検知エリアにプレイヤーキャラクターがいたら、自身の親要素に設定しているEnemyScriptのSetTargetメソッドを呼び出し、追いかけるターゲットを設定します。

プレイヤーキャラクターが検知エリアを出て行った時はResetTargetを呼び出し、ターゲットをなしにします。

EnemyScriptスクリプトはこの後作成します。

敵操作スクリプトEnemyScriptの作成

プレイヤーキャラクターを検知した時にそのプレイヤーキャラクターをターゲットにし、追いかける処理を作成していきます。

Updateメソッドでtargetが指定されていなければreturnをして処理を実行させません。

targetが指定されていれば、ターゲットの位置をNavMeshAgentのSetDestinationメソッドで指定します。

エージェントの現在の速さをアニメーションパラメータのSpeedの値に入れています。

これでUpdateメソッドが呼ばれる度にプレイヤーキャラクターの位置を更新し、移動速度に応じてアニメーションも変更されるようになります。

SetTargetメソッドはSearchPlayerスクリプトから呼び出しターゲットを設定します。

agent.enabledでエージェントが有効な時だけResumeメソッドでエージェントを動かします。

ResetTargetメソッドはSearchPlayerスクリプトから呼び出し、ターゲットをnullにしています。

agent.enabledでエージェントが有効な時はStopメソッドでエージェントを停止します。

SetTarget、ResetTargetメソッドはそれぞれサーバーである時だけ実行する事にします。

ターゲットを見失ったらアニメーションパラメータのSpeedを0にし、Idle状態へと遷移させます。

敵キャラクターのステータススクリプトを作成

敵キャラクターのステータススクリプトを作成します。

プレイヤーキャラクターに設定したUStatusとほとんど同じですね。

UStatusと違うのはhpが0以下になったらDestroyを使ってゲームオブジェクトを削除しているところです。

これで敵キャラクターが出来上がりました。

Enemyインスペクタは下のようになります。

UnityNetworkの敵キャラのインスペクタ1

UnityNetworkの敵キャラのインスペクタ2

シーンオブジェクトの敵の確認

敵キャラクターはナビゲーション機能で動きますので、プレイヤーキャラクターをすり抜けてしまいます。

そこでプレイヤーキャラクターにNavMeshObstacleを取り付け、プレイヤーキャラクターと当たり判定が出来るようにします。

敵がプレイヤーキャラクターと接触出来るようにする

↑のようにプレイヤーキャラクターにNavMeshObstacleを取り付けたらインスペクタの右上のApplyボタンを押してプレハブに反映させておきます。

ナビゲーションで移動する床のゲームオブジェクトのインスペクタの右上のStaticにチェックを入れます。

地面のゲームオブジェクトのStaticにチェックを入れておく

Navigationウインドウ(メニュー→Windows→Navigation)でNavMeshの設定をしてBakeボタンを押します。

NavigationウインドウでBakeボタンを押す

すると地面に薄い青のNavMeshAgentが動ける場所が作成されました。

NavMeshをベイクして敵キャラの移動出来る場所を作成

それではインターネットマッチで接続し、敵キャラクターの同期と敵を攻撃してHPが0以下になった時にゲームオブジェクトが消えるかどうかを確認してみます。

↑のようになりました。

敵キャラクターをインスタンス化して登場させる

先ほどの敵はあらかじめシーン上に存在していました。

途中から敵キャラクターを登場させたいという事もあると思うので、スクリプトから敵キャラクターをネットワーク上にインスタンス化する方法もやってみましょう。

敵キャラクターは先ほど作った敵キャラクターをAssetsフォルダにドラッグ&ドロップしプレハブ化します。

敵用のSpawnPointの作成

敵が登場出来る場所を作成していきます。

ヒエラルキー上で右クリック→Create Emptyで空のゲームオブジェクトを作成し、名前をEnemySpawnPointsとします。

子要素に空のゲームオブジェクトを作成しEnemySpawnPointに番号を付けた名前にします。

敵のSpawnPoint

これで敵が登場する場所の作成が終わりました。

敵のSpawnPointを視覚化した図

↑のような位置に敵の登場位置を作成しました。

敵の数を管理するSpawnEnemyゲームオブジェクトの作成

敵の数を管理するゲームオブジェクトを作成していきます。

ヒエラルキー上で右クリック→Create Emptyを選択、空のゲームオブジェクトを作成して名前をSpawnEnemyとします。

SpawnEnemyゲームオブジェクトにはNetworkIdentityコンポーネントを取り付けServer Onlyにチェックを入れます。

Server Onlyにチェックを入れる事でサーバーだけで動作させる事が出来ます。

SpawnEnemyゲームオブジェクトには新しくSpawnEnemyスクリプトを作成し取り付けます。

spawnPointsには先ほど作った敵を登場させる位置をインスペクタで指定し、enemyには敵のプレハブを指定します。

maxEnemyNumにゲームに登場出来る敵の最大数を指定し、enemyNumは現在出現している敵の数が入ります。

OnStartServerメソッドでspawnPointsの数分の敵をインスタンス化します。

OnStartServerメソッドはNetworkBehaviourのメソッドでサーバーがアクティブになった時に呼び出されます。

これをオーバーライドして記述します。

コルーチンで敵の数を監視し、敵が最大数より少なくなっていたら新しい敵をインスタンス化します。

InstantiateEnemyメソッドが実際に敵をインスタンス化している処理です。

インスタンス化した敵をクライアントでも登場させる為、NetworkServer.Spawnでクライアントに敵を登場させています。

CheckEnemyNumメソッドでは10秒毎に敵の数をチェックし、少なければインスタンス化しています。

SetEnemyNumメソッドは敵を倒した時にenemyNumの数を減らす処理をしていて、EnemyStatusから呼び出します。

EnemyStatusのフィールドとSetHpメソッドに変更を加えます。

StartメソッドでFindObjectOfTypeでSpawnEnemyスクリプトを取得します。

敵のHPが0以下になった時にSpawnEnemyスクリプトのSetEnemyNumメソッドを呼び出し、敵の数を減らします。

NetworkManagerに敵のプレハブを登録

ゲームの途中からインスタンス化するゲームオブジェクトはあらかじめNetworkManagerのSpawn InfoのRegistered Spwanable Prefabsに登録しておきます。

NetworkManagerにインスタンス化するプレハブを登録する

↑のように敵のプレハブを設定します。

敵のインスタンス化の確認をする

これでゲームの途中から敵のプレハブをインスタンス化する事が出来るようになりました。

いくつかアプリケーションを実行し、確認してみましょう。

↑のようになりました。

敵が無限に出てくるのがわかりますね。(^_^)v

今回の仕様では敵の登場位置はランダムに決定しているので、同じ場所敵が登場してしまいます。

SpawnPoint毎に敵の数を管理し、そこから出現した敵が倒された時にその場所から敵を生成するようにするとより本格的な感じになりますね。

参考サイト

Unityマニュアルーマルチプレイヤーシューティングを追加するー

Unityチュートリアル-非プレイヤーオブジェクトをハンドルする-

スポンサーリンク

記事をシェアして頂ける方はこちら

フォローして頂くとやる気が出ます