在Unet 中 你如果你遇到类似 的问题
Failed to spawn server object, assetId=309e0b989f7cc354e8f1dfb977e657e2 netId=10
UnityEngine.Networking.NetworkIdentity:UNetStaticUpdate()
应该是没有 手动把要添加的物体 添加到 Registered Spawnable Prefabs中
unity 官方API 给出 自定义 生产的方法
The default behaviour of creating spawned objects from prefabs on the client can be customized by using spawn handler functions. This way you have full control of how you spawn the object as well as how you un-spawn it. You can register functions to spawn and un-spawn client objects with ClientScene.RegisterSpawnHandler. The server creates objects directly and then spawn them on the clients though this functionality. This function takes the asset ID of the object and two function delegates, one to handle creating objects on the client and one to handler destroying objects on the client. The asset ID can be a dynamic one or just the asset ID found on the prefab object you want to spawn (if you have one).
The spawn / un-spawner need to have this object signature, this is defined in the high level API.
可以通过使用spawn处理函数来定制在客户端上从prefabs创建spawned对象的默认行为。 这样你可以完全控制你如何产生对象以及如何不产生它。 您可以使用ClientScene.RegisterSpawnHandler注册函数来生成和未生成客户端对象。 服务器直接创建对象,然后通过此功能将它们生成在客户端上。 此函数使用对象的资产ID和两个函数委托,一个用于处理客户端上的创建对象,另一个用于处理客户端上的销毁对象。 资产ID可以是动态的,也可以是您想要生成的预制对象(如果有的话)中找到的资产ID。
spawn / un-spawner需要有这个对象签名,这是在高级API中定义的。
在此之前 生成物体都是 设为预设体 手动拖拽至Registered Spawnable Prefabs;
下面动态注册
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
//为了能让脚本在连上局域网的同时还能分别控制物体,所以要继承 NetworkBehaviour
public class PlayerController : NetworkBehaviour
{
public float traSpeed = 3; //移动的速度
public float rotSpeed = 120; //一秒旋转的角度
public GameObject bulletPre; //子弹的prefab
public Transform bulletTrans; //生成子弹的位置
public NetworkHash128 assetId { get; set; }
void Start()
{
assetId = bulletPre.GetComponent<NetworkIdentity>().assetId;
ClientScene.RegisterSpawnHandler(assetId, SpawnBullet, UnSpawnBullet);
}
public GameObject SpawnBullet(Vector3 position, NetworkHash128 assetId)
{
return (GameObject)Instantiate(bulletPre, position, Quaternion.identity);
}
public void UnSpawnBullet(GameObject spawned)
{
Destroy(spawned);
}
// Update is called once per frame
void Update()
{
// isLocalPlayer 是 NetworkBehaviour 的内置属性
if (!isLocalPlayer) //如果不是本地客户端,就返回,不执行下面的操作
{
return;
}
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
transform.Translate(Vector3.forward * v * traSpeed * Time.deltaTime); //朝某个方向移动
transform.Rotate(Vector3.up * h * rotSpeed * Time.deltaTime); //围绕某轴旋转
if (Input.GetKeyDown(KeyCode.Space))
{
CmdFire();
}
}
//这是重写 NetworkBehaviour 内的方法
//这个方法只会在创建本地角色时调用
public override void OnStartLocalPlayer()
{
GetComponent<MeshRenderer>().material.color = Color.blue;
}
[Command] //在客户端调用,但是在服务端运行,这是方法必须以 Cmd 开头
void CmdFire()
{
GameObject bullet = Instantiate(bulletPre, bulletTrans.position, Quaternion.identity) as GameObject;
bullet.GetComponent<Rigidbody>().velocity = transform.forward * 10;
Destroy(bullet, 2); //2秒后销毁子弹
//NetworkManager.singleton.spawnPrefabs.Add(bullet);
bullet.GetComponent<MeshRenderer>().material.color = Color.blue;
NetworkServer.Spawn(bullet); //在所有客户端都生成一个物体
//StartCoroutine(WaitDeleteButtlet(bullet, 2f));
}
//private IEnumerator WaitDeleteButtlet(GameObject obj, float time)
//{
// yield return new WaitForSeconds(time);
// NetworkManager.singleton.spawnPrefabs.Remove(obj);
//}
}
这样就已经可以运行了 Registered Spawnable Prefabs 代码是 帮你注册 并添加到他们list中
如果想要添加在 Registered Spawnable Prefabs;
NetworkManager.singleton.spawnPrefabs.Add(bullet);
这样就添加上去了