added Multipeer Connectivity Transport (#203)

* added Multipeer Connectivity Transport

* added Multipeer Connectivity transport to the README file

* removed Multipeer Connectivity transport package dependency
This commit is contained in:
yuchen 2023-02-14 23:34:52 +08:00 коммит произвёл GitHub
Родитель 858f6df327
Коммит 2a5a082ba7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
22 изменённых файлов: 864 добавлений и 0 удалений

Просмотреть файл

@ -30,6 +30,7 @@ Check our [contribution guidelines](CONTRIBUTING.md) for information on how to c
|**[WebSocket](/Transports/com.community.netcode.transport.websocket)**| Desktop, Mobile, WebGL | :heavy_check_mark: | :heavy_check_mark:||
|**[Photon Realtime](/Transports/com.community.netcode.transport.photon-realtime)**| Desktop, Mobile, WebGL\** | :heavy_check_mark: | :heavy_check_mark: | |
|**[Facepunch](/Transports/com.community.netcode.transport.facepunch)**| Steam | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|**[Multipeer Connectivity](/Transports/com.community.netcode.transport.multipeer-connectivity)**| iOS | :heavy_check_mark: | :heavy_check_mark: | |
\* Needs manual binary compilation.<br>
\** Other platforms such as console platforms are also supported but require communication with Exit Games.

Просмотреть файл

@ -0,0 +1,5 @@
Changelog
All notable changes to this package will be documented in this file. The format is based on Keep a Changelog
## 0.0.1
This is the first release of Multipeer Connectivity Transport Package.

Просмотреть файл

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c9e5a22959fc54a34a1a39a42095c856
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ad739c1238fea4787bfaf7fcc2aa5fb1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,44 @@
using System.IO;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
namespace Netcode.Transports.MultipeerConnectivity.Editor
{
public static class MultipeerConnectivityTransportBuildProcessor
{
[PostProcessBuild]
public static void OnPostProcessBuild(BuildTarget buildTarget, string buildPath)
{
if (buildTarget == BuildTarget.iOS)
{
// For info.plist
string plistPath = buildPath + "/Info.plist";
PlistDocument plist = new();
plist.ReadFromFile(plistPath);
PlistElementDict rootDict = plist.root;
// For MPC
rootDict.SetString("NSLocalNetworkUsageDescription", "For connecting to nearby devices");
PlistElementArray array = rootDict.CreateArray("NSBonjourServices");
array.AddString("_netcode-mpc._tcp");
array.AddString("_netcode-mpc._udp");
File.WriteAllText(plistPath, plist.WriteToString());
// For build settings
string projectPath = PBXProject.GetPBXProjectPath(buildPath);
PBXProject project = new();
project.ReadFromString(File.ReadAllText(projectPath));
string mainTargetGuid = project.GetUnityMainTargetGuid();
string unityFrameworkTargetGuid = project.GetUnityFrameworkTargetGuid();
project.SetBuildProperty(mainTargetGuid, "ENABLE_BITCODE", "NO");
project.SetBuildProperty(unityFrameworkTargetGuid, "ENABLE_BITCODE", "NO");
project.WriteToFile(projectPath);
}
}
}
}

Просмотреть файл

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 87455759e33dc4b68bdc772bfa69f17c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,16 @@
{
"name": "Netcode.Transports.MultipeerConnectivity.Editor",
"rootNamespace": "Netcode.Transports.MultipeerConnectivity.Editor",
"references": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

Просмотреть файл

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 0a7d4cfcfc6c244ca90689d39f1d12d2
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,11 @@
MIT License
Copyright (c) Holo Interactive
Copyright (c) 2021 Unity Technologies
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Просмотреть файл

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 04d8853901b2745d08dc0f50b58ae938
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,108 @@
# Multipeer Connectivity Transport for Netcode for GameObjects
## Overview
This package implemented the transport layer of Netcode for GameObjects with Apple Multipeer Connectivity, which can enable peer-to-peer communication between nearby devices. By using Multipeer Connectivity, nearby devices can connect to each other when there is no WiFi or cellular network. Multipeer Connectivity is the technology behind AirDrop, which means it can transfer large file between devices very fast. Please reference Apple's official document for detailed information: https://developer.apple.com/documentation/multipeerconnectivity.
We created a [sample project](https://github.com/holoi/UnityNetcodeMPCTransportSample) demonstrating how to properly setup the network connection.
## Some Good to Know Concepts Before Using The Transport
### Host-Client Architecture vs Peer-To-Peer Architecture
Before using this transport, it is important to know that Netcode for GameObjects uses a host-client network architecture while Multipeer Connectivity uses a peer-to-peer architecture.
In a host-client network, one device hosts the network and other devices join the network as clients. The host can directly communicate with all connected clients but a client can only directly communicate with the host. For two connected client, the messages they send to each other must be relayed by the host.
In a peer-to-peer network, there is no host device and any two devices are connected directly as peers. Therefore, any two peers can directly send messages to each other.
In this transport, we wrapped Multipeer Connectivity in a host-client manner to fit the architecture of Netcode for GameObjects.
### Advertising and Browsing
Before nearby devices can establish network connection, Multipeer Connectivity requires a discovery phase where nearby devices first find each other. This makes Multipeer Connectivity transport different from other Netcode transports.
In Multipeer Connectivity, an advertiser is a device which advertises itself and a browser is a device which browses nearby advertising peers. Therefore, in discovery phase, the host device should be an advertiser and all other devices should be browsers. In the following sections, we will use host and advertiser, client and browser interchangeably.
When a host starts the network, it starts to advertise itself so that nearby browsers can find it. When a browser finds a nearby host (an advertiser), it sends a connection request to the host. If the host approves the connection request, the sender of the connection request will be connected to the network as a client. When a client successfully connects to the network, it should stop browsing.
## Transport Configurations
Before start as either host or client, you can set the properties of the transport to adjust its behaviour to meet your needs. Under the default configuration, nearby host and clients will automatically connected.
<img width="363" alt="image" src="https://user-images.githubusercontent.com/44870300/217411500-35190153-683c-46a0-be16-34be3472f341.png">
Property `SessionId` is a string to make your Multipeer Connectivity session unique. Only browsers with the same `SessionId` as the advertiser can connect to the network. When there are multiple applications using Multipeer Connectivity in the surrounding area, this property ensures devices only connected to other devices running the same application.
Property `Nickname` is the name of your device shown in the discovery phase.
### Host Configurations
When property `AutoAdvertise` is set to true, the device will automatically advertise right after starting as host. Otherwise, you will need to start advertising manually.
```
// We make the transport a singleton so you can easily reference it
MultipeerConnectivityTransport.Instance.StartAdvertising();
```
When you do not want new clients to join the network, you can stop advertising so that nearby browers can no longer find you anymore.
```
MultipeerConnectivityTransport.Instance.StopAdvertising();
```
When property `AutoApproveConnectionRequest` is set to true, it will automatically approve any incoming connection request when it receives one. Otherwise, you will need to manually approve all connection requests which you want to approve.
```
private void Start()
{
// Event invoked when the advertiser receives a new connection request
MultipeerConnectivityTransport.Instance.OnAdvertiserReceivedConnectionRequest += OnAdvertiserReceivedConnectionRequest;
}
private void OnAdvertiserReceivedConnectionRequest(int connectionRequestKey, string senderName)
{
if (decide whether we want to approve this connection request)
{
// We approve the connection request with the given key
MultipeerConnectivityTransport.Instance.ApproveConnectionRequest(connectionRequestKey);
}
}
```
### Client Configurations
When property `AutoBrowse` is set to true, the device will automatically browse nearby hosts right after starting as client. Otherwise, you will need to start browsing manually.
```
MultipeerConnectivityTransport.Instance.StartBrowsing();
// You can also stop browsing manually
MultipeerConnectivityTransport.Instance.StopBrowsing();
```
When property `AutoSendConnectionRequest` is set to true, the browser will automatically send connection request to the first nearby host it finds. Otherwise, you will need to manually send connection request to the nearby host with which you want to connect.
```
private void Start()
{
// Event invoked when the browser finds a nearby host device
MultipeerConnectivityTransport.Instance.OnBrowserFoundPeer += OnBrowserFoundPeer;
}
private void OnBrowserFoundPeer(int nearbyHostKey, string nearbyHostName)
{
if (device whether we want to send connection request to this host)
{
MultipeerConnectivityTransport.Instance.SendConnectionRequest(nearbyHostKey);
}
}
```
## iOS Permissions
When you build the project onto your iOS devices for the first time, both host and client devices will trigger the Local Network Permission. You must allow this permission to let your devices connect. Furthermore, the browser device will trigger another Wireless Data Permission. You need to also allow this permission as well.
## Debug Your Project in Unity Editor
Please notice that Multipeer Connectivity Transport can only run on an iOS device. It cannot run on your Mac. Therefore, when you want to debug your project in Unity Editor, we recommand you temporarily switch to use Unity Transport.

Просмотреть файл

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 7e654059b780d4a3a8036a56160410cf
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9b9401d305e574dcb91f2aa272199432
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,494 @@
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
namespace Netcode.Transports.MultipeerConnectivity
{
public class MultipeerConnectivityTransport : NetworkTransport
{
/// <summary>
/// This class is a singleton so it's easy to be referenced anywhere.
/// </summary>
public static MultipeerConnectivityTransport Instance => s_instance;
private static MultipeerConnectivityTransport s_instance;
/// <summary>
/// The server client Id should always be 0.
/// </summary>
public override ulong ServerClientId => 0;
[Tooltip("This is a unique Id to identify your MPC session. Only devices with the same session Id can connect to each other. " +
"You can leave this to empty but it will make your network session not unique.")]
public string SessionId = null;
[Tooltip("This will be the name of your device in the network.")]
public string Nickname = "yuchen";
[Header("Host Config")]
[Tooltip("Setting this to true to automatically advertise after starting host. " +
"Otherwise, you will need to manually call StartAdvertising().")]
public bool AutoAdvertise = true;
[Tooltip("Setting this to true to automatically approve all incoming connection requests. " +
"Otherwise, you will need to manually approve each connection request.")]
public bool AutoApproveConnectionRequest = true;
[Header("Client Config")]
[Tooltip("Setting this to true to automatically browse after starting client. " +
"Otherwise, you will need to manually call StartBrowsing().")]
public bool AutoBrowse = true;
[Tooltip("Setting this to true to automatically join the first browsed session. " +
"Otherwise, you will need to manually send connection request to a host.")]
public bool AutoSendConnectionRequest = true;
public Dictionary<int, string> NearbyHostDict => _nearbyHostDict;
public Dictionary<int, string> PendingConnectionRequestDict => _pendingConnectionRequestDict;
public bool IsAdvertising => _isAdvertising;
public bool IsBrowsing => _isBrowsing;
/// <summary>
/// Showing whether the device is currently advertising itself.
/// </summary>
private bool _isAdvertising = false;
/// <summary>
/// Showing whether the device is currently browsing for nearby peers.
/// </summary>
private bool _isBrowsing = false;
/// <summary>
/// Stores all browsed nearby hosts. The first parameter is the browsed host key
/// and the second is the browsed host name.
/// </summary>
private readonly Dictionary<int, string> _nearbyHostDict = new();
/// <summary>
/// Stores all received connection requests. The first parameter is the connection request key
/// and the second is the name of the client who sent the connection request.
/// </summary>
private readonly Dictionary<int, string> _pendingConnectionRequestDict = new();
/// <summary>
/// Check if we are currently running on an iOS device.
/// </summary>
public static bool IsRuntime => Application.platform == RuntimePlatform.IPhonePlayer;
/// <summary>
/// Initialize the MPCSession and register native callbacks.
/// </summary>
/// <param name="nickname">The name of the device displayed in the network</param>
/// <param name="onBrowserFoundPeer">Invoked when the browser finds a peer</param>
/// <param name="onBrowserLostPeer">Invoked when the browser loses a peer</param>
/// <param name="onAdvertiserReceivedConnectionRequest">Invoked when the advertiser receives a connection request</param>
/// <param name="onAdvertiserApprovedConnectionRequest">Invoked when the advertiser approves a connection request</param>
/// <param name="onConnectingWithPeer">Invoked when connecting with a peer</param>
/// <param name="onConnectedWithPeer">Invoked when connected with a peer</param>
/// <param name="onDisconnectedWithPeer">Invoked when disconnected with a peer</param>
/// <param name="onReceivedData">Invoked when receives data message from a peer</param>
[DllImport("__Internal")]
private static extern void MPC_Initialize(string nickname,
Action<int, string> onBrowserFoundPeer,
Action<int, string> onBrowserLostPeer,
Action<int, string> onAdvertiserReceivedConnectionRequest,
Action<int> onAdvertiserApprovedConnectionRequest,
Action<string> onConnectingWithPeer,
Action<int, string> onConnectedWithPeer,
Action<int, string> onDisconnectedWithPeer,
Action<int, IntPtr, int> onReceivedData);
/// <summary>
/// Start advertising to allow nearby peers to find you.
/// </summary>
/// <param name="sessionId">The unique id of the network session</param>
/// <param name="autoApproveConnectionRequest">Setting to true to approve all incoming connection requests</param>
[DllImport("__Internal")]
private static extern void MPC_StartAdvertising(string sessionId, bool autoApproveConnectionRequest);
/// <summary>
/// Start browsing for nearny advertising peers.
/// </summary>
/// <param name="sessionId">The unique id of the network session</param>
/// <param name="autoSendConnectionRequest">Setting to true to automatically send connection request to the first browsed peer</param>
[DllImport("__Internal")]
private static extern void MPC_StartBrowsing(string sessionId, bool autoSendConnectionRequest);
/// <summary>
/// Stop advertising.
/// </summary>
[DllImport("__Internal")]
private static extern void MPC_StopAdvertising();
/// <summary>
/// Stop browsing.
/// </summary>
[DllImport("__Internal")]
private static extern void MPC_StopBrowsing();
/// <summary>
/// Shutdown and deinitialize the MPCSession.
/// </summary>
[DllImport("__Internal")]
private static extern void MPC_Shutdown();
/// <summary>
/// Send data message to a specific connected peer.
/// </summary>
/// <param name="transportID">The transport id of the recipient peer</param>
/// <param name="data">The raw data</param>
/// <param name="length">The length of the data</param>
/// <param name="reliable">Whether to use realiable way to send the data</param>
[DllImport("__Internal")]
private static extern void MPC_SendData(int transportID, byte[] data, int length, bool reliable);
/// <summary>
/// Send connection request to a specific browsed host.
/// </summary>
/// <param name="nearbyHostKey">The key of the host in the dict</param>
[DllImport("__Internal")]
private static extern void MPC_SendConnectionRequest(int nearbyHostKey);
/// <summary>
/// Approve the connection request sent by a specific client.
/// </summary>
/// <param name="connectionRequestKey">The key of the connection request in the dict</param>
[DllImport("__Internal")]
private static extern void MPC_ApproveConnectionRequest(int connectionRequestKey);
/// <summary>
/// Links to a native callback which is invoked when the browser finds a new nearby host host.
/// </summary>
/// <param name="nearbyHostKey">The key of the host in the dict</param>
/// <param name="nearbyHostName">The name of the host</param>
[AOT.MonoPInvokeCallback(typeof(Action<int, string>))]
private static void OnBrowserFoundPeerDelegate(int nearbyHostKey, string nearbyHostName)
{
if (s_instance != null)
{
// Add browsed host to the dict
s_instance._nearbyHostDict.Add(nearbyHostKey, nearbyHostName);
// Invoke the event
s_instance.OnBrowserFoundPeer?.Invoke(nearbyHostKey, nearbyHostName);
}
}
/// <summary>
/// Links to a native callback which is invoked when the browser loses a host.
/// </summary>
/// <param name="nearbyHostKey">The key of the host in the dict</param>
/// <param name="nearbyHostName">The name of the host</param>
[AOT.MonoPInvokeCallback(typeof(Action<int, string>))]
private static void OnBrowserLostPeerDelegate(int nearbyHostKey, string nearbyHostName)
{
if (s_instance != null)
{
// Remove browsed host from the dict
s_instance._nearbyHostDict.Remove(nearbyHostKey);
// Invoke the event
s_instance.OnBrowserLostPeer?.Invoke(nearbyHostKey, nearbyHostName);
}
}
/// <summary>
/// Links to a native callback which is invoked when the advertiser receives a connection request.
/// </summary>
/// <param name="connectionRequestKey">The key of the connection request in the dict</param>
/// <param name="senderName">The name of the client who sent the connection request</param>
[AOT.MonoPInvokeCallback(typeof(Action<int, string>))]
private static void OnAdvertiserReceivedConnectionRequestDelegate(int connectionRequestKey, string senderName)
{
if (s_instance != null)
{
if (!s_instance.AutoApproveConnectionRequest)
{
// Add connection request to the dict
s_instance._pendingConnectionRequestDict.Add(connectionRequestKey, senderName);
}
// Invoke the event
s_instance.OnAdvertiserReceivedConnectionRequest?.Invoke(connectionRequestKey, senderName);
}
}
/// <summary>
/// Links to a native callback which is invoked when the advertiser handles a connection request.
/// </summary>
/// <param name="connectionRequestKey">The key of the connection request in the dict</param>
[AOT.MonoPInvokeCallback(typeof(Action<int>))]
private static void OnAdvertiserApprovedConnectionRequestDelegate(int connectionRequestKey)
{
if (s_instance != null)
{
if (s_instance._pendingConnectionRequestDict.ContainsKey(connectionRequestKey))
{
// Remove the connection request from the dict
s_instance._pendingConnectionRequestDict.Remove(connectionRequestKey);
}
// Invoke the event
s_instance.OnAdvertiserApprovedConnectionRequest?.Invoke(connectionRequestKey);
}
}
/// <summary>
/// Links to a native callback which is invoked when the local peer is connecting with a peer.
/// </summary>
/// <param name="peerName">The name of the peer</param>
[AOT.MonoPInvokeCallback(typeof(Action<string>))]
private static void OnConnectingWithPeerDelegate(string peerName)
{
if (s_instance != null)
{
s_instance.OnConnectingWithPeer?.Invoke(peerName);
}
}
/// <summary>
/// Links to a native callback which is invoked when the local peer is connected with a peer.
/// </summary>
/// <param name="transportID">The transport id of the peer</param>
/// <param name="peerName">The name of the peer</param>
[AOT.MonoPInvokeCallback(typeof(Action<int, string>))]
private static void OnConnectedWithPeerDelegate(int transportID, string peerName)
{
if (s_instance != null)
{
s_instance._isBrowsing = false;
s_instance._nearbyHostDict.Clear();
s_instance.InvokeOnTransportEvent(NetworkEvent.Connect, (ulong)transportID,
default, Time.realtimeSinceStartup);
}
}
/// <summary>
/// Links to a native callback which is invoked when the local peer is disconnected with a peer.
/// </summary>
/// <param name="transportID">The transport id of the peer</param>
/// <param name="peerName">The name of the peer</param>
[AOT.MonoPInvokeCallback(typeof(Action<int, string>))]
private static void OnDisconnectedWithPeerDelegate(int transportID, string peerName)
{
if (s_instance != null)
{
s_instance.InvokeOnTransportEvent(NetworkEvent.Disconnect, (ulong)transportID,
default, Time.realtimeSinceStartup);
}
}
/// <summary>
/// Links to a native callback which is invoked when the local peer receives data from a peer.
/// </summary>
/// <param name="transportID">The transport id of the peer</param>
/// <param name="dataPtr">The pointer to the raw data</param>
/// <param name="length">The length of the data array</param>
[AOT.MonoPInvokeCallback(typeof(Action<int, IntPtr, int>))]
private static void OnReceivedDataDelegate(int transportID, IntPtr dataPtr, int length)
{
if (s_instance != null)
{
byte[] data = new byte[length];
Marshal.Copy(dataPtr, data, 0, length);
s_instance.InvokeOnTransportEvent(NetworkEvent.Data, (ulong)transportID,
new ArraySegment<byte>(data, 0, length), Time.realtimeSinceStartup);
}
}
/// <summary>
/// Invoked when the browser finds a nearby host peer.
/// The first parameter is the host peer key in the dict.
/// The second parameter is the name of the host peer.
/// </summary>
public event Action<int, string> OnBrowserFoundPeer;
/// <summary>
/// Invoked when the browser loses a nearby host peer.
/// The first parameter is the host peer key in the dict.
/// The second parameter is the name of the host peer.
/// </summary>
public event Action<int, string> OnBrowserLostPeer;
/// <summary>
/// Invoked when the advertiser receives a connection request.
/// The first parameter is the connection request key in the dict.
/// The second parameter is the name of the peer who sent the connection request.
/// </summary>
public event Action<int, string> OnAdvertiserReceivedConnectionRequest;
public event Action<int> OnAdvertiserApprovedConnectionRequest;
/// <summary>
/// Invoked when initializes connection with a new peer. This event should be used only for notification purpose.
/// The first parameter is the name of the connecting peer.
/// </summary>
public event Action<string> OnConnectingWithPeer;
private void Awake()
{
// Initialize the singleton instance
if (s_instance != null && s_instance != this)
{
Destroy(gameObject);
}
else
{
s_instance = this;
}
}
public override void Initialize(NetworkManager networkManager)
{
if (!IsRuntime)
{
Debug.LogError($"[MPCTransport] MPCTransport cannot run in Unity Editor, it can only run on an iOS device. " +
$"If you want to test your project in Unity Editor, please use Unity Transport instead when debugging.");
return;
}
MPC_Initialize(Nickname,
OnBrowserFoundPeerDelegate,
OnBrowserLostPeerDelegate,
OnAdvertiserReceivedConnectionRequestDelegate,
OnAdvertiserApprovedConnectionRequestDelegate,
OnConnectingWithPeerDelegate,
OnConnectedWithPeerDelegate,
OnDisconnectedWithPeerDelegate,
OnReceivedDataDelegate);
}
public override bool StartServer()
{
if (AutoAdvertise)
{
StartAdvertising();
}
return true;
}
public override bool StartClient()
{
if (AutoBrowse)
{
StartBrowsing();
}
return true;
}
public override NetworkEvent PollEvent(out ulong transportId, out ArraySegment<byte> payload, out float receiveTime)
{
transportId = 0;
payload = default;
receiveTime = Time.realtimeSinceStartup;
return NetworkEvent.Nothing;
}
public override void Send(ulong transportId, ArraySegment<byte> data, NetworkDelivery networkDelivery)
{
MPC_SendData((int)transportId, data.Array, data.Count,
!(networkDelivery == NetworkDelivery.Unreliable || networkDelivery == NetworkDelivery.UnreliableSequenced));
}
public override ulong GetCurrentRtt(ulong transportId)
{
return 0;
}
/// <summary>
/// Called when a client tries to disconnect from the server.
/// </summary>
public override void DisconnectLocalClient()
{
}
public override void DisconnectRemoteClient(ulong transportId)
{
}
public override void Shutdown()
{
if (IsRuntime)
{
MPC_Shutdown();
// Reset variables
_pendingConnectionRequestDict.Clear();
_nearbyHostDict.Clear();
_isAdvertising = false;
_isBrowsing = false;
}
}
/// <summary>
/// Start advertising.
/// </summary>
public void StartAdvertising()
{
if (IsRuntime && !_isAdvertising)
{
_pendingConnectionRequestDict.Clear();
MPC_StartAdvertising(SessionId, AutoApproveConnectionRequest);
_isAdvertising = true;
}
}
/// <summary>
/// Stop advertising.
/// </summary>
public void StopAdvertising()
{
if (IsRuntime && _isAdvertising)
{
MPC_StopAdvertising();
_isAdvertising = false;
_pendingConnectionRequestDict.Clear();
}
}
/// <summary>
/// Start browsing.
/// </summary>
public void StartBrowsing()
{
if (IsRuntime && !_isBrowsing)
{
_nearbyHostDict.Clear();
MPC_StartBrowsing(SessionId, AutoSendConnectionRequest);
_isBrowsing = true;
}
}
/// <summary>
/// Stop browsing.
/// </summary>
public void StopBrowsing()
{
if (IsRuntime && _isBrowsing)
{
MPC_StopBrowsing();
_isBrowsing = false;
_nearbyHostDict.Clear();
}
}
public void SendConnectionRequest(int nearbyHostKey)
{
if (IsRuntime)
{
MPC_SendConnectionRequest(nearbyHostKey);
}
}
public void ApproveConnectionRequest(int connectionRequestKey)
{
if (IsRuntime)
{
MPC_ApproveConnectionRequest(connectionRequestKey);
}
}
}
}

Просмотреть файл

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a34c91f8a5fd946968f5c22555ab3655
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,16 @@
{
"name": "Netcode.Transports.MultipeerConnectivity",
"rootNamespace": "Netcode.Transports.MultipeerConnectivity",
"references": [
"GUID:1491147abca9d7d4bb7105af628b223e"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

Просмотреть файл

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 07b02f18e0d754e9596ba13afb37f745
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 96c87c164f0014152ac1957d1f4b5c06
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,73 @@
fileFormatVersion: 2
guid: 3552ddd18e8294e9d8c976b103e71aee
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 0
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,8 @@
{
"name": "com.community.netcode.transport.multipeer-connectivity",
"displayName": "Multipeer Connectivity for Netcode for GameObjects",
"version": "0.0.1",
"unity": "2021.3",
"description": "This package implemented the transport layer of Netcode for GameObjects with Apple Multipeer Connectivity, which can enable peer-to-peer communication between nearby devices.\n\nBy using Multipeer Connectivity, nearby devices can connect to each other when there is no WiFi or cellular network. Multipeer Connectivity is the technology behind AirDrop, which means it can transfer large file between devices very fast.\n\nPlease reference Apple's official document for detailed information: https://developer.apple.com/documentation/multipeerconnectivity.",
"author": "Holo Interactive"
}

Просмотреть файл

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6b3677f68a57a4c118c24fa9a4f74840
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: