Aller au contenu


Optimisons Nos Scripts !


  • Veuillez vous connecter pour répondre
10 réponses à ce sujet

#1 Shadow she-wolf

Shadow she-wolf

    Le katana de la GBT


Posté 25 juin 2009 - 12:39

Bonjour,

Je vais vous parler ici de l'optimisation des scripts. Tout d'abord, pourquoi faire ? Est-ce bien utile ?
Et bien, le gain de performance sera mineur en cours du jeu, les problèmes de fluidité venant principalement de la carte graphique, par contre, cela permet d'éviter de trop ralentir les phases de chargement quand on change de cellules, en particulier avec les blocs OnLoad.
Puis, je ne dois pas être la seule maniaque du forum... ;)

(ceci est une synthèse de ce que j'ai pu trouver dans les doc anglaises)
(certaines de ces astuces peuvent être utiles pour morrowind (surtout, car il dépend bien plus du processeur qu'oblivion) et fallout)

(c'est une ébauche, donc toute aide est la bienvenue)


Les tests et les opérateurs.

Voici un script du jeu de base:
	if timer <= 0 && getstage MQ15 == 58 && OrtheRef.getdead == 0
		   set timer to 5
		   sayTo player MQ15EldamilWarning
	   endif
   
	   if timer <= 0 && getstage MQ15 == 66 && getdistance player < 1000
		   if suicide == 0
			   set timer to sayTo player MQ15EldamilWarning
			   set suicide to 1
		   endif
	   endif
   
	   if suicide == 1 && getstage MQ15 == 66 && timer <= 0
		   setstage MQ15 67
	   endif

Nous pouvons voir qu'il y a trois tests if et que pour chacun de ceux-ci a deux opérateurs logiques &&.
Il faut savoir qu'en l'état, le jeu va tester les trois if, et que pour chaque if, il va tester les trois conditions à chaque fois, même si la première du if est fausse, donc au total, par frame, le jeu va tester neuf conditions.
Or, en disposant les if en cascade, si la première condition est fausse, le jeu ne testera pas les autres conditions qui suivent.
En disposant le script comme ceci:
	if timer <= 0
		   if getstage MQ15 == 58 
			   if OrtheRef.getdead == 0
				   set timer to 5
				   sayTo player MQ15EldamilWarning
			   endif
		   elseif getstage MQ15 == 66 
			   if getdistance player < 1000
				   if suicide == 0
					   set timer to sayTo player MQ15EldamilWarning
					   set suicide to 1
				   elseif suicide == 1
					   setstage MQ15 67
				   endif
			   endif
		   endif
	   endif
Le jeu, ne fera tout d'abord que le test if timer <= 0,si ce dernier est vrai, il va continuer, mais si il est faux, il n'ira pas plus loin, dans cette dernière situation, on économisera 8 tests par frame.
Toutefois, dans le cas où la première condition est souvent vérifiée, l'exécution n'en sera que plus lente si on split en deux tests. Il faut donc placer en premier les variables les moins souvent vraies.
Et bien entendu cette astuce n'est réellement utile que dans les blocs GameMode.


Concernant les opérateurs de comparaison (==, !=, <=...).
Moins le jeu en a, mieux il se porte en terme de réactivité, concrètement, comment utiliser ce fait ?
Lorsqu'une variable est de type booléenne, c'est à dire qu'elle n'a que deux états logiques, dont l'un est 0.
En effet, écrire:
if GetDead
Revient à écrire:
if GetDead != 0

Donc si GetDead prend la valeur de 1 ou encore, soyons fou, 63 ou 0.5, le test sera considéré comme vrai, et si elle a pour valeur 0, le test sera considéré comme faux.
Il en va de même, préférez les tests de type else quand c'est possible, puisqu'il n'y a pas d'opérateur possible avec ce dernier.
Petit exemple à partir d'un script commun dans ce jeu:
;script normal
if next == 1 && timer <=0
	 set next to 0
	 myParent.activate mySelf 1
endif
		 
if timer > 0
	set timer to timer - getSecondsPassed
endif
		 
		   
		 
;script optimisé
		 
		   
if timer > 0
	set timer to timer - getSecondsPassed
else						;>0 étant le complément de <=0, un else fait parfaitement l'affaire
	if next				;disparition de l'opérateur ==
		set next to 0
		myParent.activate mySelf 1
	endif
endif

Les Return.

Cette astuce nous vient directement de morrowind, et elle fonctionne sur oblivion (et fallout je suppose du coup...).
Quand on a des résultats très lourds, il peut être avantageux d'utiliser la fonction return, en effet, même si le test if est faux, le jeu peut lire son résultat, ce qui alourdit inutilement le temps processeur...
Petit exemple:
; non-optimisé
	   
   begin GameMode
	  if test
		 (un résultat très très lourd)
	  endif
   end
   
; optimisé
   
   begin GameMode
	  if test == 0; négation du test précédent
		 RETURN
	  endif  
	  (un résultat très très lourd)
   end
Dans la seconde situation, le moteur de script lisant les scripts de haut en bas, si le test == 0 est vrai, il va tomber sur un return qui lui dit de recommencer la lecture du script depuis le début, et donc tout ce qui est après n'est pas lu.
Il faut donc utiliser ceci en tout fin de script forcément, à moins qu'il ne soit construit de manière ordonnée.


Ce qui est gourmant en temps processeur:

La première chose qu'il faut faire, c'est éviter au maximum l'utilisation des blocs GameMode, car ceux-ci sont exécutés à chaque frame, cependant que les blocs OnLoad, eux, ne fonctionnent que pendant la période de chargement et donc influent sur celle-ci.
Voir la liste des blocs disponibles.

Même si oblivion dépend beaucoup moins du processeur que morrowind, certaines choses sont à éviter au possible pour éviter que le processeur ne souffre de trop.

Tout d'abord, quatre fonctions de scripts ont été classées comme étant très gourmandes:
GetNumItems (OBSE)
GetInventoryObject (OBSE)
GetFPS (OBSE)
GetDistance

Ces fonctions posent problèmes principalement si elles sont exécutées souvent, par exemple dans un bloc GameMode.

Evitez autant que possible les Low level Processing en cochant la case No Low Level Processing pour les acteurs.
Low level Processing indique que l'IA de l'acteur fonctionnera même si il n'est pas à proximité du joueur, tandis qu'avec No Low Level Processing, l'IA ne fonctionnera qu'a proximité du joueur, ce qui soulagera le processeur.
Toujours avec l'IA, celle-ci peut être "saturée" si il y a trop de "script IA avancés" autour du joueur, ce qui peut faire buguer des acteurs.

#2 Kafou

Kafou

    Le canari a bouffé le rominet !


Posté 25 juin 2009 - 16:14

Voir le messageShadow she-wolf, le 25.06.2009 à 13:38, dit :

pour chaque if, il va tester les trois conditions à chaque fois, même si la première du if est fausse
Si c'est vrai, ils sont vraiment cons chez Beth ;)

Par contre je préciserai quand même : dans le cas où la première condition est souvent vérifiée, l'exécution n'en sera que plus lente si on split en deux tests. A moins d'une implémentation complètement absurde, faire deux tests est plus coûteux que de n'en faire qu'un. Tout dépend quel est le résultat le plus courant de la première condition.

Citation

Concernant les opérateurs de comparaison (==, !=, <=...).
Moins le jeu en a, mieux il se porte en terme de réactivité, concrètement, comment utiliser ce fait ?
Lorsqu'une variable est de type booléenne, c'est à dire qu'elle n'a que deux états logiques, dont l'un est 0.
En effet, écrire:
if GetDead
Revient à écrire:
if GetDead != 0

Donc si GetDead prend la valeur de 1 ou encore, soyons fou, 63 ou 0.5, le test sera considéré comme vrai, et si elle a pour valeur 0, le test sera considéré comme faux.
Si c'est vrai que les deux lignes ne sont pas strictement identiques en termes de vitesse d'exécution, ils sont vraiment ultra méga cons chez Beth :mrgreen:

Citation

Dans la seconde situation, le moteur de script lisant les scripts de haut en bas, si le test == 0 est vrai, il va tomber sur un return qui lui dit de recommencer la lecture du script depuis le début, et donc tout ce qui est après n'est pas lu.
Il faut donc utiliser ceci en tout fin de script forcément, à moins qu'il ne soit construit de manière ordonnée.
Je précise que return sert aussi à zapper sciemment le reste du script quand on sait qu'il ne faut pas (ou qu'il n'y a pas besoin) de l'exécuter. Au-delà d'un souci de performances ça a son utilité, afin d'éviter d'imbriquer 50 conditions (ce qui, du moins dans Morrowind, n'est pas possible).
You look like you need a monkey!

Attention : perfectionniste paresseux.

#3 Shadow she-wolf

Shadow she-wolf

    Le katana de la GBT


Posté 25 juin 2009 - 20:53

Voir le messageKafou, le 25.06.2009 à 17:13, dit :

Si c'est vrai, ils sont vraiment cons chez Beth :P
Si c'est vrai que les deux lignes ne sont pas strictement identiques en termes de vitesse d'exécution, ils sont vraiment ultra méga cons chez Beth :D
Et bien, je précise juste, je n'ai écrit sur le premier sujet, que ce qui me semble logique, et non toutes les astuces.
Sachant que tout cela vient du wiki du construction set anglais, qu'ils ont des outilspour tester tout cela et que ces astuces sont connues depuis plusieurs années par la communauté anglophone qui est, que je sache, très performante.
Donc oui, ils sont vraiment cons chez Beth'. :?

Pour le coup du: il est plus rapide de ne rien écrire plutôt qu'écrire !=0 (ou >0 qui revient au même si les valeurs sont toujours posivites ou nulles), c'est possible si le calcul se fait à un plus bas niveau dans le premier cas que dans le second, après tout le premier peut être directement en "hard" tandis que le second est compilé.
Puis même, dans tous les cas, ça optimise notre temps d'écriture. :P



Mais niveau connerie, il y a encore plus fort, mais vraiment beaucoup plus fort !
Ceci:
begin GameMode
	 if fQuestDelayTime
	   set fQuestDelayTime to .01
	 endif
   end
Serait plus rapide à executer que:
begin GameMode
	   set fQuestDelayTime to .01
   end

On ne peut faire mieux. :)
Tu peux comprendre ma perplexité et le fait que je ne l'ai pas mentionné au-dessus...


Et, je prend note sur le premier sujet pour l'utilisation des tests en cascades qui n'est pas toujours plus efficace.

#4 Kafou

Kafou

    Le canari a bouffé le rominet !


Posté 25 juin 2009 - 21:07

Voir le messageShadow she-wolf, le 25.06.2009 à 21:52, dit :

Et, je prend note sur le premier sujet pour l'utilisation des tests en cascades qui n'est pas toujours plus efficace.
A vérifier, vues les aberrations du système de script sur les autres points...
You look like you need a monkey!

Attention : perfectionniste paresseux.

#5 Shadow she-wolf

Shadow she-wolf

    Le katana de la GBT


Posté 26 juin 2009 - 10:00

Voir le messageKafou, le 25.06.2009 à 22:06, dit :

A vérifier, vues les aberrations du système de script sur les autres points...

Je viens de vérifier, c'est en fait, un peu bidon leur machin.

J'ai essayé la différence entre GetDead et GetDead == 1
Ainsi que la diférence entre un if avec deux test ou deux if avec un unique test.

Les résultats changent à chaque fois, parfois l'un est plus rapide, parfois c'est l'autre...

#6 Ancestral Ghost

Ancestral Ghost

    Chasseur furtif


Posté 26 juin 2009 - 10:17

Moi qui pensais que mes scripts étaient à peu prêt optimisés, je me rend compte que ce n'est pas le cas et me voila bien surprit : En fait il faut être illogique pour optimiser ses scripts chez Beth.

#7 Kafou

Kafou

    Le canari a bouffé le rominet !


Posté 26 juin 2009 - 10:25

En même temps, c'est pas comme si ça servait à grand chose de se prendre la tête pour gagner 0.01 FPS...

L'optimisation de script, c'est utile quand ton script il tourne 500 fois par frame, c'est tout.
You look like you need a monkey!

Attention : perfectionniste paresseux.

#8 Riv Daan

Riv Daan

Posté 07 juillet 2009 - 16:51

Salut, pour les if, c'est vrai que dans la logique, les faires en cascade devraient étre plus rapide, mais bon c'est téllement petit pour un test de variable, que c'est presque invisible.
Dire que beth est con, c'est un peu poussé, car faire deux test sur la méme ligne ne fond pas grand chose, on évite juste des indentations de fou.
Aprés le principe marche vraiment si ya 20 test sur la méme ligne, pas pour 2.
On sera dans la programmation pur, tous est optimisation, mais la c'est que du script, si on met 2 condition sur la même ligne, ça va pas faire grand chose.

Je pense que l'optimisation dans ce jeu serai plus sur les variables, car j'ai vu pas mal de mec qui fond des script avec une 20aine de variable qui servent a 2 ou 3 truck.

#9 beeratwork

beeratwork

Posté 07 juillet 2009 - 19:18

Les scripts sur oblivion, c'est nul, y a des tas de fonction qui ont du être rajoutée par obse, car on ne sait pas faire des choses "normale" à la base dans le jeu...

Je suis d'accord avec Riv Daan, l'optimisation peut se faire sur les variables...
Puis dans les scripts, le step by step fonctionne très bien.

Y a quelque cas où ça foire, par exemple lorsque dans un sort on met des scripeffectfinish avec avant un scripteffectupdate...

Mais je maintiens, c'est un exploit de faire un script qui fait quelque chose de convenable, car ce n'est pas normal. C'est normal quand ça foire. C'est pas normal ça.

#10 Kafou

Kafou

    Le canari a bouffé le rominet !


Posté 07 juillet 2009 - 19:23

Optimiser le nombre de variables ?

Une variable c'est quatre octets en mémoire... 10000 scripts avec 10 variables chacun ça fait, attention, 400Ko de mémoire ! C'est sûr que ça va mettre nos bécannes à genou :mrgreen:
You look like you need a monkey!

Attention : perfectionniste paresseux.

#11 Riv Daan

Riv Daan

Posté 07 juillet 2009 - 22:25

Héhé, c'est sur, mais c'est vous qui voulez optimisé a mort lol.
Pi de toute façon, vu la taille des scripts, ya pas dix mille ligne nom plus.
Faut pas codé comme des porcs pi ça suffit pour l'optimisation.
Beaucoup de gars dfont des gamemode qui font presque rien et qui pourrait étre fait en onactivate ou autre.




0 utilisateur(s) li(sen)t ce sujet

0 membre(s), 0 invité(s), 0 utilisateur(s) anonyme(s)