Optimisation maximale sous Gamemaker
Sommaire1-Optimisation de la ram
2-Optimisation du processeur
3-Optimisation du rendu
4-Optimisations diverses
Je vais vous parler ici d'optimisation sous Gamemaker.
Les techniques qui existent en général, comment comparer deux codes, etc.
Sous GM, vous pourrez optimiser votre jeu de deux façon.
-Ne pas charger trop de ressources pour optimiser la mémoire et utiliser moins de ram.
-Faire des calculs plus optimisés pour utiliser moins de processeur.
![Exclamation](https://2img.net/i/fa/i/smiles/icon_exclaim.gif)
Les tests sont faits sous GM6 et GM8, et les résultats ne sont pas encore super précis
1-Optimisation de la ramPour optimiser la mémoire, la première chose a savoir est :
Combien prennent une variable, une image en mémoire ?VariablesSous GM les variables sont théoriquement des nombres flottants a double précision. L'équivalent du type double en C++.
Ils devraient donc prendre 8 octets en mémoire mais nous allons voir que c'est encore pire x_x
Et ils perdent en précision avec des calculs ou les nombres sont trop grands.
Voici un tableau récapitulatif de la mémoire utilisée par des variables sous GM :
Variable | Mémoire utilisée théoriquement | Mémoire utilisée | Rapport |
n | 8 octets | - | - |
n[1024] | 8ko | 32ko | 4 |
n[32 000] | 250ko | 770ko | 3 |
10 * n[32 000] | 2500ko | 7668ko | 3 |
On en déduit donc que les variables sous GM prennent au final 24 octets, tout du moins avec un tableau a une dimension.
C'est vraiment beaucoup, et donc il faudra faire attention a l'utilisation abusive de variables sous GM.
Pour ceux qui voudraient vérifier par eux même voici la démarche a suivre :
- Spoiler:
1-Créez un nouveau projet GM
2-Créez un objet et instanciez le dans une room
3-Mettez le code suivant dans l'event "Press <Space>" :
- Code:
-
for(i=0; i<32000; i+=1) {
n1[i] = i
n2[i] = i
n3[i] = i
n4[i] = i
n5[i] = i
n6[i] = i
n7[i] = i
n8[i] = i
n9[i] = i
na[i] = i
}
4-Lancez le jeu
5-Ouvrez le gestionnaire des taches et regardez la ram utilisée par game.exe
6-Appuyez sur espace, et comparez la ram avec la précédente.
ImagesLes images sous GM sont en 32bits. Donc 4octets par pixel.
Théoriquement une image devrais prendre 4*largeur*hauteur octets en mémoire vidéo.
Hors il s'avère que :
-Les images sont aussi stockées dans la ram, pour les tests de collision pixel perfect, et les fonctions du style sprite_set_alpha_from_sprite
-Les images prennent beaucoup plus de place en ram que la valeur théorique ci dessus
-Les images prennent aussi de la ram en mémoire vidéo. Par contre je n'ai pas pu faire de tests mais elles devraient être stockées en 32bits.
(je n'ai pas trouvé comment voir la ram vidéo)
Voici un tableau récapitulatif :
Largeur | Hauteur | Poids Théorique (Ko) | Poids Réel (Ko) |
640 | 480 | 1200 | 2500 |
1000 | 1000 | 3900 | 8700 |
2000 | 2000 | 15625 | 35240 |
1024 | 1024 | 4096 | 9100 |
Il faut savoir aussi qu'un sprite contenant plus de sous images prendras un peu plus de ram, mais c'est négligeable.
Une image prend donc en mémoire :
Mémoire utilisée = Largeur * Hauteur * 8 octetsIls est donc vivement conseillé de ne charger que le strict nécessaire pendant le jeu, si vous utilisez des sprites ou background assez grands.
1-Optimisation du processeurIci nous allons voir comment optimiser la partie code.
Le GML étant un langage interprété, de petits changements au niveau du code peuvent entrainer des changements assez conséquents.
Ce qu'il faut savoir, c'est que l'interpréteur :
-Analyse le code pendant l’exécution. Donc plus une expression est longue plus elle seras longue a analyser.
-Ne simplifie pas les opérations complexes, ni même les stupides.
La première chose a savoir, c'est qu'il est toujours préférable d'utiliser du code compilé, car il est énormément plus rapide.
Ainsi utiliser la fonction sqrt de GM (code compilé) seras énormément plus rapide que de créer votre propre fonction sqrt en GML.
Pour des applications qui demandent des calculs performants (par exemple collisions 3d, moteur physique) il seras toujours préférable
d'utiliser des dll.
Maintenant, comment savoir si une expression va être plus longue a exécuter qu'une autre ? Comment optimiser un morceau de code ?
Et bien pour cela il nous suffit de calculer le temps d’exécution, et de comparer.
Pour calculer le temps d’exécution d'un bout de code, il suffit de :
1- Garder current_time en mémoire
2- Exécuter le code beaucoup de fois, avec une loop for
3- Comparer avec le current_time actuel
Voici le script pour comparer le temps d’exécution de 2 bouts de code :
- Code:
-
ts = current_time
for(i=0; i<500000; i+=1)
{
<code1>
}
t1 = current_time - ts
ts = current_time
for(i=0; i<500000; i+=1)
{
<code2>
}
t2 = current_time - ts
show_error("t1 = " + string(t1) + " - t2 = " + string(t2), 0)
Nous pouvons maintenant commencer a voir ce qui gaspille des performances dans un code gml.
a) Les appels de fonction
Voici les performances des fonctions mathématiques dans une loop for de 500000 itérations :
Fonction | Temp (ms) |
Code vide | 312 |
Fonction gml vide | 2000 |
random | 672 |
choose | 750 |
abs | 672 |
sign | 656 |
round | 672 |
floor | 688 |
ceil | 703 |
frac | 672 |
sqrt | 671 |
power | 719 |
exp | 688 |
ln | 687 |
log2 | 719 |
log10 | 703 |
logn | 766 |
sin | 687 |
cos | 688 |
tan | 687 |
arcsin | 703 |
arccos | 688 |
arctan | 703 |
arctan2 | 750 |
degtorad | 672 |
radtodeg | 687 |
min | 735 |
max | 750 |
min | 703 |
median | 734 |
point_distance | 766 |
point_direction | 828 |
lengthdir_x | 750 |
lengthdir_y | 766 |
is_real | 656 |
is_string | 672 |