LoginSignup
ohshi_hi
@ohshi_hi

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

ホストとクライアントの通信確立後にホストでオブジェクトを生成し所有権をクライアントに渡したい

解決したいこと

ホストとクライアントの通信確立後にホストでオブジェクトを生成し所有権をクライアントに渡したい。
クライアント側でそのオブジェクトを移動したり弾を打ったりできるようにしたい。

発生している問題・エラー

Netcode for GameObjectsを使って1対1のマルチプレイゲームを作っています。
現在、ホスト側で"Unity.Netcode.NetworkManager.Singleton.StartHost();"を実行した後、オブジェクトを生成してそのオブジェクトの所有権をクライアントに変えるよう実装しています。

所有権をクライアントに変えているのは、クライアント側でそのオブジェクトを移動したり弾を打ったりしたいからです。

デバッグを確認する限り特別エラーが出ているわけではないですが、生成したオブジェクトの操作がホストの方でしかできないようになっています。また、ホスト側でもデバッグ処理は適切ですが画面に動きの反映がされないです。

調べてみたところ、"NetworkManager.Singleton.OnClientConnectedCallback += HandleClientConnected;"という方法でクライアントがコネクトしたことを伝えることでメソッドを実行できる方法があるらしいので試してみたのですが、呼び出し元がクライアントといった理由?でエラーが出てしまいました。

解決方法を教えていただきたいです。

または、問題・エラーが起きている画像をここにドラッグアンドドロップ

該当するソースコード

通信に関するスクリプト

using System.Collections;
using System.Collections.Generic;
using System.Net;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;


public class NetworkUI : NetworkBehaviour
{
    // IPアドレスフィールドを定義する
    public InputField ipAddressField;
    public GameObject avatarPrefab; // アバターのプレハブ

    public GameObject StartButton;
    public GameObject InputIPaddress;
    public GameObject host;
    public GameObject client;
    public GameObject StartHaikei;

    private LauncherCamControll launcherCamControll;
    private FireBullet3 FireBullet3;

    private void Start()
    {
        launcherCamControll = FindObjectOfType<LauncherCamControll>();
        FireBullet3 = FindObjectOfType<FireBullet3>();
        //NetworkManager.Singleton.OnClientConnectedCallback += HandleClientConnected;
    }
    //private void Awake() //接続開始を知らせる
    //{
        // Unity Netcodeのイベントを設定
        //NetworkManager.Singleton.OnClientConnectedCallback += HandleClientConnected;
    //}


    // Start is called before the first frame update
    public void StartHost()
    {
        // IPアドレスを取得する
        string ipAddress = ipAddressField.text;

        // Parse the IP address string into a valid IP format
        IPAddress address;
        if (IPAddress.TryParse(ipAddress, out address))
        {
            // Set the connection data for the Unity Transport
            NetworkManager.Singleton.GetComponent<UnityTransport>().SetConnectionData(
                address.ToString(),  // The IP address as a string
                (ushort)7777         // The port number as an unsigned short
            );
            

            Unity.Netcode.NetworkManager.Singleton.StartHost();
            FireBullet3.GenerateBulletOnServer();
            //FireBullet1.AwakeLauncher();
            //launcherCamControll.SetLauncherCam();


        }
    }

    // Update is called once per frame
    public void StartClient()
    {
        // IPアドレスを取得する
        string ipAddress = ipAddressField.text;

        /// Parse the IP address string into a valid IP format
        IPAddress address;
        if (IPAddress.TryParse(ipAddress, out address))
        {
            // Set the connection data for the Unity Transport
            NetworkManager.Singleton.GetComponent<UnityTransport>().SetConnectionData(
                address.ToString(),  // The IP address as a string
                (ushort)7777         // The port number as an unsigned short
            );
            // アバターのデータを保存
            //SaveAvatarData();

            Unity.Netcode.NetworkManager.Singleton.StartClient();

            //FireBullet2.AwakeLauncher();
            //launcherCamControll.SetLauncherCam();
        }
    }

    private void HandleClientConnected(ulong clientId)  //lancherを起動させる
    {
        Debug.Log("Client with ID " + clientId + " has connected to the server.");
        if (IsHost)
        {
            FireBullet3.GenerateBulletOnServer();
        }

    }



    public void StartGame()
    {
        StartButton.SetActive(false);
        InputIPaddress.SetActive(false);
        host.SetActive(false);
        client.SetActive(false);
        StartHaikei.SetActive(false);
    }
    


}

Launcher(生成したいオブジェクト)に関するスクリプト

using Unity.Netcode;

using UnityEngine;

public class FireBullet3 : NetworkBehaviour
{
    [SerializeField]
    [Tooltip("弾の発射場所")]
    private GameObject firingPoint;

    [SerializeField]
    [Tooltip("弾")]
    private GameObject bullet;

    [SerializeField]
    [Tooltip("弾の速さ")]
    private float speed = 650f;

    [SerializeField]
    [Tooltip("Laucher")]
    private GameObject Launcher;

    private bool hasOwnership = false;
    private LauncherCamControll launcherCamControll;
    private Transform initialPosition;

