之前更换模型功能有一些缺陷,只能在本地看到,而网络其他用户看不到这个玩家换模型。
实现这个功能不能简单的用Network.Instantiate方法,因为此方法要求所使用创建的Prefab必须先存在工程中,也就是说必须更换的模型资源随着初始包预先加载才可以用这个方法同步创建出对象。 而通常换模型需要临时下载新的模型资源,而如果其他用户还没有下载这个资源,就肯定不能用它创建出对象。
所以这里用了RPC通知各个客户端和服务器,需要创建出模型的一些信息,让它们在本地下载这个资源,并在场景创建出来。
这个RPC实现如下:
01.
02.function ReplacePlayer(spawnPos:Vector3,spawnRotation:Quaternion,suitName:String,networkViewID0:NetworkViewID, networkViewID1:NetworkViewID)
03.{
04. var go =Instantiate(GetDownloadPrefab(suitName),spawnPos,spawnRotation) as GameObject;
05. nvs = go.GetComponents(NetworkView);
06. nvs[0].viewID = networkViewID0;
07. nvs[1].viewID = networkViewID1;
08.
09. if(networkViewID0.isMine)
10. {
11. selfPlayer = go.transform;
12. ResetCameraTarget(selfPlayer);
13. }
14.
15.}
这里通知的信息包含了,创建出模型的位置、朝向、模型的名称、以及两个NetworkViewID.这里有2个NetworkViewID是因为人物身上有两个NetworkView组件用来同步数据,一个是同步人物的transform信息,另一个用于同步人物的Animation信息,在创建新模型后需要分别恢复这两个组件的NetworkViewID。另外RPC参数中无法使用数组类型,所以只能分开来写。
GetDownloadPrefab就是用于获得下载的资源。
下载后在本地用Instantiate创建出新的人物模型对象,然后恢复之前的NetworkViewID,这样保证网络模块不会受到影响。
之后如果检查是自己的客户端,就重设selfPlayer到这个新创建的对象,并且重设摄像机的追踪目标等。
调用这个函数,代码如下:
01.var suitName;
02. if(currentSuit==1)
03. {
04. currentSuit = 0;
05. suitName = "PlayerPrefab0";
06. }
07. else
08. {
09. currentSuit = 1;
10. suitName = "PlayerPrefab1";
11. }
12.
13.
14. nvs = selfPlayer.gameObject.GetComponents(NetworkView);
15. var viewIDs = new NetworkViewID[2];
16. viewIDs[0] = (nvs[0] as NetworkView).viewID;
17. viewIDs[1] = (nvs[1] as NetworkView).viewID;
18.
19. var pos = selfPlayer.position;
20. var rot = selfPlayer.rotation;
21. Network.Destroy(selfPlayer.gameObject);
22. networkView.RPC("ReplacePlayer",RPCMode.AllBuffered,pos,rot, suitName,viewIDs[0],viewIDs[1]);
这里先获取到所需下载模型的名称suitName
然后保留原来人物的两个NetworkView组件的NetworkViewID,这里获取同一种组件的多个对象使用了GetComponents方法,这个方法返回的是指定类型的Component数组。
再保存下人物的位置、朝向等信息后,销毁之前的人物模型。
最后用保留下的信息,调用刚才指定的RPC函数。
欢迎到论坛参与提问与讨论!~