diff --git a/Runtime/HumanoidControl/Scripts/Networking/HumanoidPlayer.cs b/Runtime/HumanoidControl/Scripts/Networking/HumanoidPlayer.cs index 53d14df..f07562e 100644 --- a/Runtime/HumanoidControl/Scripts/Networking/HumanoidPlayer.cs +++ b/Runtime/HumanoidControl/Scripts/Networking/HumanoidPlayer.cs @@ -6,7 +6,7 @@ using UnityEngine; namespace Passer.Humanoid { #pragma warning disable 0618 -#if hNW_UNET || hNW_MIRROR || hNW_PHOTON || hNW_BOLT +#if hNW_UNET || hNW_MIRROR || hNW_PHOTON || hNW_BOLT || hNETCODE public partial class HumanoidPlayer { [SerializeField] diff --git a/Runtime/HumanoidControl/Scripts/Networking/Netcode/HumanoidPlayerNetcode.cs b/Runtime/HumanoidControl/Scripts/Networking/Netcode/HumanoidPlayerNetcode.cs index 3fc61b1..ad34256 100644 --- a/Runtime/HumanoidControl/Scripts/Networking/Netcode/HumanoidPlayerNetcode.cs +++ b/Runtime/HumanoidControl/Scripts/Networking/Netcode/HumanoidPlayerNetcode.cs @@ -1,69 +1,113 @@ +#if hNETCODE using System.Collections.Generic; using UnityEngine; -using UnityEngine.Networking; +using Unity.Netcode; +using Unity.Netcode.Components; namespace Passer.Humanoid { -#if hNW_UNET #pragma warning disable 0618 - [RequireComponent(typeof(NetworkIdentity))] - public partial class HumanoidPlayer : PawnUnet, IHumanoidNetworking { + [RequireComponent(typeof(NetworkObject))] + public partial class HumanoidPlayer : NetworkBehaviour, IHumanoidNetworking { + + // temporary (?) dummies + + public void Send(bool b) { } + public void Send(byte b) { } + public void Send(int x) { } + public void Send(float f) { } + public void Send(Vector3 v) { } + public void Send(Quaternion q) { } + + public bool ReceiveBool() { + return false; + } + public byte ReceiveByte() { + return 0; + } + public int ReceiveInt() { + return 0; + } + public float ReceiveFloat() { + return 0; + } + public Vector3 ReceiveVector3() { + return Vector3.zero; + } + public Quaternion ReceiveQuaternion() { + return Quaternion.identity; + } + // end temporary dummies public ulong nwId { - get { return netId.Value; } + get { return identity.objectIdentity; } } + [SerializeField] + protected float _sendRate = 25; + public float sendRate { + get { return _sendRate; } + } + public HumanoidNetworking.Smoothing smoothing => HumanoidNetworking.Smoothing.None; + + + public bool isLocal { get; set; } + public List humanoids { get; set; } - protected NetworkIdentity identity; + protected NetworkObject identity; public ulong GetObjectIdentity(GameObject obj) { - NetworkIdentity identity = obj.GetComponent(); + NetworkObject identity = obj.GetComponent(); if (identity == null) return 0; - return identity.netId.Value; + return identity.objectIdentity; } public GameObject GetGameObject(ulong objIdentity) { - NetworkInstanceId netId = new NetworkInstanceId((uint)objIdentity); - GameObject gameObject = ClientScene.FindLocalObject(netId); + Unity.Netcode.NetworkObject nwObject = GetNetworkObject(objIdentity); + if (nwObject == null) + return null; + GameObject gameObject = nwObject.gameObject; return gameObject; } - #region Init + float lastSend; - override public void Awake() { - DontDestroyOnLoad(this); - - identity = GetComponent(); - humanoids = new List(); - - lastSend = Time.time; + [SerializeField] + protected bool _createLocalRemotes = false; + public bool createLocalRemotes { + get { return _createLocalRemotes; } + set { _createLocalRemotes = value; } } - public override void OnStartClient() { - name = name + " " + netId; + + #region Init + + public virtual void OnStartClient() { + //name = name + " " + netId; //NetworkManager nwManager = FindObjectOfType(); //short msgType = MsgType.Highest + 2; //nwManager.client.RegisterHandler(msgType, ClientProcessAvatarPose); - if (identity.isServer) { - IHumanoidNetworking[] nwHumanoids = FindObjectsOfType(); - foreach (IHumanoidNetworking nwHumanoid in nwHumanoids) { - foreach (HumanoidControl humanoid in nwHumanoid.humanoids) { - if (humanoid.isRemote) - continue; + // No idea how this works with Netcode + //if (identity.isServer) { + // IHumanoidNetworking[] nwHumanoids = FindObjectsOfType(); + // foreach (IHumanoidNetworking nwHumanoid in nwHumanoids) { + // foreach (HumanoidControl humanoid in nwHumanoid.humanoids) { + // if (humanoid.isRemote) + // continue; - DebugLog("Server Instantiate " + humanoid.nwId + " " + humanoid.humanoidId); - ((IHumanoidNetworking)this).InstantiateHumanoid(humanoid); - } - } - } + // DebugLog("Server Instantiate " + humanoid.nwId + " " + humanoid.humanoidId); + // ((IHumanoidNetworking)this).InstantiateHumanoid(humanoid); + // } + // } + //} } - public override void OnStartServer() { + public virtual void OnStartServer() { //short msgType = MsgType.Highest + 1; //NetworkServer.RegisterHandler(msgType, ForwardAvatarPose); } @@ -72,23 +116,23 @@ namespace Passer.Humanoid { #region Start - public override void OnStartLocalPlayer() { + public virtual void OnStartLocalPlayer() { isLocal = true; name = "HumanoidPlayer(Local)"; humanoids = HumanoidNetworking.FindLocalHumanoids(); - if (debug <= PawnNetworking.DebugLevel.Info) - Debug.Log((int)netId.Value + ": Found " + humanoids.Count + " Humanoids"); + if (debug <= HumanoidNetworking.DebugLevel.Info) + Debug.Log((int)identity.objectIdentity + ": Found " + humanoids.Count + " Humanoids"); for (int i = 0; i < humanoids.Count; i++) { HumanoidControl humanoid = humanoids[i]; if (humanoid.isRemote) continue; - humanoid.nwId = netId.Value; + humanoid.nwId = identity.objectIdentity; humanoid.humanoidNetworking = this; - if (debug <= PawnNetworking.DebugLevel.Info) + if (debug <= HumanoidNetworking.DebugLevel.Info) Debug.Log(humanoid.nwId + ": Send Start Humanoid " + humanoid.humanoidId); ((IHumanoidNetworking)this).InstantiateHumanoid(humanoid); @@ -120,14 +164,14 @@ namespace Passer.Humanoid { } protected virtual void Update() { - if (smoothing == PawnNetworking.Smoothing.Interpolation || - smoothing == PawnNetworking.Smoothing.Extrapolation) { + if (smoothing == HumanoidNetworking.Smoothing.Interpolation || + smoothing == HumanoidNetworking.Smoothing.Extrapolation) { HumanoidNetworking.SmoothUpdate(humanoids); } } - public override void LateUpdate() { + public virtual void LateUpdate() { if (Time.time > lastSend + 1 / sendRate) { foreach (HumanoidControl humanoid in humanoids) { if (!humanoid.isRemote) { @@ -145,8 +189,8 @@ namespace Passer.Humanoid { #region Stop override public void OnDestroy() { - if (debug <= PawnNetworking.DebugLevel.Info) - Debug.Log((int)netId.Value + ": Destroy Remote Humanoid"); + if (debug <= HumanoidNetworking.DebugLevel.Info) + Debug.Log((int)identity.objectIdentity + ": Destroy Remote Humanoid"); foreach (HumanoidControl humanoid in humanoids) { if (humanoid == null) @@ -160,74 +204,77 @@ namespace Passer.Humanoid { humanoid.nwId = 0; } } - #endregion - protected virtual void SendToServer(NetworkIdentity identity, HumanoidNetworking.IMessage msg) { - byte[] data = msg.Serialize(); + #endregion Stop - short msgType = MsgType.Highest + 1; - writer = new NetworkWriter(); - writer.StartMessage(msgType); - writer.WriteBytesAndSize(data, data.Length); - writer.FinishMessage(); - identity.connectionToServer.SendWriter(writer, Channels.DefaultUnreliable); - } + //protected virtual void SendToServer(NetworkObject identity, HumanoidNetworking.IMessage msg) { + // byte[] data = msg.Serialize(); - protected virtual void SendToClients(byte[] data) { - short msgType = MsgType.Highest + 2; - NetworkWriter sWriter = new NetworkWriter(); + // short msgType = MsgType.Highest + 1; + // writer = new NetworkWriter(); + // writer.StartMessage(msgType); + // writer.WriteBytesAndSize(data, data.Length); + // writer.FinishMessage(); + // identity.connectionToServer.SendWriter(writer, Channels.DefaultUnreliable); + //} - sWriter.StartMessage(msgType); - sWriter.WriteBytesAndSize(data, data.Length); - sWriter.FinishMessage(); + //protected virtual void SendToClients(byte[] data) { + // short msgType = MsgType.Highest + 2; + // NetworkWriter sWriter = new NetworkWriter(); - NetworkServer.SendWriterToReady(null, sWriter, Channels.DefaultUnreliable); - } + // sWriter.StartMessage(msgType); + // sWriter.WriteBytesAndSize(data, data.Length); + // sWriter.FinishMessage(); + + // NetworkServer.SendWriterToReady(null, sWriter, Channels.DefaultUnreliable); + //} #region Instantiate Humanoid void IHumanoidNetworking.InstantiateHumanoid(HumanoidControl humanoid) { - if (debug <= PawnNetworking.DebugLevel.Info) - DebugLog("Instantiate Humanoid " + humanoid.nwId + "/" + humanoid.humanoidId); + if (debug <= HumanoidNetworking.DebugLevel.Info) + DebugLog("Send Instantiate Humanoid " + humanoid.humanoidId); HumanoidNetworking.InstantiateHumanoid instantiateHumanoid = new HumanoidNetworking.InstantiateHumanoid(humanoid); - byte[] data = instantiateHumanoid.Serialize(); + if (createLocalRemotes) + this.Receive(instantiateHumanoid); - CmdForwardInstantiateHumanoid(data); + byte[] data = instantiateHumanoid.Serialize(); + ForwardInstantiateHumanoidRpc(data); } protected HumanoidNetworking.InstantiateHumanoid instantiatedHumanoid; - [Command] // @ server - protected virtual void CmdForwardInstantiateHumanoid(byte[] data) { - + [Rpc(SendTo.Server)] // @ server + protected virtual void ForwardInstantiateHumanoidRpc(byte[] data) { instantiatedHumanoid = new HumanoidNetworking.InstantiateHumanoid(data); - HumanoidPlayer[] nwHumanoids = FindObjectsOfType(); + HumanoidPlayer[] nwHumanoids = UnityEngine.Object.FindObjectsOfType(); foreach (HumanoidPlayer nwHumanoid in nwHumanoids) nwHumanoid.ServerSendInstantiateHumanoid(); } protected virtual void ServerSendInstantiateHumanoid() { - if (debug <= PawnNetworking.DebugLevel.Info) { + if (debug <= HumanoidNetworking.DebugLevel.Info) { DebugLog("Server Send InstantiateHumanoid: " + instantiatedHumanoid.nwId + "/" + instantiatedHumanoid.humanoidId); } byte[] data = instantiatedHumanoid.Serialize(); - RpcReceiveInitiateHumanoid(data); + ReceiveInitiateHumanoidRpc(data); } - [ClientRpc] // @ remote client - protected virtual void RpcReceiveInitiateHumanoid(byte[] data) { + [Rpc(SendTo.NotServer)] // @ remote client + protected virtual void ReceiveInitiateHumanoidRpc(byte[] data) { HumanoidNetworking.InstantiateHumanoid instantiateHumanoid = new HumanoidNetworking.InstantiateHumanoid(data); - - if (debug <= PawnNetworking.DebugLevel.Info) + if (debug <= HumanoidNetworking.DebugLevel.Info) DebugLog("Received Instantiate Humanoid " + instantiateHumanoid.nwId + "/" + instantiateHumanoid.humanoidId); - if (instantiateHumanoid.nwId != identity.netId.Value) { + if (instantiateHumanoid.nwId != identity.objectIdentity) { // Get the right HumanoidPlayer for this humanoid - NetworkInstanceId netId = new NetworkInstanceId((uint)instantiateHumanoid.nwId); - GameObject gameObject = ClientScene.FindLocalObject(netId); + //NetworkInstanceId netId = new NetworkInstanceId((uint)instantiateHumanoid.nwId); + //GameObject gameObject = ClientScene.FindLocalObject(netId); + Unity.Netcode.NetworkObject nwObject = GetNetworkObject(instantiatedHumanoid.nwId); + GameObject gameObject = nwObject.gameObject; HumanoidPlayer humanoidPlayer = gameObject.GetComponent(); if (humanoidPlayer != null) humanoidPlayer.ReceiveInstantiate(data); @@ -238,7 +285,7 @@ namespace Passer.Humanoid { this.ReceiveInstantiate(data); } - #endregion + #endregion Instantiate Humanoid #region Destroy Humanoid @@ -246,56 +293,59 @@ namespace Passer.Humanoid { if (humanoid == null) return; - if (debug <= PawnNetworking.DebugLevel.Info) + if (debug <= HumanoidNetworking.DebugLevel.Info) DebugLog("Destroy Humanoid " + humanoid.humanoidId); HumanoidNetworking.DestroyHumanoid destroyHumanoid = new HumanoidNetworking.DestroyHumanoid(humanoid); byte[] data = destroyHumanoid.Serialize(); - CmdForwardDestroyHumanoid(data); + ForwardDestroyHumanoidRpc(data); } - [Command] // @ server - private void CmdForwardDestroyHumanoid(byte[] data) { - if (debug <= PawnNetworking.DebugLevel.Debug) + [Rpc(SendTo.Server)] // @ server + private void ForwardDestroyHumanoidRpc(byte[] data) { + if (debug <= HumanoidNetworking.DebugLevel.Debug) DebugLog("Forward DestroyHumanoid"); - RpcReceiveDestroyHumanoid(data); + ReceiveDestroyHumanoidRpc(data); } - [ClientRpc] - private void RpcReceiveDestroyHumanoid(byte[] data) { + [Rpc(SendTo.NotServer)] + private void ReceiveDestroyHumanoidRpc(byte[] data) { this.ReceiveDestroy(data); } - #endregion + #endregion Destroy Humanoid #region Pose public HumanoidNetworking.HumanoidPose lastHumanoidPose { get; set; } public void UpdateHumanoidPose(HumanoidControl humanoid) { + if (debug <= HumanoidNetworking.DebugLevel.Debug) + DebugLog("Send Pose Humanoid " + humanoid.humanoidId + " nwId: " + humanoid.nwId); + HumanoidNetworking.HumanoidPose humanoidPose = new HumanoidNetworking.HumanoidPose(humanoid, Time.time, syncFingerSwing, syncFace); - if (debug <= PawnNetworking.DebugLevel.Debug) - DebugLog("Send Humanoid Pose " + humanoid.nwId + "/" + humanoid.humanoidId); + if (createLocalRemotes) + this.Receive(humanoidPose); byte[] data = humanoidPose.Serialize(); - CmdForwardHumanoidPose(data); + ForwardHumanoidPoseRpc(data); } - [Command] - protected virtual void CmdForwardHumanoidPose(byte[] data) { - if (debug <= PawnNetworking.DebugLevel.Debug) { + [Rpc(SendTo.Server)] + protected virtual void ForwardHumanoidPoseRpc(byte[] data) { + if (debug <= HumanoidNetworking.DebugLevel.Debug) { HumanoidNetworking.HumanoidPose humanoidPose = new HumanoidNetworking.HumanoidPose(data); DebugLog("Forward HumanoidPose " + humanoidPose.nwId + "/" + humanoidPose.humanoidId); } - RpcReceiveHumanoidPose(data); + ReceiveHumanoidPoseRpc(data); } - [ClientRpc] - protected virtual void RpcReceiveHumanoidPose(byte[] data) { + [Rpc(SendTo.NotServer)] + protected virtual void ReceiveHumanoidPoseRpc(byte[] data) { this.ReceiveHumanoidPose(data); } @@ -304,28 +354,28 @@ namespace Passer.Humanoid { #region Grab void IHumanoidNetworking.Grab(HandTarget handTarget, GameObject obj, bool rangeCheck, HandTarget.GrabType grabType) { - if (debug <= PawnNetworking.DebugLevel.Info) + if (debug <= HumanoidNetworking.DebugLevel.Info) Debug.Log(handTarget.humanoid.nwId + ": Grab " + obj); ulong objIdentity = GetObjectIdentity(obj); if (objIdentity == 0) { - if (debug <= PawnNetworking.DebugLevel.Error) + if (debug <= HumanoidNetworking.DebugLevel.Error) Debug.LogError("Grabbed object " + obj + " does not have a network identity"); return; } HumanoidNetworking.Grab grab = new HumanoidNetworking.Grab(handTarget, objIdentity, rangeCheck, grabType); byte[] data = grab.Serialize(); - CmdForwardGrab(data); + ForwardGrabRpc(data); } - [Command] - protected virtual void CmdForwardGrab(byte[] data) { - RpcReceiveGrab(data); + [Rpc(SendTo.Server)] + protected virtual void ForwardGrabRpc(byte[] data) { + ReceiveGrabRpc(data); } - [ClientRpc] - protected virtual void RpcReceiveGrab(byte[] data) { + [Rpc(SendTo.NotServer)] + protected virtual void ReceiveGrabRpc(byte[] data) { this.ReceiveGrab(data); } @@ -334,21 +384,21 @@ namespace Passer.Humanoid { #region Let Go void IHumanoidNetworking.LetGo(HandTarget handTarget) { - if (debug <= PawnNetworking.DebugLevel.Info) + if (debug <= HumanoidNetworking.DebugLevel.Info) DebugLog("LetGo"); HumanoidNetworking.LetGo letGo = new HumanoidNetworking.LetGo(handTarget); byte[] data = letGo.Serialize(); - CmdForwardLetGo(data); + ForwardLetGoRpc(data); } - [Command] - protected virtual void CmdForwardLetGo(byte[] data) { - RpcReceiveLetGo(data); + [Rpc(SendTo.Server)] + protected virtual void ForwardLetGoRpc(byte[] data) { + ReceiveLetGoRpc(data); } - [ClientRpc] - protected virtual void RpcReceiveLetGo(byte[] data) { + [Rpc(SendTo.NotServer)] + protected virtual void ReceiveLetGoRpc(byte[] data) { this.ReceiveLetGo(data); } @@ -356,22 +406,22 @@ namespace Passer.Humanoid { #region ChangeAvatar - void IHumanoidNetworking.ChangeAvatar(HumanoidControl humanoid, string avatarPrefabName) { - if (debug <= PawnNetworking.DebugLevel.Info) + void IHumanoidNetworking.ChangeAvatar(HumanoidControl humanoid, string avatarPrefabName, string possessionLocation) { + if (debug <= HumanoidNetworking.DebugLevel.Info) DebugLog("Change Avatar: " + avatarPrefabName); - HumanoidNetworking.ChangeAvatar changeAvatar = new HumanoidNetworking.ChangeAvatar(humanoid, avatarPrefabName); + HumanoidNetworking.ChangeAvatar changeAvatar = new HumanoidNetworking.ChangeAvatar(humanoid, avatarPrefabName, possessionLocation); byte[] data = changeAvatar.Serialize(); - CmdForwardChangeAvatar(data); + ForwardChangeAvatarRpc(data); } - [Command] - protected virtual void CmdForwardChangeAvatar(byte[] data) { - RpcReceiveChangeAvatar(data); + [Rpc(SendTo.Server)] + protected virtual void ForwardChangeAvatarRpc(byte[] data) { + ReceiveChangeAvatarRpc(data); } - [ClientRpc] - protected virtual void RpcReceiveChangeAvatar(byte[] data) { + [Rpc(SendTo.NotServer)] + protected virtual void ReceiveChangeAvatarRpc(byte[] data) { this.ReceiveChangeAvatar(data); } @@ -386,16 +436,16 @@ namespace Passer.Humanoid { HumanoidNetworking.SyncTrackingSpace syncTracking = new HumanoidNetworking.SyncTrackingSpace(humanoid, trackingTransform.position, trackingTransform.rotation); byte[] data = syncTracking.Serialize(); - CmdForwardSyncTracking(data); + ForwardSyncTrackingRpc(data); } - [Command] - protected virtual void CmdForwardSyncTracking(byte[] data) { - RpcReceiveSyncTracking(data); + [Rpc(SendTo.Server)] + protected virtual void ForwardSyncTrackingRpc(byte[] data) { + ReceiveSyncTrackingRpc(data); } - [ClientRpc] - protected virtual void RpcReceiveSyncTracking(byte[] data) { + [Rpc(SendTo.NotServer)] + protected virtual void ReceiveSyncTrackingRpc(byte[] data) { this.ReceiveSyncTrackingSpace(data); } @@ -425,7 +475,7 @@ namespace Passer.Humanoid { } } - #endregion + #endregion Network Sync #region Network Object @@ -447,38 +497,38 @@ namespace Passer.Humanoid { #region Void Event - public void RPC(FunctionCall functionCall) { - CmdRPCVoid(functionCall.targetGameObject, functionCall.methodName); - } + //public void RPC(FunctionCall functionCall) { + // RPCVoidServerRpc(functionCall.targetGameObject, functionCall.methodName); + //} - [Command] // @ server - public void CmdRPCVoid(GameObject target, string methodName) { - RpcRPCVoid(target, methodName); - } + //[Rpc(SendTo.Server)] // @ server + //public void RPCVoidServerRpc(GameObject target, string methodName) { + // RPCVoidRpc(target, methodName); + //} - [ClientRpc] // @ remote client - public void RpcRPCVoid(GameObject targetGameObject, string methodName) { - Debug.Log("RPC: " + methodName); - FunctionCall.Execute(targetGameObject, methodName); - } + //[Rpc(SendTo.NotServer)] // @ remote client + //public void RPCVoidRpc(GameObject targetGameObject, string methodName) { + // Debug.Log("RPC: " + methodName); + // FunctionCall.Execute(targetGameObject, methodName); + //} #endregion #region Bool Event - public void RPC(FunctionCall functionCall, bool value) { - CmdRPCBool(functionCall.targetGameObject, functionCall.methodName, value); - } + //public void RPC(FunctionCall functionCall, bool value) { + // RPCBoolServerRpc(functionCall.targetGameObject, functionCall.methodName, value); + //} - [Command] // @ server - public void CmdRPCBool(GameObject target, string methodName, bool value) { - RpcRPCBool(target, methodName, value); - } + //[Rpc(SendTo.Server)] // @ server + //public void RPCBoolServerRpc(GameObject target, string methodName, bool value) { + // RPCBoolRpc(target, methodName, value); + //} - [ClientRpc] // @ remote client - public void RpcRPCBool(GameObject target, string methodName, bool value) { - FunctionCall.Execute(target, methodName, value); - } + //[Rpc(SendTo.NotServer)] // @ remote client + //public void RPCBoolRpc(GameObject target, string methodName, bool value) { + // FunctionCall.Execute(target, methodName, value); + //} #endregion @@ -504,20 +554,21 @@ namespace Passer.Humanoid { //} #endregion - #endregion + + #endregion Network Object #region Debug - public void DebugLog(string s) { - Debug.Log(netId + ": " + s); + public void DebugLog(string message) { + Debug.Log(identity.objectIdentity + ": " + message); } - public void DebugWarning(string s) { - Debug.LogWarning(netId + ": " + s); + public void DebugWarning(string message) { + Debug.LogWarning(identity.objectIdentity + ": " + message); } - public void DebugError(string s) { - Debug.LogError(netId + ": " + s); + public void DebugError(string message) { + Debug.LogError(identity.objectIdentity + ": " + message); } #endregion @@ -525,4 +576,4 @@ namespace Passer.Humanoid { #pragma warning restore 0618 } #endif - } \ No newline at end of file +} \ No newline at end of file diff --git a/Runtime/PasserVR.HumanoidControl.asmdef b/Runtime/PasserVR.HumanoidControl.asmdef index 5c491e9..d58b9c9 100644 --- a/Runtime/PasserVR.HumanoidControl.asmdef +++ b/Runtime/PasserVR.HumanoidControl.asmdef @@ -1,5 +1,6 @@ { "name": "PasserVR.HumanoidControl", + "rootNamespace": "", "references": [ "UnityEditor.SpatialTracking", "UnityEngine.SpatialTracking", @@ -11,9 +12,11 @@ "PhotonVoice.API", "LeapMotion", "LeapMotion.LeapCSharp", - "Ultraleap.Tracking.Core", + "Ultraleap.Tracking.Core", "SteamVR", - "Unity.XR.OpenVR" + "Unity.XR.OpenVR", + "Unity.Netcode.Runtime", + "Unity.Netcode.Components" ], "includePlatforms": [], "excludePlatforms": [],