    private void Start()
    {
        launcherCamControll = FindObjectOfType<LauncherCamControll>();
    }

    //使っていない
    public void AwakeLauncher()
    {
        Debug.Log("Awakeメソッド起動");

        if (IsHost)
        {
            //SpawnLauncher();
            Debug.Log("SpanLauncher起動");
            hasOwnership = true;
        }
    }


    public void GenerateBulletOnServer()
    {
        //ネットワークオブジェクトの生成
        NetworkObject NetLauncher = Instantiate(Launcher).GetComponent<NetworkObject>();
        NetLauncher.Spawn();
        Debug.Log("Spawn");
        //launcherCamControll.SetLauncherCam();

        //ホスト側でクライアントIDを取得、所有権変更
        ulong clientId = NetworkManager.Singleton.LocalClientId;
        Debug.Log(clientId);
        NetworkObject launcherNetworkObject = NetLauncher.GetComponent<NetworkObject>();
        launcherNetworkObject.ChangeOwnership(clientId);
        Debug.Log("ChangeOwnerShip");

        //送信
        //SetLauncherClientRpc(clientId);
    }


    //使っていない
    private void SpawnLauncher()
    {
        Vector3 launcherPosition = firingPoint.transform.position;
        GameObject newLauncher = Instantiate(Launcher, launcherPosition, transform.rotation);

        // ランチャーの向きなどを設定する必要がある場合はここで設定する

        newLauncher.name = Launcher.name;
        launcherCamControll.SetLauncherCam();
        

        // サーバーに同期情報を送信  位置情報向きいらない
        //SetLauncherServerRpc(newLauncher, launcherPosition, newLauncher.transform.forward);
    }

    
    void Update()
    {
        if (IsOwner)
        {
            // スペースキーが押されたかを判定
            if (Input.GetKeyDown(KeyCode.Space))
            {
                // 弾を発射する
                LauncherShot();
                Debug.Log("発射");
            }

            // 左キーが押されているかを判定
            if (Input.GetKey(KeyCode.LeftArrow))
            {
                // オブジェクトをy軸を中心に10度回転させる
                transform.Rotate(0f, Input.GetAxis("Horizontal") * -20f * Time.deltaTime, 0f);
                Debug.Log("左");
            }

            // 右キーが押されているかを判定
            if (Input.GetKey(KeyCode.RightArrow))
            {
                // オブジェクトをy軸を中心に-10度回転させる
                transform.Rotate(0f, -Input.GetAxis("Horizontal") * 20f * Time.deltaTime, 0f);
                Debug.Log("右");
            }
        }
    }

    //弾を打つ
    private void LauncherShot()
    {
        Vector3 bulletPosition = firingPoint.transform.position;
        GameObject newBall = Instantiate(bullet, bulletPosition, transform.rotation);
        Vector3 direction = transform.forward;
        direction = Quaternion.Euler(-15f, 0f, 0f) * direction;
        newBall.GetComponent<Rigidbody>().AddForce(direction * speed, ForceMode.Impulse);
        newBall.name = bullet.name;

        SetLauncherRotationServerRpc(transform.rotation);
        LaunchBulletServerRpc(bulletPosition, direction, speed);
    }

    public void ChangeLauncherRotation(Quaternion newRotation)
    {
        if (IsOwner)
        {
            SetLauncherRotationServerRpc(newRotation);
        }
    }

    //ホストでオブジェクト生成した際に呼ぶ
    [Unity.Netcode.ClientRpc]
    private void SetLauncherClientRpc(ulong newClientId)
    {
        // オブジェクトの所有権が変更された際に実行したい処理をここに記述
    }

    [Unity.Netcode.ServerRpc]
    private void SetLauncherRotationServerRpc(Quaternion rotation)
    {
        transform.rotation = rotation;
        Debug.Log("SetLauncherRotation起動");
        SetLauncherRotationClientRpc(rotation);
    }

    [Unity.Netcode.ServerRpc]
    private void LaunchBulletServerRpc(Vector3 position, Vector3 direction, float bulletSpeed)
    {
        LaunchBullet(position, direction, bulletSpeed);
        Debug.Log("LauncherBullet起動");
    }



    


    [Unity.Netcode.ServerRpc] //初期位置をHostに送る
    private void SetLauncherServerRpc(Vector3 position, Quaternion rotation)
    {
        //GenerateBulletOnServer(position, rotation);
    }




    private void LaunchBullet(Vector3 position, Vector3 direction, float bulletSpeed)
    {
        GameObject newBullet = Instantiate(bullet, position, Quaternion.LookRotation(direction));
        newBullet.GetComponent<Rigidbody>().AddForce(direction * bulletSpeed, ForceMode.Impulse);
    }

    [Unity.Netcode.ClientRpc]
    private void SetLauncherRotationClientRpc(Quaternion rotation)
    {
        if (IsOwner)
        {
            transform.rotation = rotation;
        }
    }
}




自分で試したこと

これを参考に実装しました。

0

No Answers yet.

Your answer might help someone💌