Transferts d’ancre locale dans Unity
Dans les situations où vous ne pouvez pas utiliser Azure Spatial Anchors, les transferts d’ancre locaux permettent à un appareil HoloLens d’exporter une ancre à importer par un deuxième appareil HoloLens.
Remarque
Les transferts d’ancres locales fournissent un rappel d’ancre moins robuste que Les ancres spatiales Azure, et les appareils iOS et Android ne sont pas pris en charge par cette approche.
Définition de la fonctionnalité SpatialPerception
Pour qu’une application transfère des ancres spatiales, la fonctionnalité SpatialPerception doit être activée.
Comment activer la fonctionnalité SpatialPerception :
- Dans l’Éditeur Unity, ouvrez le volet « Paramètres du lecteur » (Modifier > le lecteur des paramètres > du projet)
- Cliquez sur l’onglet « Windows Store »
- Développez « Paramètres de publication » et cochez la fonctionnalité « SpatialPerception » dans la liste « Fonctionnalités »
Remarque
Si vous avez déjà exporté votre projet Unity vers une solution Visual Studio, vous devez exporter vers un nouveau dossier ou définir manuellement cette fonctionnalité dans AppxManifest dans Visual Studio.
Transfert d’ancre
Espace de noms : UnityEngine.XR.WSA.Sharing
Type : WorldAnchorTransferBatch
Pour transférer un WorldAnchor, il faut établir l’ancre à transférer. L’utilisateur d’un HoloLens analyse son environnement et choisit manuellement ou programmatiquement un point dans l’espace pour être l’ancre pour l’expérience partagée. Les données qui représentent ce point peuvent ensuite être sérialisées et transmises aux autres appareils qui partagent l’expérience. Chaque appareil désérialise ensuite les données d’ancrage et tente de localiser ce point dans l’espace. Pour que le transfert d’ancre fonctionne, chaque appareil doit avoir analysé suffisamment d’environnement afin que le point représenté par l’ancre puisse être identifié.
Programme d’installation
L’exemple de code de cette page comporte quelques champs qui devront être initialisés :
- GameObject rootGameObject est un GameObject dans Unity qui a un composant WorldAnchor sur celui-ci. Un utilisateur de l’expérience partagée place ce GameObject et exporte les données vers les autres utilisateurs.
- WorldAnchor gameRootAnchor est unityEngine.XR.WSA.WorldAnchor qui se trouve sur rootGameObject.
- byte[] importedData est un tableau d’octets pour l’ancre sérialisée que chaque client reçoit sur le réseau.
public GameObject rootGameObject;
private UnityEngine.XR.WSA.WorldAnchor gameRootAnchor;
void Start ()
{
gameRootAnchor = rootGameObject.GetComponent<UnityEngine.XR.WSA.WorldAnchor>();
if (gameRootAnchor == null)
{
gameRootAnchor = rootGameObject.AddComponent<UnityEngine.XR.WSA.WorldAnchor>();
}
}
Exportation
Pour exporter, nous avons simplement besoin d’un WorldAnchor et de savoir ce que nous l’appellerons de telle sorte qu’il soit logique pour l’application de réception. Un client de l’expérience partagée effectue ces étapes pour exporter l’ancre partagée :
- Créer un WorldAnchorTransferBatch
- Ajouter WorldAnchors à transférer
- Commencer l’exportation
- Gérer l’événement OnExportDataAvailable à mesure que les données deviennent disponibles
- Gérer l’événement OnExportComplete
Nous créons un WorldAnchorTransferBatch pour encapsuler ce que nous allons transférer, puis l’exporter en octets :
private void ExportGameRootAnchor()
{
WorldAnchorTransferBatch transferBatch = new WorldAnchorTransferBatch();
transferBatch.AddWorldAnchor("gameRoot", this.gameRootAnchor);
WorldAnchorTransferBatch.ExportAsync(transferBatch, OnExportDataAvailable, OnExportComplete);
}
À mesure que les données deviennent disponibles, envoyez les octets au client ou à la mémoire tampon en tant que segments de données disponibles et envoyez par le biais des moyens souhaités :
private void OnExportDataAvailable(byte[] data)
{
TransferDataToClient(data);
}
Une fois l’exportation terminée, si nous avons transféré des données et que la sérialisation a échoué, indiquez au client d’ignorer les données. Si la sérialisation a réussi, indiquez au client que toutes les données ont été transférées et que l’importation peut démarrer :
private void OnExportComplete(SerializationCompletionReason completionReason)
{
if (completionReason != SerializationCompletionReason.Succeeded)
{
SendExportFailedToClient();
}
else
{
SendExportSucceededToClient();
}
}
Importation en cours
Après avoir reçu tous les octets de l’expéditeur, nous pouvons importer les données dans un WorldAnchorTransferBatch et verrouiller notre objet de jeu racine dans le même emplacement physique. Remarque : l’importation échoue parfois temporairement et doit être retentée :
// This byte array should have been updated over the network from TransferDataToClient
private byte[] importedData;
private int retryCount = 3;
private void ImportRootGameObject()
{
WorldAnchorTransferBatch.ImportAsync(importedData, OnImportComplete);
}
private void OnImportComplete(SerializationCompletionReason completionReason, WorldAnchorTransferBatch deserializedTransferBatch)
{
if (completionReason != SerializationCompletionReason.Succeeded)
{
Debug.Log("Failed to import: " + completionReason.ToString());
if (retryCount > 0)
{
retryCount--;
WorldAnchorTransferBatch.ImportAsync(importedData, OnImportComplete);
}
return;
}
this.gameRootAnchor = deserializedTransferBatch.LockObject("gameRoot", this.rootGameObject);
}
Une fois qu’un GameObject est verrouillé via l’appel LockObject, il aura un WorldAnchor qui le conservera dans la même position physique dans le monde, mais il peut se trouver à un emplacement différent dans l’espace de coordonnées Unity que d’autres utilisateurs.