Astuces de persistance
La persistance est disponible si elle est prise en charge par la plateforme sous-jacente. Actuellement, cette fonctionnalité est limitée à la famille d’appareils HoloLens, avec la prise en charge de VR intégrée d’Unity (XR héritée).
Persistance de base
La persistance de base pour les outils World Locking Tools est activée par défaut. Cette activation comprend deux parties.
Les cases concernées sont « Chargement automatique » et « Enregistrement automatique », qui sont cochées. Vous remarquez peut-être que les options sont grisées. Cela est dû au fait qu’elles font partie de la sélection « Utiliser les valeurs par défaut ». La désactivation de l’option « Utiliser les valeurs par défaut » permet de sélectionner les options d’automatisation individuellement.
Des informations supplémentaires sont disponibles sur ces paramètres, ainsi que sur leur manipulation à partir d’un script.
AutoSave
L’option Enregistrement automatique indique à WLT d’effectuer des enregistrements d’état fréquents et réguliers lors de l’exécution de l’application. À tout moment, l’application peut être arrêtée avec une perte minimale d’état.
AutoLoad
L’option de chargement automatique AutoLoad indique à WLT de charger tout état précédemment enregistré au démarrage. Cela permet à l’application de reprendre une nouvelle session là où la dernière session s’était arrêtée (concernant WLT).
Persistance complète
Quand les options d’enregistrement automatique/de chargement automatique (AutoSave/AutoLoad) sont activées, WLT fonctionne de manière fluide entre les sessions. Alors que la position et l’orientation de l’espace global sont arbitraires lors de la première exécution (étant donné qu’il n’existe aucun état précédent enregistré, la position de la tête sert de point d’origine au démarrage), les exécutions suivantes partagent ce même cadre de coordonnées.
Cela entraîne un comportement intéressant quand l’application démarre une nouvelle session dans un espace déconnecté de l’espace de la session précédente. Pour plus d’informations, consultez la section persistance par emplacement ci-dessous.
Remarque
Les paramètres d’enregistrement automatique et de chargement automatique (AutoSave/AutoLoad) s’appliquent également aux SpacePins globaux. Voir ci-dessous pour plus de détails.
Contrôle d’application sur la persistance
La persistance complète par défaut convient à un large éventail d’applications.
Toutefois, certaines applications peuvent avoir besoin d’un contrôle plus précis sur le processus.
Il peut sembler étrange que l’activation de la persistance automatique WLT soit divisée en deux propriétés : l’enregistrement automatique (AutoSave) et le chargement automatique (AutoLoad). En examinant les cas où les deux sont utilisés indépendamment, on obtient des insights sur le système de persistance global.
Enregistrement automatique sans chargement automatique
Avec cette configuration, WLT est configuré pour enregistrer régulièrement son état. Toutefois, l’état persistant n’est pas chargé automatiquement au démarrage.
Au lieu de cela, le système démarre dans un nouvel état, comme s’il s’agissait de la première exécution sur cet appareil. L’état de la session précédente est restauré uniquement après une demande explicite de Load().
Cela permet à l’application de décider si la restauration de l’état de la session précédente est l’action appropriée, et même de modifier les données restaurées si nécessaire.
L’état général de l’enregistrement WLT se trouve dans le fichier « LocalState/frozenWorldState.hkfw ». Une fois créé par WLT, ce fichier peut être copié vers un autre emplacement et restauré selon les besoins de l’application.
Les données d’enregistrement du fichier d’alignement (SpacePin) sont par défaut « LocalState/Persistence/Alignment.fwb ». Toutefois, cela peut être remplacé par l’application via le SaveFileName du gestionnaire d’alignement.
La décision de charger l’état de la session précédente avec cette configuration doit être effectuée au démarrage. Lors de l’exécution, l’état enregistré de la session précédente est remplacé par l’état de cette session. Pour une configuration plus flexible, consultez Enregistrement et chargement manuels ci-dessous.
Enregistrement manuel, mais chargement automatique
Dans cette configuration, WLT charge les états disponibles à partir d’une session précédente au démarrage. Toutefois, l’état n’est pas enregistré automatiquement. Cela permet à l’application de décider si l’état doit être enregistré et à quel moment, avec un appel à Save().
L’option de chargement automatique (AutoLoad) indique uniquement à WLT de charger tous les états disponibles au démarrage. L’application peut restaurer tout état enregistré, à tout moment, à l’aide d’un appel explicite à Load().
Enregistrement et chargement manuels
L’application peut choisir de conserver un contrôle total sur le processus d’enregistrement et de chargement.
L’état est ensuite enregistré uniquement avec un appel explicite de l’application à Save(). Il est chargé uniquement avec un appel explicite à Load().
L’état chargé par l’appel à Load() peut avoir été enregistré précédemment lors de cette session ou d’une session précédente.
Désactivation de la persistance
Comme expliqué ci-dessus, la persistance est toujours disponible pour l’application à partir du script. La persistance automatisée peut être activée et désactivée à partir d’un script ou d’un WorldLockingContext dans l’inspecteur. Si la persistance automatisée est désactivée, WLT ne tente pas d’enregistrer ou de charger l’état sans demandes explicites de l’application.
Bien sûr, étant donné que la commande de chargement automatique (AutoLoad) affecte uniquement le chargement au démarrage, la modification de la valeur du script après le démarrage n’a aucun effet.
Attention lors du développement
Comme indiqué ci-dessus, l’emplacement des fichiers d’enregistrement pour les outils WLT globaux et l’alignement sont globaux pour l’application. En particulier, les nœuds d’alignement, également appelés SpacePins, sont conservés par nom (voir ci-dessous). Si une application enregistre l’état avec un ensemble de SpacePins à partir d’une scène, puis charge l’état avec un ensemble de SpacePins à partir d’une autre scène, et que les deux ensembles de SpacePins partagent des noms communs, le comportement n’est pas défini.
Il existe plusieurs façons de contourner ce problème. Si possible, il est préférable de tout simplement éviter de réutiliser les noms SpacePin dans un projet. Si vous constatez un comportement de glissement de scène inattendu après le redéploiement, essayez de supprimer l’état de l’enregistrement WLT. De même, en cas de modification radicale de l’application, les utilisateurs les plus prudents souhaitent peut-être supprimer les fichiers d’enregistrement WLT sur l’appareil, ou simplement désinstaller l’application avant d’installer la nouvelle version.
Persistance par emplacement
Scénario
Il existe une classe intéressante d’applications qui sont exécutées dans plusieurs emplacements physiques. L’application peut être exécutée dans la salle A, l’appareil fermé, déplacé, puis l’application A redémarrée dans la salle B. La salle B peut se situer à proximité de la salle A ou bien sur un autre continent. L’application et l’appareil n’ont aucun moyen de le savoir.
Pour simplifier, disons que l’application est configurée pour la persistance WLT manuelle.
Démonstration
Prenons par exemple les salles non connectées A et B.
L’application est démarrée dans la salle A. Après avoir établi un espace de coordonnées figé contigu dans la salle, la totalité de la salle est mappée à fragment 1. Un objet X d’hologramme persistant est placé dans la salle. L’application enregistre ensuite l’État, puis elle est fermée.
L’appareil est mis hors tension, déplacé vers la salle B, puis redémarré.
L’appareil reconnaît qu’il ne s’agit pas de la salle A. WLT affecte donc un nouvel ID de fragment à son contenu, par exemple ID == 29. Pourquoi la valeur 29 ? Car ce n’est pas 1. Les ID de fragment sont des valeurs arbitraires, autres que 1. Les ID de fragment ne sont pas FragmentId.Invalid, ni FragmentId.Unknown, ni identiques à un autre fragment connu.
Il existe maintenant deux fragments, sans moyen de les fusionner (car aucune information n’est disponible sur leurs emplacements relatifs).
Le développeur de l’application peut se demander : J’ai placé un objet X persistant dans la salle A, que se passe-t-il quand l’objet X est chargé au démarrage de l’application dans la salle B ?
La réponse est que le comportement est déterminé par le développeur de l’application. L’ID de fragment actuel quand l’objet X est placé dans la salle A est disponible et peut être rendu persistant. L’application peut ensuite décider au démarrage s’il faut afficher l’objet X ou non, selon que le fragment actuel est le même que lors de sa création ou non.
Ici, le développeur décide (et implémente) que l’objet X est chargé uniquement si l’ID de fragment actuel est 1, et que l’objet Y, à partir de la salle B, est chargé uniquement si le fragment actuel est 29.
La persistance de l’ID de fragment associé à un espace est enregistrée dans le cadre de la persistance des outils World Locking Tools. Toutefois, la persistance de l’ID de fragment associé à un objet, ainsi que les actions à entreprendre en fonction de celle-ci, sont déterminées par l’application.
Il est possible d’enregistrer la position dans l’espace global avec l’ID de fragment associé à l’objet. Si l’ID de fragment correspond, après le chargement de l’objet, sa position peut être restaurée. Il repasse alors à sa position dans le monde physique lors de la dernière session. Avec la persistance des outils World Locking Tools, une pose reste fixe entre les sessions par rapport aux caractéristiques du monde physique qui l’entourent.
Persistance des SpacePins
Les SpacePins peuvent être considérés comme des wrappers côté application pour AlignmentAnchors. Tandis que les SpacePins (et les classes dérivées) sont des composants Unity, les AlignmentAnchors sont purement conceptuels. Il n’existe pas de classe ni de type correspondant à un AlignmentAnchor. Par conséquent, dans cette discussion, les SpacePins et AlignmentAnchors sont utilisés de manière interchangeable, avec une préférence générale pour les SpacePins.
Toutefois, cela peut déconcerter un utilisateur qu’un AlignmentManager puisse persister des SpacePins, quand il n’a aucune notion de SpacePins. Cela est dû au fait qu’AlignmentManager gère le AlignmentAnchor conceptuel, qui représente l’essence d’un SpacePin et à partir duquel un SpacePin peut être reconstitué.
Il existe plus de contrôles au niveau de l’application pour la persistance des SpacePins que pour le système de persistance WLT général, car les SpacePins sont intrinsèquement davantage pilotés par les entrées de l’application que le reste des outils World Locking Tools.
Il est important de se souvenir que les SpacePins (et AlignmentAnchors) sont conservés par nom. Les exigences sont légèrement plus étendues que la règle plus générale interdisant que deux SpacePins actifs dans la même interface IAlignmentManager portent le même nom. En cas de SpacePins persistants, deux SpacePins de la même base de données ne peuvent pas porter le même nom, qu’ils soient actifs ou non.
Bases de données du gestionnaire d’alignement
Chaque IAlignmentManager dispose d’une base de données de SpacePins par nom, comme impliqué par son implémentation de RestoreAlignmentAnchor (chaîne uniqueName, position virtualPose).
Base de données d’alignement globale
Il existe un IAlignmentManager global, détenu par WorldLockingManager.GetInstance(). Comme mentionné, l’emplacement par défaut du fichier d’enregistrement est déterminé par la propriété SaveFileName. Notez que SaveFileName est une propriété de la classe AlignmentManager, et non de l’interface IAlignmentManager. Une implémentation de l’interface IAlignmentManager peut implémenter la persistance sans aucun concept de fichier ni de nom de fichier. SaveFileName est un artefact de la façon dont la classe AlignmentManager implémente la persistance. Il est donc limité à la classe AlignmentManager.
Bases de données d’alignement local
Il peut exister un nombre quelconque de gestionnaires d’alignement des sous-espaces, un pour chaque AlignSubtree, qui apparaît comme le champ AlignSubtree.alignmentManager. En outre, l’application peut créer ses propres instances AlignmentManager, voire ses propres classes dérivées de IAlignmentManager.
L’AlignmentManager de chaque composant AlignSubtree a son propre emplacement de fichier d’enregistrement, qui correspond par défaut au nom de GameObject avec l’extension « .fwb». Par exemple, si le composant AlignSubtree est placé sur un GameObject nommé « MyRoot », le fichier d’enregistrement est nommé « MyRoot.fwb ». Une barre oblique « / » peut être utilisée pour le placer dans un sous-dossier. Il est déconseillé que deux composants AlignSubtree utilisent le même emplacement de fichier d’enregistrement.
En résumé
À long terme, il est fortement recommandé de donner des noms globaux uniques SpacePins/AlignmentAnchoril, car cela est plus simple et plus robuste, que de tenter de gérer l’exigence plus simple localement unique. Mais vous pouvez faire comme vous le souhaitez.