HTC_VR_Unity_Unet多人協同問題記錄以及解決
HTC_VR_Unity_Unet多人協同
因為要做HTC協同的專案,一開始選定了使用UNET完成協同部分操作,後來Unet碰到了很多坑,在這裡記一下:
解決了場景跳轉報錯問題
解決了多個HTC預製衝突問題
///網路管理指令碼
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;
///
/// 將NetworkManager方法按這裡的方式重寫
/// 因為我只用到了這些方法所以只重寫這一小部分
/// 具體原因不清楚
///
public class VR_NetWorkeManager : NetworkManager
{
public Transform thePlayersParent; public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) { // base.OnServerAddPlayer(conn, playerControllerId); var player = (GameObject)GameObject.Instantiate(playerPrefab, startPositions[0].position, Quaternion.identity); player.transform.parent = thePlayersParent; NetworkServer.AddPlayerForConnection(conn, player, playerControllerId); //NetworkServer.SendByChannelToAll(); } public override void OnClientSceneChanged(NetworkConnection conn) { Debug.Log(456); ClientScene.AddPlayer(conn, 0); //base.OnClientSceneChanged(conn); //ClientScene.Ready(conn); } public override void OnClientConnect(NetworkConnection conn) { base.OnClientConnect(conn); } public override void OnServerSceneChanged(string sceneName) { Debug.Log(sceneName); //base.OnServerSceneChanged(sceneName); }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using Valve.VR;
using Assets.Scripts.VR_GameTools;
using Valve.VR.InteractionSystem;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityEngine.Video;
using DG.Tweening;
///
/// 必須掛在NetWorkeManager生成的Play上
/// 需要一個VR_RayPrefab射線的預製體,最好掛上網路標識NetWorkeIdentity
/// 需要給VR_CaiDan,VR_Tra賦值VR_Hand_Axis暫時沒用上
///
public class VR_MyPlayer : NetworkBehaviour
{
#region 頭盔相關引數
//頭盔相關引數==
GameObject VR_Hand1;//手柄1
GameObject VR_Hand2;//手柄2
public SteamVR_Input_Sources VR_LeftHand;
public SteamVR_Input_Sources VR_RightHand;
public SteamVR_Action_Boolean VR_CaiDan;
public SteamVR_Action_Boolean VR_Tra;
public SteamVR_Action_Vector2 VR_Hand_Axis;
public GameObject VR_RayPrefab;
#endregion
#region 網路物體
#endregion
#region 本地客戶端獲取的物體
#endregion
#region 生命週期
void Start()
{
if (!isLocalPlayer)
{
//不是本地客戶端執行什麼
//這裡在跳轉場景時會碰到問題
//原因是有多個客戶端的預製體
//各客戶端相機顯示的是同一個相機,HTC位置連結的是所有預製體所以在這裡會出現問題
//解決辦法:在不是本地客戶端的是隱藏除了要顯示的身體模型外的所有元件
//如果需要同步手柄位置,人物動作,可以再寫一個沒有相機,以及HTC同步的位置的模型,用網路連線的方式同步,PS這裡沒寫所以沒有相關程式碼
return;
}
//本地客戶端執行什麼
}
void Update()
{
if (!isLocalPlayer)
{
return;
}
#region hand1扳機事件
VR_Hand1 = GameTools.FindChild(transform, "Hand1").gameObject;
if (VR_Tra.GetStateDown(VR_LeftHand))
{
Ray ray1 = new Ray(VR_Hand1.transform.position, VR_Hand1.transform.forward);
RaycastHit hitinfo;
if (Physics.Raycast(ray1, out hitinfo))
{
}
}
if (VR_Tra.GetState(VR_LeftHand))
{
Ray ray1 = new Ray(VR_Hand1.transform.position, VR_Hand1.transform.forward);
RaycastHit hitinfo;
if (Physics.Raycast(ray1, out hitinfo))
{
}
}
if (VR_Tra.GetStateUp(VR_LeftHand))
{
MovePlayerId = int.Parse((GetComponent<NetworkIdentity>().netId.ToString()));
Ray ray1 = new Ray(VR_Hand1.transform.position, VR_Hand1.transform.forward);
RaycastHit hitinfo;
if (Physics.Raycast(ray1, out hitinfo))
{
// 點選執行的方法
TriggerEvent(hitinfo.transform.name,hitinfo.transform.gameObject);
}
}
#endregion
#region 扳機2事件
VR_Hand2 = GameTools.FindChild(transform, "Hand2").gameObject;
//Debug.DrawRay(ray.origin, ray.direction, Color.red);
if (VR_Tra.GetStateDown(VR_RightHand))
{
Ray ray1 = new Ray(VR_Hand2.transform.position, VR_Hand2.transform.forward);
RaycastHit hitinfo;
if (Physics.Raycast(ray1, out hitinfo))
{
}
}
if (VR_Tra.GetState(VR_RightHand))
{
Ray ray1 = new Ray(VR_Hand2.transform.position, VR_Hand2.transform.forward);
RaycastHit hitinfo;
if (Physics.Raycast(ray1, out hitinfo))
{
}
}
if (VR_Tra.GetStateUp(VR_RightHand))
{
MovePlayerId = int.Parse((GetComponent<NetworkIdentity>().netId.ToString()));
Debug.Log("手柄2名稱:" + VR_Hand2.gameObject.name);
Ray ray = new Ray(VR_Hand2.transform.position, VR_Hand2.transform.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{ // 點選執行的方法
Debug.Log("手柄2名稱:" + VR_Hand2.gameObject.name);
TriggerEvent(hit.transform.name,hit.transform.gameObject);
}
}
#endregion
///點選選單跳轉場景
if (VR_CaiDan.GetStateDown(VR_LeftHand)|| VR_CaiDan.GetStateDown(VR_RightHand))
{
//name要跳轉的場景
CmdLoadSceneAsync(name);
}
}
#endregion
#region 本地方法
/// <summary>
/// 畫一條射線
/// </summary>
/// <param name="hand22"></param>
void CreatRay(GameObject hand22)
{
Vector3 pos = new Vector3(0.002f, -0.004f, 1.001f);
Vector3 scale = new Vector3(0.001f, 0.001f, 100.0f);
Vector3 rot = new Vector3(0, 0, 0);
GameObject _Ray = Instantiate(VR_RayPrefab) as GameObject;
_Ray.transform.SetParent(hand22.transform);
_Ray.transform.localScale = new Vector3(0.002f, 0.002f, 100f);
_Ray.transform.localPosition = Vector3.zero + new Vector3(0f, 0f, 50f);
_Ray.transform.localRotation = Quaternion.identity;
//NetworkServer.Spawn(_Ray);
}
/// <summary>
/// 手柄點選觸發方法
/// 根據名字判斷執行什麼方法
/// </summary>
/// <param name="name">名字</param>
/// <param name="hit">碰撞點</param>
void TriggerEvent(string name,GameObject hit)
{
Debug.Log("手柄2名稱:" + name);
switch (name)
{
case "Magnify":
CmdScale(0.1f);
break;
}
}
#endregion
#region
/// <summary>
/// 這裡是客戶端發給伺服器
/// </summary>
/// <param name="dam">傳輸的數值,支援float,int ,string,Vector3等數值但是不支援GameObject等型別</param>
[Command]
void CmdScale(float dam)
{
RpcScale(dam);
}
///
/// 點選後觸發什麼功能寫在RPC裡面
/// 這裡是伺服器分發給客戶端執行
///
/// 傳輸的數值,支援float,int ,string,Vector3等數值但是不支援GameObject等型別
[ClientRpc]
void RpcScale(float dam)
{
}
#endregion
}