Perl日記

PerlとかRubyとかPHPとかPythonとか

MLAPI その7

スペースキーを押したら弾がでるようにしたい。

Capsule をシーン内に入れて、Bullet という名前にする。
最初はネットワーク同期をやってみたいので、NetworkedObject をアタッチ。
適当にスケールを小さくして、Prefab にして、シーン内から削除。

NetworkingManager の NetworkedPrefabs の「+」から Bullet を追加する。
ここの Prefab は、MLAPI.NetworkingManager.Singleton.NetworkConfig.NetworkedPrefabs で取れるらしい。

f:id:rightgo09:20201207225221p:plain

スペースキーを押したときに、弾が出現するようにしてみる。

public class PlayerCubeController : MLAPI.NetworkedBehaviour
{

    private void Update()
    {
        if (!IsOwner)
        {
            return;
        }

        // 移動のやつ

        // スペースキーを押して弾出現
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Shoot();
        }
    }

    private void Shoot()
    {
        GameObject prefab = MLAPI.NetworkingManager.Singleton.NetworkConfig.NetworkedPrefabs[1].Prefab;
        GameObject go = Instantiate(prefab, new Vector3(Random.Range(-9, 9), 1.0f, Random.Range(-9, 9)), Quaternion.Euler(0, 0, 90));
        go.GetComponent<MLAPI.NetworkedObject>().Spawn();
    }

ホストだけで確認するとこれでよかったが、クライアントと一緒に試すとエラーがでる。

ArgumentException: An item with the same key has already been added. Key: 1

これはホストとクライアントで同じことをしようとしてエラーが起こっているらしい。


たぶんやり方は 2 つあって、サーバに実行を集約させてクライアントは享受するだけにするか、自クライアントで実行する+それ以外のクライアントに実行させるか。


とりあえず前者で、サーバ RPC で実行する。

        if (Input.GetKeyDown(KeyCode.Space))
        {
            InvokeServerRpc(Shoot);
        }
    }

    [MLAPI.Messaging.ServerRPC]
    private void Shoot()
    {
        // 略
    }

f:id:rightgo09:20201207225655p:plain

たぶんこのやり方だとスペースキーを押してから、サーバへ通信を往復して実行してる分、若干ラグがあるのかな? もし完全に同期を求められないようなやつなら、後者の自クライアントで実行しつつ、サーバを介して他のクライアントで実行が良さそうかなと思った。

参考:
https://mlapi.network/wiki/messaging-system/