Unityマルチプレイヤーオンラインゲーム(1)

1.NetWorkManagerの空のオブジェクト管理ネットワークを作成します

新しいシーンを作成し、シーンの下に空のオブジェクトNetWorkManagerをマウントし、NetWorkManagerおよびNetworkManagerHUDコンポーネントを追加します

2.プレーヤーオブジェクトを追加します

  • Playerオブジェクトを追加し、プレハブプレハブとして生成します
  • PlayerControllerスクリプトをマウントして、オブジェクトの回転と動きを制御します

3.クライアントオブジェクトとサーバーオブジェクトの同期を実現します

  • プレハブをロードした後、サーバーとクライアントの2人のプレーヤーが同時に移動していることがわかります。解決策:isLocalPlayerプロパティを持つNetworkBehaviourからplayercontrollerを継承します。ローカルプレーヤーでない場合は、何も返さないでください。
  • 両側の位置を同期します。同期機能を実現するには、プレーヤーにNetworkTransformをマウントします。

4.ローカルオブジェクトの色を変更します

 public override void OnStartLocalPlayer()
    {
        //只在本地对象初始化完成后调用
        GetComponent<MeshRenderer>().material.color = Color.blue;
    }

5.主人公の射撃を制御する

スペースバーを押して弾丸を発射します

 private void fire()
    {
        GameObject bullet = Instantiate(bulletPrefab, bulletPos);
        bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * 10f;
        Destroy(bullet, 2);
    }

6.クライアントに同期された弾丸

  1. まず、NetWorkManagerで生成する必要のある箇条書きを追加します
    画像-20210326120216270
  2. すべての箇条書きはサーバーによって生成されてから、各クライアントに同期される必要があります。弾丸を生成するfireメソッドの前に[Command]を追加し、メソッド名をCmdFire()に変更します。これは、このメソッドがサーバー側で呼び出されることを意味します。
  3. NetWorkTransformを弾丸オブジェクトに追加して、弾丸を同期します
 [Command]
   private void CmdFire()
   {
       GameObject bullet = Instantiate(bulletPrefab, bulletPos);
       bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * 10f;
       Destroy(bullet, 2);


       //同步到各个客户端
       NetworkServer.Spawn(bullet);
   }

7.ヘルスバーディスプレイをプレーヤーに追加します

  1. スライダーを作成する
    画像-20210326144916171
  2. スライダーのキャンバスとLookAtCameraスクリプトにより、ヘルスバーがプレーヤーと一緒に回転するのを防ぎます
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LookAtCamera : MonoBehaviour
{
  

   void Update()
   {
       transform.LookAt(Camera.main.transform);
   }
}
  1. ヘルスロジックを記述して、スライダーデータとバインドします
public class Health : MonoBehaviour
{
   // 固定血量
   public int bloodCount = 100;
   public int allBlood = 100;
   public Slider slider;

   public void takeDemage()
   {
       //受到伤害
       if (bloodCount > 0)
       {
           bloodCount -= 10;
           slider.value = bloodCount / (float)allBlood;
       }
   }
}

8.ヘルスバーと血液量を同期させます

さらに厄介な点は、上記の手順7の後で、サーバーのHPが低下しているが、クライアントのHPは低下しないか、ほとんど低下しないことです。これは、ファイアロジックがサーバーによって処理されるためです。ネットワークと伝送の問題により、サーバーはクライアントよりも高速に実行する必要があります。サーバーが衝突してこのオブジェクトを破棄すると、クライアントにはこれがありません。オブジェクトがなくなったためです。その衝突検出をタイムリーに実行することができず、血液量が減少します。

解決策:血液量削減のロジックでは、サーバー側でのみ処理でき、クライアント側でも同期操作のみを実行できます。

public class Health : NetworkBehaviour
{
    // 同步血量
    [SyncVar(hook ="OnChangeHealth")]
    public int bloodCount = 100;
    public int allBlood = 100;
    public Slider slider;

    public void takeDemage()
    {
        if (!isServer) return;
        //受到伤害
        if (bloodCount > 0)
        {
            bloodCount -= 10;
        }
    }

    //检测到SncVar 标准的变量变化后,就会执行 OnChangeHealth 这个方法
    void OnChangeHealth(int health)
    {
        slider.value = bloodCount / (float)allBlood;
    }
}

おすすめ

転載: blog.csdn.net/woshihaizeiwang/article/details/115249370