今回はUnityNetworkでオンライン対応の第4回で、キャラクターのHPの表示と他のキャラクターへの攻撃の機能を作成していきたいと思います。
前回は、キャラクターの同期とカメラの設定を行いました。
キャラクターへの攻撃機能を作成すると、オンラインに接続した他のキャラクターと対戦をするようなゲームを作る事が出来ます。
キャラクターのステータス
キャラクターのステータススクリプトとHP表示用UIを作成していきます。
Hp表示用UIの作成
まずはUnityNetworkPlayerの子要素に右クリック→UI→Textを作成し、名前をHpと変更します。
↑のような感じになります。
Hpを選択し、インスペクタでCanvasのRender ModeをWorld Spaceにし、ワールド空間のUIにします。
RectTransformのWidthやHeightのサイズ変更、子要素のTextをAnchorをstretch、stretchにしてCanvasサイズにテキストのサイズを合わせます。
↑のような設定値を入れました。
実際のHp用のUIは
↑のような感じの位置と大きさにしました。
またHpゲームオブジェクトは常にカメラの方向を向かせたいのでRotateHpTextスクリプトを作成しHpゲームオブジェクトに設定します。
1 2 3 4 5 6 7 8 9 10 11 12 | using UnityEngine; using System.Collections; public class RotateHPText : MonoBehaviour { // Update is called once per frame void Update () { transform.rotation = Camera.main.transform.rotation; } } |
これでキャラクターの移動と共にHpを表示したUIも移動することになります。
キャラクターステータス処理スクリプトの作成
キャラクターのステータス関連の処理を行うUStatusスクリプトを作成しUnityNetworkPlayerゲームオブジェクトに取り付けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | using UnityEngine; using System.Collections; using UnityEngine.Networking; using UnityEngine.UI; public class UStatus : NetworkBehaviour { // HP表示用テキストUI public Text hpText; // 攻撃力 public int attackPower; private int maxHp = 100; // 体力 [SyncVar (hook = "OnChangeHP")] public int hp; // ユニークID [SyncVar] public NetworkInstanceId id; void Start() { hpText.text = hp.ToString (); id = GetComponent <NetworkIdentity> ().netId; } public int GetAttackPower() { return attackPower; } public void SetHp(int hp) { this.hp = hp; hpText.text = this.hp.ToString (); } public int GetHp() { return hp; } // ダメージ処理 public void TakeDamage(int damage) { SetHp (GetHp () - damage); } // SyncVar指定したhpに変更があったら呼び出される void OnChangeHP(int hp) { hpText.text = hp.ToString (); } public NetworkInstanceId GetId() { return this.id; } } |
UStatusスクリプトではキャラクターのHPと攻撃力を保持し、キャラクターがダメージを受けた時の処理も担当する事にします。
hpフィールドは[SyncVar]アトリビュートを取り付け同期するようにします。
フックでOnChangeHPメソッドを指定しているので、サーバーでhpの値が書き変わった時にクライアントでOnChangeHPメソッドが実行されます。
StartメソッドでHPを初期設定したくなりますが、ここで初期設定をしてしまうと自身のアプリケーション上のキャラクター全部のHPを設定してしまうので、HP表示用テキストの値にhpを設定するだけにします。
こうすることで他のキャラクターはSyncVarで同期されているのでその値が表示され、自身はインスペクタで設定した値になります。
自身のアプリケーション上のキャラクターには固有のIDを設定するようにします。
クライアント上で二人プレイをしてオンラインに繋ぐ場合はクライアント上でもユニークなIDを取り付ける必要があるかもしれません。
そこら辺は必要になったら対応していくという事で、今のところは無視していきます・・・・。
TakeDamageメソッドは攻撃を受けた時に呼び出されます。
[SyncVar]を付けたhpは同期されます。
クライアントではフックを使ってOnChangeHPメソッドが呼び出されるので、キャラクターのHPをHP表示用UIに再設定しています。
ここら辺の処理は混乱しますねぇ・・・・(^_^;)
とりあえずこれでキャラクターのHP表示用UI、ステータス関連の処理スクリプトの作成が完了しました。
UnityNetworkPlayerゲームオブジェクトにUStatusスクリプトを取り付けます。
UStatusのHpTextにはUnityNetworkPlayerの子要素のHP表示用UIをドラッグ&ドロップし、AttackPowerには10、Hpには100を設定しておきます。
攻撃機能の作成
次にキャラクターが剣を振って他のキャラクターに当たった時の処理を作成していきます。
まずはUnityNetworkPlayerのタグにPlayerタグを設定しておきます。
これは剣が当たったコライダがキャラクターである事を判別する為です。
次に剣にUAttackスクリプトを作成し取り付けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | using UnityEngine; using System.Collections; using UnityEngine.Networking; public class UAttack : MonoBehaviour { private UStatus uStatus; void Start() { uStatus = transform.root.GetComponent <UStatus> (); } void OnTriggerEnter(Collider col) { // 相手にPlayerタグが設定されていて、かつ自身のネットワークIDと違うキャラだった時にダメージを与える if (col.tag == "Player" && col.GetComponent <UStatus>().GetId() != uStatus.GetId ()) { col.GetComponent <UStatus>().TakeDamage(uStatus.attackPower); } } } |
フィールドにUStatus型のuStatusを宣言し、Startメソッドで自身の親に設定しているUStatusスクリプトを取得します。
OnTriggerEnterメソッドは剣のコライダが他のコライダと接触した時に呼ばれるので、ここで他のキャラクターと接触したかを判定します。
まずはタグにPlayerが設定されていなければいけません(キャラクターとの当たり判定をする為)、
そして、Playerタグとの接触だけだと自分で振った剣が自分のコライダと接触した時も条件が成立してしまいます。
つまり剣を振るだけで自分の体力が減るわけですね・・・・(^_^;)
というわけで、接触したコライダが自身のキャラなのか他のキャラなのかの条件も加えます。
そこでキャラクターに設定したUStatusのGetIdでネットワークIDを調べて判定する事にします。
条件が成立した場合は接触した相手が持っているUStatusスクリプトのTakeDamageメソッドを呼び出しています。
これで攻撃処理も完成しました。
HP表示と攻撃機能の確認
機能が出来たので、ビルドした後複数アプリケーションを起動し確認してみましょう。
↑のようになりました。
攻撃を受けると自身のアプリケーションの他のキャラクターのHPが減り、他のアプリケーションのキャラクターのHPも変わっていますね。
後からログインしたプレイヤーにはすでにダメージを受けたキャラクターのHPは減った状態で表示されているのがわかります。
攻撃が当たっているように見えてHPが減っていないのはオンラインとは関係ない部分が大きく、単純に当たり判定のすり抜けが起きているからです。
そちらは
↑を参照してください。
終わりに
SyncVarアトリビュートを使ってHPを同期する事が出来ました。
サーバーのキャラクターのHPだけを減らし、それをクライアントの値と同期するという感じですね。
混乱しますが・・・・(^_^;)
今回はHPを減らす事が出来るようになりましたが、HPが0以下になっても何も処理をしてません。
そこで、次回はキャラクターの登場位置の設定と、HPが0になった時に再度登場させる機能を作成していきます。