HTCVIVE---使用Unet制作多人联机(使用位置赋值)

这里使用的方法时制作一个空的Player,使结构和CameraRig主要结构一致,然后实时获取CameraRig的手柄和头盔的位置,然后把Player的位置进行同步,对应的可见模型就添加在Player上面.

首先创建了三个脚本:

InteractionTest是负责具体交互功能同步测试的脚本,挂在Player上(仅交互功能测试使用,对同步VIVE位置信息没有作用)

MappingIVIVETransform是用来获取ViVE组件位置的脚本,挂在Player上

VIVEInstance是一个单例脚本,主要获取VIVE的手柄头盔,挂在CameraRig上。

首先是VIVEInstance脚本:

using UnityEngine;

public class VIVEInstance : MonoBehaviour {

    public static VIVEInstance Instance;
  
    public Transform LeftHand;
    public Transform RightHand;
    public Transform Head;
    private void Awake()
    {
        Instance = this;
    }
}

赋值后的结果,分别赋值接可以了。CameraRig就配置好了,不需要其他操作

然后我们创建一个Player的空物体。结构如下:

首先Player下面添加一个Head我这里使用的是一个Sphere,然后添加空物体LeftHand和空物体RightHand(下面的Model针对特定模型用来显示的,如果LeftHand和RightHand自带模型组件则不需要),Player的结果就是这样,然后添加组件;

如上图。首先是Player的自身同步组件,然后需要添加三个NetWork Transform Child组件,因为我们需要同步头部,左右手三个物体,所以需要添加三个,然后分别拖拽赋值。Player下的子物体不需要特殊操作。

然后添加MappingIVIVETransform脚本,需要继承自NetWorkBehaviour,具体代码如下:

using UnityEngine;
using UnityEngine.Networking;
public class MappingVIVETransform : NetworkBehaviour
{

    public Transform Head;
    public Transform LeftHand;
    public Transform RightHand;
    private void Update()
    {
        Mapping();
    }

    public void Mapping()
    {
        if (isLocalPlayer)
        {
            Head.position = VIVEInstance.Instance.Head.position;
            Head.rotation = VIVEInstance.Instance.Head.rotation;
            LeftHand.position = VIVEInstance.Instance.LeftHand.position;
            LeftHand.rotation = VIVEInstance.Instance.LeftHand.rotation;
            RightHand.position = VIVEInstance.Instance.RightHand.position;
            RightHand.rotation = VIVEInstance.Instance.RightHand.rotation;
        }
       
    }
}

 

在Update里面实时赋值,这里需要判断是不是isLocalPlayer。挂在Player的结构如下:

到了这一步同步其实就已经完成了,测试就可以互相看到彼此。如果卡顿延迟严重记得调节同步组件下的:

具体值按照自身需求来

 

写了一个发射子弹的测试脚本InterationTest。子弹的颜色随机,按下一次单发,按下不松连发:

using UnityEngine;
using UnityEngine.Networking;

public class InteractionTest : NetworkBehaviour
{
    public GameObject Bullet;
    public Transform LuncherPos;
    private float luncherTimer;
    public float IntervalTime;
    private SteamVR_TrackedObject leftTrackerObj;
    private SteamVR_TrackedObject rightTrackerObj;
    private SteamVR_Controller.Device leftDevice;
    private SteamVR_Controller.Device rightDevice;
    public override void OnStartClient()
    {
        leftTrackerObj = GameObject.Find("[CameraRig]/Controller (left)").GetComponent<SteamVR_TrackedObject>();
        rightTrackerObj = GameObject.Find("[CameraRig]/Controller (right)").GetComponent<SteamVR_TrackedObject>();
    }

    void Start()
    {
        if (leftTrackerObj != null)
        {
            leftDevice = SteamVR_Controller.Input((int)leftTrackerObj.index);
        }
        if (rightTrackerObj != null)
        {
            rightDevice = SteamVR_Controller.Input((int)rightTrackerObj.index);
        }
    }

    void FixedUpdate()
    {
        if (isLocalPlayer)
        {
            if (leftDevice != null)
            {
                if (leftDevice.GetPressDown(SteamVR_Controller.ButtonMask.Trigger))
                {
                    CmdSingleLuncher();
                }
                if (leftDevice.GetPress(SteamVR_Controller.ButtonMask.Trigger))
                {
                    ContinuousLuncher();
                }
                if (leftDevice.GetPressUp(SteamVR_Controller.ButtonMask.Trigger))
                {
                    luncherTimer = 0;
                }
            }         
        }      
    }

    [Command]
    public void CmdSingleLuncher()
    {
        RpcSingleLuncher();
    }

    [ClientRpc]
    public void RpcSingleLuncher()
    {
        GameObject go = GameObject.Instantiate(Bullet, LuncherPos.position, Quaternion.identity);
        go.GetComponent<MeshRenderer>().material.color = RandomColor();
        go.GetComponent<Rigidbody>().velocity = LuncherPos.forward * 5f;
        Destroy(go, 2f);
    }

    public void ContinuousLuncher()
    {
        luncherTimer += Time.deltaTime;
        if (luncherTimer >= IntervalTime)
        {
            CmdSingleLuncher();
            luncherTimer = 0;
        }
    }

    private Color RandomColor()
    {
        float r = Random.Range(0, 1f);
        float g = Random.Range(0, 1f);
        float b = Random.Range(0, 1f);
        Color color = new Color(r, g, b);
        return color;
    }
}

 

整体Player结构:

欢迎加群:4364930讨论。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章