プレイヤーの体力をネットワーク化する

確認済のバージョン: 5.3

-

難易度: 中級

プレイヤーの現在の体力の変更はサーバーにおいてのみ適用されるべきものです。その後でクライアント上で同期されます。これは サーバー権限 と呼ばれます。 サーバー権限についての詳細はネットワークシステムの概念に関するページをご覧ください。

現在の体力とダメージのシステムをネットワークに連携させ、サーバー権限の下で機能させるには、ステート同期(State Synchronization) および、ネットワークオブジェクトの特殊なメンバー変数「 SyncVar 」を使用する必要があります。ネットワーク同期された変数、あるいは SyncVar は、***[SyncVar] *** 属性 によって指定されます。SyncVar に関する詳細は、ステートの同期(State Synchronization)に関するページをご覧ください。

  • 編集用に Health スクリプトを開いてください。
  • 名前空間 UnityEngine.Networking を追加してください。
using UnityEngine.Networking;

  • スクリプトを、NetworkBehaviour から派生するように変更してください。
public class Health : NetworkBehaviour

  • Make currentHealth a [SyncVar].
[SyncVar]
public int currentHealth = maxHealth;

  • “isServer” のチェックを TakeDamage 関数に追加してください。これにより、ダメージがサーバー上のみで適用されるようになります。
if (!isServer)
{
    return;
}

最終的なスクリプトは以下のようになります。

Health (体力)

Code snippet

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

public class Health : NetworkBehaviour {

    public const int maxHealth = 100;

    [SyncVar]
    public int currentHealth = maxHealth;
    public RectTransform healthBar;

    public void TakeDamage(int amount)
    {
        if (!isServer)
        {
            return;
        }
        
        currentHealth -= amount;
        if (currentHealth <= 0)
        {
            currentHealth = 0;
            Debug.Log("Dead!");
        }

        healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y);
    }
}
  • スクリプトを保存します。
  • Unity に戻ってください。
  • このシーンを、スタンドアロンのアプリケーションとして Build and Run(ビルドおよび実行)します。
  • ゲーム内 UI から Host ボタンをクリックすると、このゲームがホストとして開始されます。
  • Player ゲームオブジェクトを動かしてください。
  • Unity に戻ってください。
  • Play モードを開始します。
  • ゲーム内 UI から LAN Client ボタンをクリックすると、クライアントとしてホストに接続されます。

プレイヤーの「現在の体力」が、サーバーのみに適用された上で全てのクライアントで同期されるようになっているはずです。

ただし、Healthbar (体力ゲージ)はゲームの全てのインスタンスで機能している訳ではないので、これを全てのクライアント上で確認することは困難です。変数 currentHealth はパブリックであり、エディター上で見ることができます。ホストではなく接続されたクライアントとしてエディターが実行されている場合は、プレイヤーゲームオブジェクトの「現在の体力」はインスペクターで簡単に確認できるはずです。

description

また Healthbar が、サーバーに付属したホストクライアントのみで機能しており、その他のクライアントでは機能していないことも簡単に確認できるでしょう。

これは、Foreground ゲームオブジェクトの RectTransform がネットワーク経由で同期されておらず、Healthbar の Size Delta を設定するコードがサーバーのみで実行されているからです。Healthbar がホストクライアントで機能するのは、ホストクライアントはサーバーにとってローカルだからです。ホストクライアントはサーバーと同じシーンを共有するため、専用にシリアライズされたデータは持っていません。

ここで、Healthbar の Foreground ゲームオブジェクトの RectTransform を同期する必要があります。

  • スタンドアロン プレイヤーを終了してください。
  • Unity に戻ってください。
  • Play モードを終了してください。

ここで、ステート同期(State Synchronization)の為のもうひとつのツール、SyncVar フック の登場です。SyncVar フックは、関数を SyncVar と結び付けます。これらの関数は、SyncVar の値が変わるとサーバーおよび全てのクライアント上で呼び出されます。SyncVar と SyncVar フックに関する詳細は、ステート同期(State Synchronization)に関するページをご覧ください。

  • 編集用に Health スクリプトを開いてください。
  • Healthbar を変化させるコードを、OnChangeHealth という名前の独自の関数内に移動してください。
void OnChangeHealth (int currentHealth)
{
    healthBar.sizeDelta = new Vector2(health, currentHealth.sizeDelta.y);
}

この関数は、[SyncVar] 属性の変数と同じタイプのパラメーター(ここでは int currentHealth)を持つ必要があることにご注目ください。また、SyncVar の現在の値は、フックされた関数へ 1 つの引数として送られることも覚えておくと良いでしょう。

  • currentHealth の SyncVar 属性内に、この新しい関数へのフックを設定してください。
[SyncVar(hook = "OnChangeHealth")]

最終的なスクリプトは以下のようになります。

Health (体力)

Code snippet

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

public class Health : NetworkBehaviour {

    public const int maxHealth = 100;

    [SyncVar(hook = "OnChangeHealth")]
    public int currentHealth = maxHealth;

    public RectTransform healthBar;

    public void TakeDamage(int amount)
    {
        if (!isServer)
            return;
        
        currentHealth -= amount;
        if (currentHealth <= 0)
        {
            currentHealth = 0;
            Debug.Log("Dead!");
        }
    }

    void OnChangeHealth (int health)
    {
        healthBar.sizeDelta = new Vector2(health, healthBar.sizeDelta.y);
    }
}

これで、currentHealth の値が変わると OnChangedHealth がサーバーおよび全てのクライアント上に呼び出されて Healthbar が更新されるようになりました。

  • スクリプトを保存します。
  • Unity に戻ってください。
  • このシーンを、スタンドアロンのアプリケーションとして Build and Run(ビルドおよび実行)します。
  • ゲーム内 UI から Host ボタンをクリックすると、このゲームがホストとして開始されます。
  • Player ゲームオブジェクトを動かしてください。
  • Unity に戻ってください。
  • Play モードを開始します。
  • ゲーム内 UI から LAN Client ボタンをクリックすると、クライアントとしてホストに接続されます。

プレイヤーが互いに撃ち合うと、全ての体力ゲージ(Healthbar)がプレイヤーゲームオブジェクトの「現在の体力」(Current Health)を反映するようになっているはずです。Healthbar は同期されており、ゲームの全てのインスタンス内で機能しています。

  • スタンドアロン プレイヤーを終了してください。
  • Unity に戻ってください。
  • Play モードを終了してください。