Partager via


Installation à la demande pour les jeux

Cet article technique décrit deux techniques, l’installation à la demande et l’installation en arrière-plan, en utilisant Windows Installer. Les jeux peuvent utiliser ces techniques d’installation pour offrir une expérience de jeu meilleure et plus agréable aux joueurs, en réduisant le temps d’installation.

Vue d’ensemble

L’installation est un élément des applications basées sur ordinateur depuis longtemps. La plupart des applications nécessitent aujourd’hui d’être installées sur le disque dur local de l’utilisateur avant de pouvoir être utilisées. Les jeux vidéo ne font pas exception. Lorsqu’un consommateur achète un jeu Microsoft Windows et tente de l’exécuter, il doit d’abord passer par un processus d’installation qui copie les fichiers nécessaires du disque de jeu vers le disque dur. Ce processus d’installation est généralement long, et peut prendre jusqu’à une heure. Le temps d’installation est un facteur qui fait que certains joueurs préfèrent les jeux sur console aux jeux sur ordinateur, car ils peuvent jouer immédiatement à un jeu sur console après avoir inséré le disque de jeu. La technologie abordée dans cet article tentera de résoudre ce problème, en réduisant considérablement le temps d’installation.

Les jeux nécessitent habituellement que tous les fichiers, ou la plupart, soient installés avant le lancement. Pour réaliser une installation à la demande, les ressources de jeu doivent être modulaires. Autrement dit, le développeur doit diviser les ressources de l’application (graphiques et audio entre autres) en composants. Chaque composant est un ensemble de ressources qui peuvent être installées ou supprimées en tant qu’ensemble. Une fois cette opération effectuée, le développeur de jeu définit une ou plusieurs fonctionnalités, généralement une ou plusieurs par niveau ou zone. Chaque fonctionnalité d’une application spécifie un ensemble de composants nécessaires pour l’exécution de cette fonctionnalité particulière. Lorsqu’une application est installée, ses fonctionnalités peuvent être marquées comme « installées » (composants copiés sur le disque dur local au moment de l’installation) ou « publiées » (composants copiés sur le disque dur local après l’installation initiale, lorsque l’application utilise cette fonctionnalité). Un développeur de jeu peut réduire le temps d’installation en concevant un jeu pour qu’il se lance et s’exécute avec un ensemble minimal de fonctionnalités installées. Le reste de ses fonctionnalités peut être marqué comme « publié » et installé à la demande lorsque l’application a réellement besoin d’utiliser des composants fournis par ces fonctionnalités.

Les jeux peuvent appeler Windows Installer pour installer une fonctionnalité particulière qui n’a peut-être pas été installée. Pour que l’installation apparaisse en arrière-plan, un thread de travail peut être utilisé pour effectuer les appels au programme d’installation tandis que le thread principal continue de gérer la logique de jeu et l’affichage de l’écran. Cela réduit la perturbation du gameplay causée par l’installation. Le jeu peut lancer l’installation à tout moment. Toutefois, L’installation consommant des cycles de processeur, il n’est généralement pas judicieux d’effectuer l’installation lorsque le thread principal est en besoin critique de puissance de traitement, par exemple lorsque l’utilisateur est au cœur de l’action. Par exemple, un moment opportun pour effectuer l’installation peut être pendant que l’utilisateur se trouve dans le menu du jeu, lorsque le jeu est suspendu ou réduit, ou lorsque l’utilisateur regarde le film d’introduction ou d’autres extraits.

Prise en charge des correctifs

La plupart des jeux actuels doivent être mis à jour même dès leur expédition, à mesure que les bogues sont corrigés et que de nouvelles fonctionnalités sont ajoutées. La mise à jour nécessite souvent l’application de correctifs, qui est traditionnellement une procédure simple pour les jeux. Tous les fichiers nécessaires étant installés sur le disque dur de l’utilisateur, l’application de correctifs à un jeu implique de copier les fichiers révisés sur le disque dur, en remplaçant les fichiers existants. Lorsque l’installation à la demande est utilisée, tous les fichiers ne sont pas installés et copiés au moment de l’application des correctifs. Par conséquent, l’éditeur de correctifs ne peut pas juste écrire les fichiers mis à jour dans le dossier du jeu.

