Orcwar RTS
Re: RTS
Excellente cette démo, qui est déjà très tactique.
Re: RTS
Merci pour cette vidéo, je vais regarder ce soir en détail.
Dans un RTS on a besoin de connaitre si un adversaire est assez proche pour lui tirer dessus ou pour l'attaquer.
Pour ça il y a 2 solutions à mon sens
RayCast et SphereCast
J'avais utilisé SphereCast pour faire cela, ce qui fonctionne très bien avec peu d'objets et en limitant le nombre de SphereCast par seconde.
J'ai ensuite utilisé RayCast, en faisant tourner le rayon petit a petit soit en l'incrémentant, soit avec un random, pas mieux au niveaux perfs pour un grand nombre d'objet.
A savoir qu'uniquement un seul Thread est utilisé par Unity, donc en effet niveau CPU on l'exploite pas à fond.
J'ai utilisé des Coroutines et des appels dans Update et FixedUpdate.
Tableau perso d'objet
J'ai ensuite créé une méthode qui récupère tous les objets 10 fois par seconde et qui les range dans 2 tableaux(joeur1,joeur2), et au lieu d'appeler RayCast , j'appel une méthode via un Thread qui va lire tout le tableau pour trouver l'adversaire le plus proche.
Le gain de performance est spectaculaire, je suis passé de 33img/s a 48img/s.
Le problème est que chaque objet lance son propre Thread, et ce n'est pas très stable.
Apres 8H de développement, J'ai créé une Class static pour gérer tout ça dans un seul Thread.
J'ai encore gagné un peu en perf, avec 450 unités je suis maintenant en dessus des 50img/s en mode défense(detection ennemies), et surtout en fiabilité, plus aucun problème de saccade.
A savoir que Unity ont aussi interdit les accès à leur objets par un autre Thread que le leur, pour ne pas rendre le moteur instable, ce qui complexifie mon code car je dois copié le contenu des objets au lieu de juste y accéder.
Dans un RTS on a besoin de connaitre si un adversaire est assez proche pour lui tirer dessus ou pour l'attaquer.
Pour ça il y a 2 solutions à mon sens
RayCast et SphereCast
J'avais utilisé SphereCast pour faire cela, ce qui fonctionne très bien avec peu d'objets et en limitant le nombre de SphereCast par seconde.
J'ai ensuite utilisé RayCast, en faisant tourner le rayon petit a petit soit en l'incrémentant, soit avec un random, pas mieux au niveaux perfs pour un grand nombre d'objet.
A savoir qu'uniquement un seul Thread est utilisé par Unity, donc en effet niveau CPU on l'exploite pas à fond.
J'ai utilisé des Coroutines et des appels dans Update et FixedUpdate.
Tableau perso d'objet
J'ai ensuite créé une méthode qui récupère tous les objets 10 fois par seconde et qui les range dans 2 tableaux(joeur1,joeur2), et au lieu d'appeler RayCast , j'appel une méthode via un Thread qui va lire tout le tableau pour trouver l'adversaire le plus proche.
Le gain de performance est spectaculaire, je suis passé de 33img/s a 48img/s.
Le problème est que chaque objet lance son propre Thread, et ce n'est pas très stable.
Apres 8H de développement, J'ai créé une Class static pour gérer tout ça dans un seul Thread.
J'ai encore gagné un peu en perf, avec 450 unités je suis maintenant en dessus des 50img/s en mode défense(detection ennemies), et surtout en fiabilité, plus aucun problème de saccade.
A savoir que Unity ont aussi interdit les accès à leur objets par un autre Thread que le leur, pour ne pas rendre le moteur instable, ce qui complexifie mon code car je dois copié le contenu des objets au lieu de juste y accéder.
Moon RTS
Re: RTS
Salut,
Si tu veux un réel gain de performances "spectaculaire" (passer de 33 à 48 img seconde c'est rien du tout dans ce cas), au lieu de traverser tout le tableau pour trouver les adversaires les plus proches, utilises un quatree / un octree, ou une simple voxelisation de l'espace, afin de répartir tes entités dedans et de ne faire une boucle de proximité que sur les entités se trouvant proches les une des autres.
Là tu vas drastiquement réduire les boucles
Tu peux aussi faire un tour ici : http://jitter-physics.com/wordpress/?p=31
Pour le coup des limitations de threads, tu peux essayer de passer par un tableau d'index (donc des int) représentant les positions de tes objets dans le tableau d'origine
Ainsi tu évites de faire des copies pour rien.
Mais peux-tu préciser dans quel cas tu as ce souci plus précisément ?
Si tu veux un réel gain de performances "spectaculaire" (passer de 33 à 48 img seconde c'est rien du tout dans ce cas), au lieu de traverser tout le tableau pour trouver les adversaires les plus proches, utilises un quatree / un octree, ou une simple voxelisation de l'espace, afin de répartir tes entités dedans et de ne faire une boucle de proximité que sur les entités se trouvant proches les une des autres.
Là tu vas drastiquement réduire les boucles
Tu peux aussi faire un tour ici : http://jitter-physics.com/wordpress/?p=31
Pour le coup des limitations de threads, tu peux essayer de passer par un tableau d'index (donc des int) représentant les positions de tes objets dans le tableau d'origine
Ainsi tu évites de faire des copies pour rien.
Mais peux-tu préciser dans quel cas tu as ce souci plus précisément ?
Re: RTS
Merci bien, je vais lire tout ca, j'essaye de comprendre le principe, mais je ne pense pas y gagner grand chose, meme je désactive complément ma recherche de proximité le nombre d'img/s ne monte pas.
C'est au niveau GPU que ca limite maintenant, et aussi les navmeshs qui consomment pas mal.
Mais je ne veux pas faire un RTS avec 5000 unités pour mobile faudrait des écrans de 20 pouces
J'ai compris le principe que tu m'as donné comme liens, je vais quand meme regarder de modifier mon code, et voir si ca ameliore encore un peu mes perfs, mais je n'y crois pas trop.
Je ne fais pas de copie de gameobject ou de transform dans mon Thread, je prends uniquement le nom de l'objet dans lequel il y a un numéro et je le colle dans un objet que je stoque dans une liste.
Petite mise à jour disponible 1800 unités, avec des corrections sur les tirs, les collisions, un super décors fait en 3 minutes
C'est au niveau GPU que ca limite maintenant, et aussi les navmeshs qui consomment pas mal.
Mais je ne veux pas faire un RTS avec 5000 unités pour mobile faudrait des écrans de 20 pouces
J'ai compris le principe que tu m'as donné comme liens, je vais quand meme regarder de modifier mon code, et voir si ca ameliore encore un peu mes perfs, mais je n'y crois pas trop.
Je ne fais pas de copie de gameobject ou de transform dans mon Thread, je prends uniquement le nom de l'objet dans lequel il y a un numéro et je le colle dans un objet que je stoque dans une liste.
Petite mise à jour disponible 1800 unités, avec des corrections sur les tirs, les collisions, un super décors fait en 3 minutes
Moon RTS
Re: RTS
Pourquoi tu colles des string avec des numéros dans un objet puis dans une liste au lieu de directement stocker les numéros dans la liste ?menfou a écrit :Je ne fais pas de copie de gameobject ou de transform dans mon Thread, je prends uniquement le nom de l'objet dans lequel il y a un numéro et je le colle dans un objet que je stoque dans une liste.
Re: RTS
Je ne stock pas de String dans mon objet, je fais un substring du nom des gameobjects (ex toto1234->1234) et je stock uniquement 1234 dans un attribut de ma Class.
Je ne peux pas utiliser l'ID unique Unity, car il n'existe aucune methode Unity permettant de rechercher par ID.
Soit c'est par nom, soit par Tag, completement stupide de la part de Unity
Voila pour les perfs sur iPad1 et iPad Air, sachat que je limite le framerate a 30img/s
http://www.youtube.com/watch?v=QxIAYMwbOaQ
Je ne peux pas utiliser l'ID unique Unity, car il n'existe aucune methode Unity permettant de rechercher par ID.
Soit c'est par nom, soit par Tag, completement stupide de la part de Unity
Voila pour les perfs sur iPad1 et iPad Air, sachat que je limite le framerate a 30img/s
http://www.youtube.com/watch?v=QxIAYMwbOaQ
Moon RTS
Re: RTS
Ok mais pourquoi tu ne stockes pas toutes tes instances de classe dans une liste statique, et ensuite tu ne bosse qu'avec les index des éléments dans cette liste.
Ainsi tu ne jongles qu'avec des int dans tes threads et non plus des classes, ça sera bien plus léger et ne fera plus aucune allocation.
Depuis le thread, du moment que tu n'ajoutes/enlève pas d'éléments à la liste de classes, tu pourras accéder à chaque instances pour modifier leurs propriétés (à partir du moment où tu ne tapes pas sur une même instance à partir de deux threads différents)
Ainsi tu ne jongles qu'avec des int dans tes threads et non plus des classes, ça sera bien plus léger et ne fera plus aucune allocation.
Depuis le thread, du moment que tu n'ajoutes/enlève pas d'éléments à la liste de classes, tu pourras accéder à chaque instances pour modifier leurs propriétés (à partir du moment où tu ne tapes pas sur une même instance à partir de deux threads différents)
Re: RTS
La List est deja static, il n'y a vraiment pas beacucoup a gagner en appliquant une autre methode de gestion de cette liste d'objet.
L'Update ou je fais la construction de la List consomme un temps de 0ms dans le profiler.
Ce qui consomme c'est le Camera.Render, et GUIRepaint en defense.
Dans mon Thread de gestion des distances, je ne fais que lire une liste static de mon objet avec uniquement un Vector3 pour la position , et 2 Int.
Le Thread stock 2 Pools pour gerer les demandeurs et les recepteurs d'information, je n'ai donc aucun blocage dans l'Update ou je demande la position du plus proche car au moment ou je fais ma demande, je recois le resultat precedement calculer.
Je me focalise sur ce qui consomme réellement pour l'instant, mais par soucis de bon développement, je regarderai rapidement comment optimiser ça.
C'est en mode recherche de chemin et attaque ou il y a du boulot encore a produire, si je désactive le navmesh agent lorsqu'il est en mode attaque, l'adversaire passe a travers car il n'a pas de rigidbody.
Si je rajoute un rigidbody, je me retrouve avec des objets qui passent a travers le sol meme en mettant des contraintes sur la translation Y.
Le navmesh est un peu gourmand, mais il n'y a aucun effet étrange de constaté par rapport a rigidbody.
Juste un essai avec 5000 unités
5000unités
On rentre dans un autre monde, je m'aperçois que Unity est limité à 2048 éléments en Batch, ce qui pénalise grandement les performances.
L'Update ou je fais la construction de la List consomme un temps de 0ms dans le profiler.
Ce qui consomme c'est le Camera.Render, et GUIRepaint en defense.
Dans mon Thread de gestion des distances, je ne fais que lire une liste static de mon objet avec uniquement un Vector3 pour la position , et 2 Int.
Le Thread stock 2 Pools pour gerer les demandeurs et les recepteurs d'information, je n'ai donc aucun blocage dans l'Update ou je demande la position du plus proche car au moment ou je fais ma demande, je recois le resultat precedement calculer.
Je me focalise sur ce qui consomme réellement pour l'instant, mais par soucis de bon développement, je regarderai rapidement comment optimiser ça.
C'est en mode recherche de chemin et attaque ou il y a du boulot encore a produire, si je désactive le navmesh agent lorsqu'il est en mode attaque, l'adversaire passe a travers car il n'a pas de rigidbody.
Si je rajoute un rigidbody, je me retrouve avec des objets qui passent a travers le sol meme en mettant des contraintes sur la translation Y.
Le navmesh est un peu gourmand, mais il n'y a aucun effet étrange de constaté par rapport a rigidbody.
Juste un essai avec 5000 unités
5000unités
On rentre dans un autre monde, je m'aperçois que Unity est limité à 2048 éléments en Batch, ce qui pénalise grandement les performances.
Moon RTS