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
- Prise en charge des correctifs
- Exemple du kit de développement logiciel (SDK) InstallOnDemand
- Fonctionnalités et composants de l’exemple
- Installation
- Limitation
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
- Utilisez le lien Install Project dans le navigateur exemple pour copier les fichiers de l’exemple dans un dossier.
- Double-cliquez sur InstallOnDemand.msi pour installer l’exemple.
- Sélectionnez Installation classique.
- 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.