Windows Installer dispose de fonctionnalités pour l’application de correctifs aux applications qui utilisent l’installation à la demande. Lorsqu’il applique un correctif, le programme d’installation le met en cache sur le système. Cette fonctionnalité fonctionne bien pour les correctifs avec de petits deltas. Les fichiers publiés à l’origine n’ont plus besoin d’être sur le disque au moment de l’application du correctif, de sorte que ces fichiers peuvent être publiés. Plus tard, lorsque l’application s’exécute et doit accéder aux fichiers, le programme d’installation installe la version la plus récente de ces fichiers en copiant la version initialement publiée depuis le média (par exemple, un CD) et en appliquant le correctif après avoir lu les données de correctif enregistrées.

Exemple du kit de développement logiciel (SDK) InstallOnDemand

L’exemple Installation à la demande pour les jeux illustre les techniques d’installation à la demande abordées dans cet article. Contrairement à d’autres exemples, Installation à la demande pour les jeux ne peut pas être exécuté directement à partir du navigateur exemple. L’exemple utilisant Windows Installer pour gérer son installation, il doit être inclus dans la base de données des applications installées du programme d’installation.

Pour lancer l’exemple

  1. Utilisez le lien Install Project dans le navigateur exemple pour copier les fichiers de l’exemple dans un dossier.
  2. Double-cliquez sur InstallOnDemand.msi pour installer l’exemple.
  3. Sélectionnez Installation classique.
  4. Démarrez l’exemple en lançant InstallOnDemand.exe dans le dossier installé (généralement Program Files\InstallOnDemand) ou en le lançant depuis Menu Démarrer\Programmes.

InstallOnDemand.msi est une base de données reconnue par le programme d’installation. Elle définit l’ensemble du processus d’installation : la structure des répertoires, ce qui sera et ne sera pas copié, quelles ressources seront copiées ensemble, quelles valeurs de registre écrire, quels raccourcis créer, etc.

Au moment du lancement, l’exemple lit une séquence d’introduction. Le joueur peut y mettre fin et entrer dans le menu principal en appuyant sur la touche Échap. Après l’introduction, le joueur peut démarrer un nouvelle partie en entrant un nom de personnage et en faisant défiler des statistiques. Avant que l’exemple commence à lire la séquence d’introduction, il appelle une fonction d’installation pour vérifier si la fonctionnalité de niveau 1 est installée. Si la fonctionnalité de niveau 1 n’a pas été installée, l’exemple utilise un thread d’arrière-plan pour demander au programme d’installation d’installer le jeu, tandis que le thread principal effectue quelque chose d’autre (par exemple, la lecture de la séquence d’introduction, l’affichage du menu ou l’interaction avec le joueur lors de la création de personnage). L’expérience est différente de celle de l’installation traditionnelle du jeu, dans laquelle l’utilisateur est occupé dans le jeu (à regarder l’introduction ou à créer un personnage) pendant que l’installation progresse. Une fois que le joueur a terminé la création d’un personnage, l’exemple charge les ressources pour le niveau 1.

Sur le côté droit de l’exemple d’écran figurent cinq boutons marqués « Lire Niveau 1 » à « Lire Niveau 5 ». Ces boutons simulent l’achèvement du joueur du niveau actuel et l’avancement vers le suivant. Lorsque l’un de ces boutons est cliqué, un écran de statistiques s’affiche, indiquant des informations sur le niveau qui vient d’être terminé. L’exemple utilise également ce moment pour demander au programme d’installation de vérifier et d’installer le niveau suivant, s’il ne l’est pas déjà. L’installation se déroule pendant que le joueur lit l’écran des statistiques, de sorte que lorsque l’utilisateur clique sur OK pour entrer dans le niveau suivant, les ressources du niveau sont toutes installées et prêtes à être chargées.

Fonctionnalités et composants de l’exemple

