【问题标题】:Instantiate GameObjects over network通过网络实例化游戏对象
【发布时间】:2018-10-28 08:57:00
【问题描述】:

我有一段代码应该生成一个随机图块地图,它只为服务器执行。我不知道如何让它在玩家加入时同步到玩家。我将如何同步加入玩家的预制件?它们在一个玩家(服务器)上加载,但当另一个玩家加入时,它们不会出现。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class GenerateLevel : NetworkBehaviour {
public int MapSize = 20;
public GameObject prefab;
public GameObject _LeftW;
public GameObject _RightW;
public GameObject _TopW;
public GameObject _Botw;
public GameObject SpawnLocRed;
public GameObject SpawnLocBlue;

public string map;
public override void OnStartServer()
{
    //base.OnStartServer();
    GetComponent<Renderer>().material.color = Color.blue;

}

void Start()
{
    if (!isServer)
    {
        return;
    }


    for (int c = MapSize / 2; c > -MapSize / 2; c--)
    {

        for (int r = -MapSize / 2; r < MapSize / 2; r++)
        {
            var t = Instantiate(prefab, new Vector3(r, 0, c), 
Quaternion.identity);
            NetworkServer.Spawn(t);
            Debug.Log("Col:" + c + " Row:" + r);

            if (Random.Range(0, 3) == 2)
            {
                t.GetComponent<RAISE>().Run();
                map += 1;
            }
            else
            {
                map += 0;
                if (c < 0 - MapSize / 4 && r > 0 + MapSize / 4)
                {
                   var red= Instantiate(SpawnLocRed, new Vector3(r, 2, c), 
Quaternion.identity);
                }
                if (c > 0 + MapSize / 4 && r < 0 - MapSize / 4)
                {
                   var blue= Instantiate(SpawnLocBlue, new Vector3(r, 2, c), 
Quaternion.identity);

                }
            }

            map += "r";

        }
        map += "c";
    }
    Debug.Log(map);
    if (MapSize % 2 == 0)
    {
        GameObject wt = Instantiate(_TopW, new Vector3(-.5f, 0, -MapSize / 2), Quaternion.identity);
        wt.transform.localScale = new Vector3(MapSize, 5, 1);
        GameObject wb = Instantiate(_Botw, new Vector3(-.5f, 0, MapSize / 2+1), Quaternion.identity);
        wb.transform.localScale = new Vector3(MapSize, 5, 1);
        GameObject wl = Instantiate(_LeftW, new Vector3(-MapSize / 2-1, 0, .5f), Quaternion.identity);
        wl.transform.localScale = new Vector3(1, 5, MapSize+2);


        GameObject wr = Instantiate(_RightW, new Vector3(MapSize / 2, 0, .5f), Quaternion.identity);
        wr.transform.localScale = new Vector3(1, 5, MapSize+2);
    }
    else
    {
        GameObject wt = Instantiate(_TopW, new Vector3(-.5f, 0, -MapSize / 2), Quaternion.identity);
        wt.transform.localScale = new Vector3(MapSize-1, 5, 1);
        GameObject wb = Instantiate(_Botw, new Vector3(-.5f, 0, MapSize / 2 + 1), Quaternion.identity);
        wb.transform.localScale = new Vector3(MapSize-1, 5, 1);


        GameObject wl = Instantiate(_LeftW, new Vector3(-MapSize / 2 - 1, 0, .5f), Quaternion.identity);
        wl.transform.localScale = new Vector3(1, 5, MapSize + 1);


        GameObject wr = Instantiate(_RightW, new Vector3(MapSize / 2, 0, .5f), Quaternion.identity);
        wr.transform.localScale = new Vector3(1, 5, MapSize + 1);
    }
    Debug.Log(MapSize % 2);
}

这是更新的sn-p代码

public GameObject[] tiles = new GameObject[1000];
public string map;
public override void OnStartServer()
{
    //base.OnStartServer();
    GetComponent<Renderer>().material.color = Color.blue;

}
public void OnPlayerConnected(NetworkPlayer player)
{
    foreach(GameObject go in tiles)
    {
        NetworkServer.Spawn(go);
    }
}

void Start()
{
    if (!isServer)
    {
        return;
    }
    int temp = 0;

    for (int c = MapSize / 2; c > -MapSize / 2; c--)
    {

        for (int r = -MapSize / 2; r < MapSize / 2; r++)
        {
            var t = Instantiate(prefab, new Vector3(r, 0, c), Quaternion.identity);
            tiles[temp] = t;
            NetworkServer.Spawn(t);
         }
     }
}

经过一番摆弄,我得到了要生成的图块,但它们没有同步为每个客户端单独运行的 henerate 图块的字符。

【问题讨论】:

    标签: c# unity3d unity3d-unet unet


    【解决方案1】:

    您不能只使用Instantiate 函数让预制件在网络上显示。您还必须做其他事情:

    1。您必须通过 NetworkManager 组件注册预制件。如果有多个预制件,您必须为所有预制件执行此操作:

    2.将NetworkIdentity 组件附加到预制件。请注意,如果您还想同步对象变换,则必须将 NetworkTransform 也附加到预制件。

    3.实例化预制件后,使用NetworkServer.Spawn也在网络上实例化它。

    例如:

    //Instantiate on this device
    GameObject red = Instantiate(SpawnLocRed, new Vector3(r, 2, c), 
    Quaternion.identity);
    //Instantiate it on all clients
    NetworkServer.Spawn(red);
    

    最后,您可能希望将所有代码封装在 isLocalPlayer 内,以确保您仅从本地播放器实例化。

    if (isLocalPlayer)
    {
        //Instantiate on this device
        GameObject red = Instantiate(SpawnLocRed, new Vector3(r, 2, c), 
        Quaternion.identity);
        //Instantiate it on all clients
        NetworkServer.Spawn(red);    
    }
    

    【讨论】:

    • 在第 3 步之前我已经完成了所有设置,但问题是生成器是随机的。我怎样才能让它运行一次,然后将其同步到所有客户端?我添加了一些图片。
    • 我提到了我的答案,尤其是 第 3 步。使用Instantiate 实例化一次并将对象存储在列表中。当新客户端加入时,循环这些列表并在客户端上使用NetworkServer.Spawn 实例化它们。
    • 没有。使用 List 而不是数组,以便您可以调整它的大小。如果是服务器,则使用Instantiate 进行实例化并添加到列表中。否NetworkServer.Spawn......如果是客户端,循环列表并用NetworkServer.Spawn(currentListLoop);实例化每个列表
    • 类似" public List tiles = new List(); public void OnPlayerConnected(NetworkPlayer player) { foreach(GameObject go in tiles) { Instantiate(go); NetworkServer. Spawn(go); } } with var t = Instantiate(prefab, new Vector3(r, 0, c), Quaternion.identity); tiles.Add(t); 仅在服务器脚本中
    • 我添加了另一张图片来显示它所显示的不同步,看起来地图生成了两次,每次都没有与上一次同步。
    猜你喜欢
    • 1970-01-01
    • 2019-04-10
    • 2016-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多