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.クライアントに同期された弾丸
- まず、NetWorkManagerで生成する必要のある箇条書きを追加します
- すべての箇条書きはサーバーによって生成されてから、各クライアントに同期される必要があります。弾丸を生成するfireメソッドの前に[Command]を追加し、メソッド名をCmdFire()に変更します。これは、このメソッドがサーバー側で呼び出されることを意味します。
- 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.ヘルスバーディスプレイをプレーヤーに追加します
- スライダーを作成する
- スライダーのキャンバスとLookAtCameraスクリプトにより、ヘルスバーがプレーヤーと一緒に回転するのを防ぎます
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LookAtCamera : MonoBehaviour
{
void Update()
{
transform.LookAt(Camera.main.transform);
}
}
- ヘルスロジックを記述して、スライダーデータとバインドします
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;
}
}