Les jeux nécessitent habituellement que tous les fichiers, ou la plupart, soient installés avant le lancement. Pour réaliser une installation à la demande, les ressources de jeu doivent être modulaires. Autrement dit, le développeur doit diviser les ressources de l’application (graphiques et audio entre autres) en composants. Chaque composant est un ensemble de ressources qui peuvent être installées ou supprimées en tant qu’ensemble. Une fois cette opération effectuée, le développeur de jeu définit une ou plusieurs fonctionnalités, généralement une ou plusieurs par niveau ou zone. Chaque fonctionnalité d’une application spécifie un ensemble de composants nécessaires pour l’exécution de cette fonctionnalité particulière. Lorsqu’une application est installée, ses fonctionnalités peuvent être marquées comme « installées » (composants copiés sur le disque dur local au moment de l’installation) ou « publiées » (composants copiés sur le disque dur local lorsque l’application utilise plus tard cette fonctionnalité). Un développeur de jeu peut réduire le temps d’installation en concevant un jeu pour qu’il se lance et commence à s’exécuter avec un ensemble minimal de fonctionnalités installées. Le reste de ses fonctionnalités peut être marqué comme « publié » et installé à la demande lorsque l’application a réellement besoin d’utiliser des composants fournis par ces fonctionnalités.

Le tableau suivant répertorie les six fonctionnalités de niveau supérieur que l’exemple définit.

Nom de la fonctionnalité Fonctionnalités Composants Fichiers
Core Inclut les ressources requises à tout moment, quel que soit le niveau. Ces ressources sont les suivantes : exemple d’exécutable, média requis par la séquence d’introduction et l’écran de chargement et fichier .fx qui gère tout le rendu dans l’exemple. Core InstallOnDemand.exe, InstallOnDemand.fx, Loading.bmp, Level.x
Core (comme ci-dessus) CoreUI Media\UI\dxutcontrols.dds, Media\UI\DXUTShared.fx, Media\UI\arrow.x
Core (comme ci-dessus) CoreMisc Media\Misc\seafloor.x, Media\Misc\seafloor.bmp
Core (comme ci-dessus) CoreSpeeder Media\PRT Demo\LandShark.x, Media\PRT Demo\speeder_diff.jpg
Core (comme ci-dessus) CoreReg N/A (valeur de Registre)
Level1 Fournit les ressources utilisées par le niveau 1. Level1 Level1.jpg
Level1 (comme précédemment) L1Skybox Media\Light Probes\galileo_cross.dds
Level2 Fournit les ressources utilisées par le niveau 2. Level2 Level2.jpg
Level2 (comme précédemment) L2Skybox Media\Light Probes\grace_cross.dds
Level3 Fournit les ressources utilisées par le niveau 3. Level3 Level3.jpg
Level3 (comme précédemment) L3Skybox Media\Light Probes\rnl_cross.dds
Level4 Fournit les ressources utilisées par le niveau 4. Level4 Level4.jpg
Level4 (comme précédemment) L4Skybox Media\Light Probes\stpeters_cross.dds
Level5 Fournit les ressources utilisées par le niveau 5. Level5 Level5.jpg
Level5 (comme précédemment) L5Skybox Media\Light Probes\uffizi_cross.dds

 

Les fonctionnalités des niveaux 1 à 5 ont des sous-fonctionnalités supplémentaires qui contiennent des fichiers qui ne sont pas directement utilisés par l’exemple. Ces fichiers de sous-fonctionnalités ont été ajoutés pour rendre l’installation plus longue. Ceci dans le but d’illustrer l’opération d’installation en cours qui s’exécute en arrière-plan pendant l’exécution de l’exemple.

Le tableau suivant liste les sous-fonctionnalités.

