forked from microsoft/MixedRealityCompanionKit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSharingManager.cs
More file actions
226 lines (187 loc) · 8.29 KB
/
Copy pathSharingManager.cs
File metadata and controls
226 lines (187 loc) · 8.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
namespace SimpleSharing
{
public class SharingManager : SimpleSharing.Singleton<SharingManager>
{
// Use a different port than your anchor and SV Pose data is being sent on.
public int Port = 11024;
// In this simple example of sharing, traffic is routed through Unity running on the local PC.
// We are not using UDP multicast because some network configurations actively block that.
// For a more robust networking stack, consider using UNET's HLAPI. Mixed Reality 250 demonstrates how to do this:
// https://docs.microsoft.com/en-us/windows/mixed-reality/mixed-reality-250
[Header("IP of the local PC running this instance of Unity.")]
public string ServerIP;
public string AnchorName { get; private set; }
public string AnchorIP { get; private set; }
int channelId;
int socketId = -1;
int connectionId;
HostTopology topology;
bool connected = false;
// Use a single NetworkData class for the pose data on each remote machine, so we do not need to recreate a new one each frame.
// We are recycling this on the server to receive all data, since we get data in a sequence.
NetworkData networkPoseData = new NetworkData();
void Start()
{
AnchorName = string.Empty;
NetworkTransport.Init();
ConnectionConfig config = new ConnectionConfig();
channelId = config.AddChannel(QosType.UnreliableSequenced);
int maxConnections = 10;
topology = new HostTopology(config, maxConnections);
if (ServerIP != string.Empty)
{
connected = Connect();
}
}
private void OnDestroy()
{
byte error;
#if WINDOWS_UWP
NetworkTransport.Disconnect(socketId, connectionId, out error);
#endif
#if UNITY_EDITOR
NetworkTransport.DisconnectNetworkHost(socketId, out error);
#endif
}
public bool Connect()
{
Debug.Log(String.Format("Connecting to {0} on port {1}", ServerIP, Port));
if (socketId == -1)
{
socketId = NetworkTransport.AddHost(topology, Port);
}
byte error;
connectionId = NetworkTransport.Connect(socketId, ServerIP, Port, 0, out error);
if (error != (byte)NetworkError.Ok)
{
Debug.Log("Failed to connect.");
return false;
}
Debug.Log("Connected to server. ConnectionId: " + connectionId);
return true;
}
private void ReceiveMessage()
{
int recHostId;
int recConnectionId;
int recChannelId;
const int bufferSize = 1024;
byte[] recBuffer = new byte[bufferSize];
int dataSize;
byte error;
NetworkEventType recNetworkEvent = NetworkTransport.Receive(
out recHostId, out recConnectionId, out recChannelId,
recBuffer, bufferSize, out dataSize, out error);
switch (recNetworkEvent)
{
case NetworkEventType.ConnectEvent:
Debug.Log("Connection Event Received.");
break;
case NetworkEventType.DataEvent:
// Find the type of message we have received, and deserialize network data to properties in teh NetworkData class.
NetworkData.MessageType type = networkPoseData.DeserializeData(recBuffer, dataSize);
switch (type)
{
case NetworkData.MessageType.Pose:
if (RemotePlayerManager.Instance != null)
{
RemotePlayerManager.Instance.UpdateRemotePlayer(recConnectionId, networkPoseData.Position, networkPoseData.Rotation);
}
break;
case NetworkData.MessageType.AirTap:
if (RemotePlayerManager.Instance != null)
{
RemotePlayerManager.Instance.PerformRemoteAirTap(recConnectionId, networkPoseData.AirTapLocation, networkPoseData.AirTapDirection, networkPoseData.AirTapHitLocation);
}
break;
case NetworkData.MessageType.AnchorName:
AnchorName = networkPoseData.AnchorName;
AnchorIP = networkPoseData.AnchorIP;
break;
};
break;
case NetworkEventType.DisconnectEvent:
if (RemotePlayerManager.Instance != null)
{
// Remove the remote player from our game state.
RemotePlayerManager.Instance.RemoveRemotePlayer(recConnectionId);
}
#if WINDOWS_UWP
// Server has disconnected, queue another connection request.
connected = Connect();
#endif
break;
}
}
void Update()
{
if (!connected && ServerIP != string.Empty)
{
connected = Connect();
}
ReceiveMessage();
}
#region Send Client Data to Server
private Vector3 GetVectorInAnchorSpace(Vector3 input)
{
// Get position relative to the shared anchor's rotation if available.
if (AnchorManager.Instance != null && AnchorManager.Instance.objectToAnchor != null)
{
return AnchorManager.Instance.objectToAnchor.transform.InverseTransformPoint(input);
}
// Otherwise get position relative to this gameObject, which shares a transform to the AnchorManager.
return transform.InverseTransformPoint(input);
}
private Quaternion GetQuaternionInAnchorSpace(Quaternion input)
{
// Get rotation relative to the shared anchor's rotation if available.
if (AnchorManager.Instance != null && AnchorManager.Instance.objectToAnchor != null)
{
return Quaternion.Inverse(AnchorManager.Instance.objectToAnchor.transform.rotation) * input;
}
// Otherwise get rotation relative to this gameObject, which shares a transform to the AnchorManager.
return Quaternion.Inverse(transform.rotation) * input;
}
public void SendPose()
{
networkPoseData.SerializePose(
GetVectorInAnchorSpace(Camera.main.transform.position),
GetQuaternionInAnchorSpace(Camera.main.transform.rotation));
SendMessage(networkPoseData);
}
public void SendAirTap(Vector3 position, Vector3 rotation, Vector3 hitLocation)
{
// Use a different NetworkData instance so we do not overwrite our pose data.
NetworkData networkData = new NetworkData();
networkData.SerializeAirTap(
GetVectorInAnchorSpace(position),
GetVectorInAnchorSpace(rotation),
GetVectorInAnchorSpace(hitLocation));
SendMessage(networkData);
}
public void SendAnchorName(String anchorName, String anchorOwnerIP)
{
// Use a different NetworkData instance so we do not overwrite our pose data.
NetworkData networkData = new NetworkData();
networkData.SerializeAnchorName(anchorName, anchorOwnerIP);
SendMessage(networkData);
}
private void SendMessage(NetworkData networkData)
{
byte error;
NetworkTransport.Send(socketId, connectionId, channelId, networkData.buffer, NetworkData.bufSize, out error);
if (error != (byte)NetworkError.Ok)
{
Debug.Log("Error sending network message.");
}
}
#endregion
}
}