UNET:正确注册动态对象

时间:2017-10-25 02:00:49

标签: c# unity3d networking spawn unet

我正在制作一个个人项目,作为一些业余爱好者在编程时。我对这个项目的目标是总结让玩家构建和定制自己的船只,然后加入公共服务器并与之抗争。

我得到的错误是这样的:

  

无法生成服务器对象,assetId = 000000000000000000000000000000e7 netId = 3 UnityEngine.Networking.NetworkIdentity:UNetStaticUpdate()

以下是最相关的代码:

    public void LoadShip(Vector2 pos, string path = "save.xml",Ship oldship = null){
    Debug.Log ("Loading Ship!");
    ShipObject shipObj;
    if (oldship != null) {
        shipObj = oldship.shipObjectClass;
    } else {
        GameObject newShip = new GameObject ();
        shipObj = newShip.AddComponent<ShipObject> ();
        Rigidbody2D rb = newShip.AddComponent<Rigidbody2D> ();
        rb.gravityScale = 0;
        rb.drag = 0.1f;
        rb.angularDrag = 0.1f;
    }
    shipObj.PrepareForLoad ();
    XmlSerializer serializer = new XmlSerializer (typeof(Ship));
    FileStream reader = new FileStream (Path.Combine(Application.dataPath, path), FileMode.Open);
    if (shipObj.LoadShip ((Ship)serializer.Deserialize (reader))) {
        shipObj.gameObject.transform.position = pos;
        reader.Close ();
        //Give all the children rigidbodies, as they are loaded without them
        //by default for when physics are not needed.
        for (int i = 0; i < shipObj.transform.childCount; i++) {
            GameObject child = shipObj.transform.GetChild (i).gameObject;
            Rigidbody2D rb = child.AddComponent<Rigidbody2D> ();
            rb.gravityScale = 0;
            rb.drag = 0;
            rb.angularDrag = 0;
            rb.mass = 0;
            rb.isKinematic = true;
        }
        shipObj.name = shipObj.ship.shipName;
        Debug.LogError ("Ship name = " + shipObj.name);
        ClientScene.RegisterPrefab (shipObj.gameObject, NetworkHash128.Parse (shipObj.name));
        GameObject prefab;
        ClientScene.prefabs.TryGetValue (NetworkHash128.Parse (shipObj.name), out prefab);
        if (!prefab) {
            Debug.LogError ("Prefab not registered!");
            return;
        }
        if (shipObj.GetComponent<NetworkIdentity> () != null) {
            Cmd_SpawnShip (prefab);
        } else {
            Debug.LogError ("No network identity here!");
        }
    }
}

[Command]
public void Cmd_SpawnShip(GameObject ship){
    NetworkServer.Spawn (ship);
}

作为您正在看到的内容的破坏:玩家调用LoadShip(),其中包含所需的生成位置,它加载的船的路径,以及他们想要覆盖的现有船。然后,它使用XML加载所有必要的数据,添加物理并根据船名注册预制件,该名称在所有情况下都应该是唯一的。

主船对象及其所有子对象(如墙壁,枪支,控制台等等)都被赋予NetworkIdentity组件,并且主船也被赋予NetworkTransform组件LoadShip()。

对于任何选择加载它的客户端,该产生的产品都很好,但服务器或其他客户端都无法看到它,而是收到该错误。

我一直试图解决这个问题。也许是过去3个小时。这是漫长的一天,我相信当我说我搜索谷歌和stackoverflow时,我会相信我已经发布的问题答案。其中最常见的问题是:只是不注册预制件,在服务器上注册预制件,忘记给它一个assetID,而不是在客户端/有权限的东西上调用它。我很确定我已经避免了所有这些事情,请不要将我链接到Unity教程。我向你保证,我已经多次读过它们了。

此外,如果我只举办一个只有一个客户的游戏并在船上产卵,那么预制件不会显示在网络管理器的注册预制件下面。列表,即使我已经在网络管理员的调试&#39;日志级别,它告诉我它已成功注册预制件。

关于所有相关信息。我会事先感谢你的时间,希望我所做的任何错误都不会明显地显而易见。

1 个答案:

答案 0 :(得分:0)

努力更多地解决这个问题。经过几个小时的刻意鞭打互联网寻求答案;找到了!我在代码中遇到的两个误解是:

  • RegisterClientPrefab()会自动从GameObject中创建一个预制件以供服务器使用。我不确定为什么我首先想到这一点,事后看来这很明显。
  • 我认为当调用RegisterClientPrefab()时,它所做的就是告诉服务器,'嘿,你。我做了些什么。与大家分享!'但实际上,它只是告诉个人客户在哪里寻找特定的资产。

我解决这些误解的方法是简单地给服务器一个包含每个船的assetID的字典和一个加载它的xml的序列化byte []数组,然后是一个RegisterSpawnHandler,它可以正确地产生对象。我不确定这是最好的方法,如果有任何其他形式的编码通过网络发送比byte []数组更容易/更快,但它适用于我