Fonction Sous-fonctionnalités Fichiers
Level1 L1PH1, L1PH2, L1PH3, L1PH4, L1PH5 Level1 Placeholder Data\L1PH1.dat Level1 Placeholder Data\L1PH2.dat Level1 Placeholder Data\L1PH3.dat Level1 Placeholder Data\L1PH4.dat Level1 Placeholder Data\L1PH5.dat
Level2 L2PH1, L2PH2, L2PH3, L2PH4, L2PH5 Level2 Placeholder Data\L2PH1.dat Level2 Placeholder Data\L2PH2.dat Level2 Placeholder Data\L2PH3.dat Level2 Placeholder Data\L2PH4.dat Level2 Placeholder Data\L2PH5.dat
Level3 L3PH1, L3PH2, L3PH3, L3PH4, L3PH5 Level3 Placeholder Data\L3PH1.dat Level3 Placeholder Data\L3PH2.dat Level3 Placeholder Data\L3PH3.dat Level3 Placeholder Data\L3PH4.dat Level3 Placeholder Data\L3PH5.dat
Level4 L4PH1, L4PH2, L4PH3, L4PH4, L4PH5 Level4 Placeholder Data\L4PH1.dat Level4 Placeholder Data\L4PH2.dat Level4 Placeholder Data\L4PH3.dat Level4 Placeholder Data\L4PH4.dat Level4 Placeholder Data\L4PH5.dat
Level5 L5PH1, L5PH2, L5PH3, L5PH4, L5PH5 Level5 Placeholder Data\L5PH1.dat Level5 Placeholder Data\L5PH2.dat Level5 Placeholder Data\L5PH3.dat Level5 Placeholder Data\L5PH4.dat Level5 Placeholder Data\L5PH5.dat

 

Pendant l’installation, la fonctionnalité principale doit être marquée « installée » et toutes les autres fonctionnalités doivent être marquées comme « publiées ». En installant une seule fonctionnalité au lieu de six, le temps d’attente du joueur avant le lancement du jeu est considérablement réduit.

Installation

Windows Installer fournit un mécanisme permettant à une application de demander l’installation d’une fonctionnalité publiée. Toutefois, le mécanisme est un appel d’interface de programmation d’application (API) synchrone, ce qui signifie que l’application doit attendre dans l’appel jusqu’à ce que l’installation soit terminée. Pour effectuer une installation en arrière-plan, un thread de travail est requis afin que le thread d’application principal soit libre d’effectuer d’autres tâches importantes, telles que le rendu à l’écran pour continuer à fournir donner des rétroactions visuelles au joueur.

Dans l’exemple, trois états d’installation peuvent se produire pendant l’exécution de l’exemple : installation active, installation passive et aucune installation.

  • L’installation active est une demande lancée par l’exemple lorsqu’il doit accéder aux ressources fournies par une ou plusieurs fonctionnalités, ou les charger. L’exemple effectue cette opération lorsqu’il lui est impossible de continuer tant que la ressource n’est pas installée.
  • L’installation passive est lancée lorsque l’exemple n’effectue pas de tâche critique, par exemple lorsque le joueur se trouve dans un menu ou regarde un extrait. Lorsque c’est le cas, le thread de travail vérifie si une fonctionnalité de l’exemple est toujours marquée publiée. S’il en trouve une, il appelle le programme d’installation pour installer cette fonctionnalité. Ce processus se répète jusqu’à ce que chaque fonctionnalité de l’exemple soit installée. Essentiellement, l’installation passive utilise des cycles de processeur supplémentaires pour effectuer l’installation en arrière-plan lorsque c’est le moins intrusif pour l’exemple principal.
  • Aucune installation ne se produit lorsque le joueur est activement engagé dans le jeu. Cela empêche une chute de la fréquence d’images qui perturberait l’expérience utilisateur.

Dans l’exemple, une classe CMsiUtil est définie pour gérer toutes les tâches liées à l’installation. Essentiellement, CMsiUtil utilise un thread de travail qui appelle le programme d’installation pour installer les fonctionnalités de l’exemple dans une boucle. La classe a deux files d’attente qui stockent les demandes d’installation : une file d’attente de priorité élevée pour l’installation active et une file d’attente de basse priorité pour l’installation passive. Pendant l’initialisation, la classe énumère toutes les fonctionnalités du produit et les ajoute à la file d’attente d’installation passive. L’ensemble du produit étant mis en file d’attente de cette façon, l’ensemble du produit sera finalement installé si l’exemple dispose de suffisamment de cycles de processeur libres.

Lorsque l’exemple doit demander une installation active, l’exemple peut appeler CMsiUtil::UseFeatureSet() et transmettre le nom de la fonctionnalité de niveau supérieur. UseFeatureSet() met en file la fonctionnalité demandée et toutes ses sous-fonctionnalités dans la file d’attente d’installation active, afin que le thread de travail puisse les installer.

Lors de l’exécution d’une demande d’installation, le thread de travail vérifie la file d’attente d’installation active ainsi que la file d’attente d’installation passive pour voir si l’une d’entre elles contient des demandes supplémentaires. Chaque fois que le thread trouve une demande, il appelle l’API du programme d’installation pour effectuer l’installation effective. Une fois les deux files d’attente vides, le thread de travail est mis en veille avec un appel à WaitForSingleObject. L’ensemble du produit étant placé dans la file d’attente d’installation passive pendant l’initialisation, une file d’attente vide implique que l’ensemble du produit a été installé.

L’exemple appelle CMsiUtil::EnablePassiveInstall() pour activer ou désactiver l’installation passive. EnablePassiveInstall(true) incrémente le nombre d’activations pour l’installation passive, et EnablePassiveInstall(false) le décrémente. Si le nombre d’activations est supérieur à 0, la classe traite la file d’attente d’installation passive. L’exemple autorise l’installation passive quand l’une des opérations suivantes est vraie :

  • L’utilisateur affiche la séquence d’introduction initiale.
  • L’utilisateur navigue dans le menu de l’exemple.
  • L’utilisateur affiche les statistiques à la fin d’un niveau.
  • L’exemple d’application perd son focus et passe à l’arrière-plan.

Les méthodes de CMsiUtil sont listées ci-dessous :

Méthode Description
AbortAllRequests Provoque l’abandon de l’installation en cours et vide la file d’attente de demande d’installation active.
AbortCurrentRequest Provoque l’abandon de l’installation en cours. Le thread de travail traite ensuite la demande suivante dans la file d’attente, le cas échéant.
EnablePassiveInstall Incrémente ou décrémente le nombre d’activation d’installation passive. L’exemple utilise cet appel pour contrôler quand l’installation passive peut et ne peut pas se produire.
GetCurrentFeatureName Retourne le nom de la fonctionnalité en cours d’installation.
GetFeatureProgress Retourne la position de cycle actuelle de la fonctionnalité en cours d’installation.
GetFeatureProgressMax Retourne le nombre maximal de cycles de progression pour la fonctionnalité en cours d’installation.
Obtenir la dernière erreur Utilisez cette méthode pour récupérer le code de retour depuis la demande d’installation précédente.
GetPassiveProgress Retourne la position de cycle de la barre de progression pour l’installation passive.
GetPassiveProgressMax Retourne la position de cycle actuelle et le nombre maximal de cycles pour l’installation passive. Ensemble, l’exemple peut les utiliser pour montrer la progression globale de l’installation passive.
GetProgress Retourne la position de cycle de la barre de progression pour l’installation du jeu de fonctionnalités actif. Ceci est utilisé lorsque l’exemple affiche la barre de progression de l’installation. Windows Installer fournissant uniquement des informations de progression pour la seule fonctionnalité installée, la méthode divise la barre de progression entre les fonctionnalités demandées afin que l’utilisateur voit toujours l’installation entière comme une seule tâche.
GetProgressMax Retourne le nombre maximal de cycles de barre de progression pour l’installation du jeu de fonctionnalités actif. Ceci est utilisé lorsque l’exemple affiche la barre de progression de l’installation.
Initialize Initialise la classe avec l’identificateur global unique (GUID) du produit. Cette méthode énumère également chaque fonctionnalité de l’application qui a été publiée mais pas encore installée, et la place dans la file d’attente d’installation passive pour configurer l’installation passive.
IsInstallInProgress Utilisez cette méthode pour déterminer si une installation active est en cours de traitement.
UseFeature Méthode privée appelée par UseFeatureSet. Vérifie si une fonctionnalité est installée. Si la fonctionnalité demandée est installée, la méthode retourne. Si la fonctionnalité n’est pas encore installée (publiée), la méthode met en file d’attente une nouvelle demande d’installation active pour le thread de travail, puis retourne. Poignée d’évènement facultatif qui sera signalé lorsque l’installation demandée sera terminée.
UseFeatureSet Appelé par l’exemple lorsqu’il doit accéder aux composants fournis par une fonctionnalité particulière ou l’une de ses sous-fonctionnalités. La méthode énumère toutes les fonctionnalités de l’exemple et appelle UseFeature() pour les sous-fonctionnalités de la fonctionnalité racine spécifiée. L’exemple peut transmettre une poignée d’évènement qui sera signalé lorsque l’ensemble de fonctionnalités sera installé. Les fonctionnalités installées en tant qu’ensemble étant toutes installées, la poignée est spécifiée pour la dernière fonctionnalité mise en file d’attente par UseFeature() au lieu de chacune des fonctionnalités, afin que l’exemple soit averti une fois que toutes les fonctionnalités demandées sont installées.
UseProduct Met en file d’attente une demande d’installation active pour que le thread de travail appelle le programme d’installation pour effectuer une installation complète du produit. Poignée d’évènement facultatif qui sera signalé lorsque l’installation demandée sera terminée.

 

Limitation

La version actuelle du programme d’installation n’est pas conçue pour un accès simultané par plusieurs threads. Par conséquent, lorsque le thread de travail appelle le programme d’installation, le thread principal ne doit pas appeler le programme d’installation. Un exemple de cette limitation se produit dans l’exemple lorsque le thread principal demande une fonctionnalité, puis redemande la même fonctionnalité avant que le thread de travail ne termine l’installation. La deuxième demande appelle MsiQueryFeatureState() pour déterminer si la fonctionnalité demandée est déjà installée, car le programme d’installation peut parfois indiquer que la fonctionnalité est entièrement installée alors que le thread de travail copie toujours les fichiers.

Heureusement, il y a un moyen facile de contourner ce problème. CMsiUtil vérifie si une fonctionnalité est installée par le thread de travail ou pas avant d’appeler des fonctions comme MsiQueryFeatureState() ou MsiUseFeature() pour demander l’état d’installation de la fonctionnalité en question. Sachez que cette limitation peut également devenir un problème ailleurs.

L’application de correctifs peut affecter le fonctionnement de l’installation à la demande sur l’ordinateur d’un utilisateur final. L’application d’un correctif qui contient uniquement les données qui ont changé par rapport à la version précédente peut nécessiter l’installation de la version précédente du fichier mis à jour afin d’appliquer le delta. Dans ce cas, le correctif doit demander au programme d’installation d’installer les fonctionnalités publiées affectées avant d’appliquer le correctif au jeu.

L’exemple est installé en lançant InstallOnDemand.msi, car il suppose que Windows Installer est présent sur l’ordinateur. Si le programme d’installation est absent, les fichiers .msi ne sont pas reconnus et leur lancement ne fonctionne pas. Pour résoudre ce problème, une application doit utiliser un programme d’installation pour effectuer la tâche. Ce programme doit d’abord vérifier si le programme d’installation est présent et, si c’est le cas, sa version. Si la version ne répond pas aux exigences de l’application, le programme d’installation doit installer Windows Installer, puis lancer le fichier .msi. Ce processus est appelé amorçage. Les applications nomment généralement leur programme d’installation d’amorçage Setup.exe. L’exemple ne gère pas l’amorçage. Toutefois, vous trouverez des détails complets sur l’amorçage dans Windows Installer.

Les développeurs doivent également être attentifs à la taille de chacune des fonctionnalités dans leurs jeux. En cas d’annulation d’une installation en cours, le programme d’installation restaure l’ordinateur à son état avant l’installation. Cela signifie que l’installation de la fonctionnalité est entièrement annulée et qu’il n’y a pas d’installation partielle des fonctionnalités. Une fonctionnalité volumineuse nécessite un temps d’installation plus long, ce qui augmente la probabilité que l’installation soit interrompue et annulée ou que l’installation interfère avec l’application principale. Par exemple, l’installation passive est activée lorsque l’utilisateur affiche le menu du jeu en cours de jeu. Si une fonctionnalité est installée et que l’utilisateur recommence à jouer, le jeu peut effectuer l’une des deux opérations suivantes : il peut laisser l’installation passive se terminer ou l’annuler. Une fonctionnalité volumineuse s’adapterait mal à l’un ou l’autre modèle. Si le jeu permet l’installation étendue, celle-ci peut gêner le niveau de performance du rendu du jeu pendant un long moment. À l’inverse, si le jeu annule l’installation, l’utilisateur doit rester dans le menu pendant longtemps avant de pouvoir revenir au jeu. Les développeurs doivent trouver une taille de fonctionnalité équilibrée, qui fonctionne le mieux pour leurs jeux individuels.