Dans cette partie de la série, nous allons commencer à permettre aux objets d'interagir non seulement physiquement avec le tilemap, mais également avec tout autre objet, en mettant en œuvre un mécanisme de détection de collision entre les objets du jeu..
La démo montre le résultat final de ce tutoriel. Utilisez WASD pour déplacer le personnage. Le bouton du milieu de la souris génère une plate-forme à sens unique, le bouton droit de la souris crée une tuile pleine et la barre d'espace crée un clone de personnage. Les curseurs changent la taille du personnage du joueur. Les objets qui détectent une collision sont rendus semi-transparents.
La démo a été publiée sous Unity 5.4.0f3 et le code source est également compatible avec cette version de Unity..
Avant de parler de tout type de réaction aux collisions, par exemple en empêchant les objets de se traverser, nous devons d'abord savoir si ces objets se chevauchent.
Cela pourrait être une opération très coûteuse si nous vérifions simplement chaque objet par rapport à tous les autres objets du jeu, en fonction du nombre d'objets actifs que le jeu doit actuellement gérer. Donc, pour alléger un peu le pauvre processeur de nos joueurs, nous allons utiliser…
Cela consiste essentiellement à diviser l'espace du jeu en zones plus petites, ce qui nous permet de contrôler les collisions entre des objets appartenant uniquement à la même zone. Cette optimisation est extrêmement nécessaire dans des jeux comme Terraria, où le monde et le nombre d'objets en collision possibles sont énormes et où les objets sont peu placés. Dans les jeux à écran unique, où le nombre d’objets est fortement limité par la taille de l’écran, il n’est souvent pas nécessaire, mais reste utile.
La méthode de partitionnement spatial la plus répandue pour l'espace 2D est l'arborescence quad; vous pouvez trouver sa description dans ce tutoriel. Pour mes jeux, j'utilise une structure plate, ce qui signifie essentiellement que l'espace de jeu est divisé en rectangles d'une certaine taille et que je vérifie les collisions avec des objets résidant dans le même espace rectangulaire..
Il y a une nuance à cela: un objet peut résider dans plus d'un sous-espace à la fois. C'est tout à fait correct, cela signifie simplement que nous devons détecter des objets appartenant à l'une des partitions avec lesquelles notre ancien objet se chevauche..
La base est simple. Nous devons connaître la taille de chaque cellule et un tableau à deux dimensions, dont chaque élément est une liste d'objets résidant dans une zone particulière. Nous devons placer ces données dans la classe Map.
public int mGridAreaWidth = 16; public int mGridAreaHeight = 16; liste publique[,] mObjectsInArea;
Dans notre cas, j’ai décidé d’exprimer la taille de la partition en mosaïques. Chaque partition a donc une taille de 16 par 16 mosaïques..
Pour nos objets, nous voudrons une liste des zones avec lesquelles l’objet se chevauche actuellement, ainsi que son index dans chaque partition. Ajoutons-les à la MovingObject
classe.
liste publiquemAreas = nouvelle liste (); liste publique mIdsInAreas = nouvelle liste ();
Au lieu de deux listes, nous pourrions utiliser un seul dictionnaire, mais malheureusement, la surcharge de performances liée à l’utilisation de conteneurs complexes dans l’itération actuelle de Unity laisse beaucoup à désirer. Nous allons donc nous en tenir aux listes pour la démonstration..
Passons maintenant au calcul du nombre de partitions nécessaires pour couvrir toute la surface de la carte. L'hypothèse est ici qu'aucun objet ne peut flotter en dehors des limites de la carte..
mHorizontalAreasCount = Mathf.CeilToInt ((float) mWidth / (float) mGridAreaWidth); mVerticalAreasCount = Mathf.CeilToInt ((float) mHeight / (float) mGridAreaHeight);
Bien entendu, en fonction de la taille de la carte, les partitions ne doivent pas nécessairement correspondre exactement aux limites de la carte. C’est pourquoi nous utilisons un plafond de valeur calculée pour nous assurer d’avoir au moins assez pour couvrir l’ensemble de la carte..
Commençons les partitions maintenant.
mObjectsInArea = nouvelle liste[mHorizontalAreasCount, mVerticalAreasCount]; pour (var y = 0; y < mVerticalAreasCount; ++y) for (var x = 0; x < mHorizontalAreasCount; ++x) mObjectsInArea[x, y] = new List ();
Rien d’extraordinaire ne se passe ici. Nous nous assurons simplement que chaque cellule dispose d’une liste d’objets prêts à être utilisés..
Il est maintenant temps de créer une fonction qui mettra à jour les zones recouvertes par un objet particulier.
public void UpdateAreas (MovingObject obj)
Tout d’abord, nous devons savoir avec quelle carte l’objet se superpose. Comme nous n’utilisons que des AABB, il suffit de vérifier quelle mosaïque se trouve à chaque coin de l’AABB..
var topLeft = GetMapTileAtPoint (obj.mAABB.center + nouveau vecteur2 (-obj.mAABB.HalfSize.x, obj.mAABB.HalfSizeY)); var topRight = GetMapTileAtPoint (obj.mAABB.center + obj.mAABB.HalfSize); var bottomLeft = GetMapTileAtPoint (obj.mAABB.center - obj.mAABB.HalfSize); var bottomRight = new Vector2i ();
Maintenant, pour obtenir les coordonnées dans l’espace partitionné, il suffit de diviser la position de la mosaïque par la taille de la partition. Nous n'avons pas besoin de calculer la partition du coin inférieur droit pour le moment, car sa coordonnée x sera égale à celle du coin supérieur droit et sa coordonnée y sera égale à celle du coin inférieur gauche..
topLeft.x / = mGridAreaWidth; topLeft.y / = mGridAreaHeight; topRight.x / = mGridAreaWidth; topRight.y / = mGridAreaHeight; bottomLeft.x / = mGridAreaWidth; bottomLeft.y / = mGridAreaHeight; bottomRight.x = topRight.x; bottomRight.y = bottomLeft.y;
Tout cela devrait fonctionner en partant du principe qu'aucun objet ne sera déplacé en dehors des limites de la carte. Sinon, nous aurions besoin d'une vérification supplémentaire ici pour ignorer les objets qui sont hors limites.
Maintenant, il est possible que l’objet réside entièrement dans une seule partition, qu’il réside dans deux ou qu’il occupe l’espace droit où quatre partitions se rencontrent. Ceci est basé sur l'hypothèse qu'aucun objet n'est plus grand que la taille de la partition, auquel cas il pourrait occuper toute la carte et toutes les partitions s'il était suffisamment grand! J'ai fonctionné sous cette hypothèse, c'est pourquoi nous allons gérer cela dans le tutoriel. Les modifications pour autoriser de plus gros objets sont assez triviales, alors je vais les expliquer aussi.
Commençons par vérifier quelles zones le personnage chevauche. Si toutes les coordonnées de partition du coin sont identiques, l'objet n'occupe qu'une seule zone..
if (topLeft.x == topRight.x && topLeft.y == bottomLeft.y) mOverlappingAreas.Add (topLeft);
Si ce n'est pas le cas et que les coordonnées sont les mêmes sur l'axe des x, l'objet chevauche verticalement deux partitions différentes..
if (topLeft.x == topRight.x && topLeft.y == bottomLeft.y) mOverlappingAreas.Add (topLeft); else if (topLeft.x == topRight.x) mOverlappingAreas.Add (topLeft); mOverlappingAreas.Add (bottomLeft);
Si nous prenions en charge des objets plus volumineux que des partitions, il suffirait d'ajouter toutes les partitions du coin supérieur gauche au côté inférieur gauche à l'aide d'une boucle..
La même logique s'applique si seules les coordonnées verticales sont identiques.
if (topLeft.x == topRight.x && topLeft.y == bottomLeft.y) mOverlappingAreas.Add (topLeft); else if (topLeft.x == topRight.x) mOverlappingAreas.Add (topLeft); mOverlappingAreas.Add (bottomLeft); else if (topLeft.y == bottomLeft.y) mOverlappingAreas.Add (topLeft); mOverlappingAreas.Add (topRight);
Enfin, si toutes les coordonnées sont différentes, nous devons ajouter les quatre zones.
if (topLeft.x == topRight.x && topLeft.y == bottomLeft.y) mOverlappingAreas.Add (topLeft); else if (topLeft.x == topRight.x) mOverlappingAreas.Add (topLeft); mOverlappingAreas.Add (bottomLeft); else if (topLeft.y == bottomLeft.y) mOverlappingAreas.Add (topLeft); mOverlappingAreas.Add (topRight); else mOverlappingAreas.Add (topLeft); mOverlappingAreas.Add (bottomLeft); mOverlappingAreas.Add (topRight); mOverlappingAreas.Add (bottomRight);
Avant de poursuivre avec cette fonction, nous devons pouvoir ajouter et supprimer l'objet d'une partition particulière. Créons ces fonctions en commençant par l'ajout.
vide publique AddObjectToArea (Vector2i areaIndex, MovingObject obj) var area = mObjectsInArea [areaIndex.x, areaIndex.y]; // enregistre l'index de l'objet dans la zone obj.mAreas.Add (areaIndex); obj.mIdsInAreas.Add (area.Count); // ajoute l'objet à l'aire area.Add (obj);
Comme vous pouvez le constater, la procédure est très simple: nous ajoutons l'index de la zone à la liste des zones qui se chevauchent, nous ajoutons l'index correspondant à la liste des identifiants de l'objet et, enfin, nous ajoutons l'objet à la partition..
Créons maintenant la fonction de suppression.
espace public supprimé RemoveObjectFromArea (Vector2i areaIndex, int objIndexInArea, MovingObject obj)
Comme vous pouvez le constater, nous allons utiliser les coordonnées de la zone avec laquelle le caractère ne se chevauche plus, son index dans la liste des objets de cette zone et la référence à l'objet que nous devons supprimer..
Pour supprimer l'objet, nous allons l'échanger avec le dernier objet de la liste. Cela nous obligera également à nous assurer que l'index de l'objet pour cette zone particulière est mis à jour à celui de notre objet supprimé. Si nous n'échangions pas l'objet, nous aurions besoin de mettre à jour les index de tous les objets qui suivent celui que nous devons supprimer. Au lieu de cela, nous devons mettre à jour uniquement celui avec lequel nous avons échangé.
Avoir un dictionnaire ici épargnerait beaucoup de tracas, mais la suppression de l'objet d'une zone est une opération nécessaire beaucoup moins souvent que l'itération dans le dictionnaire, qui doit être effectuée chaque image pour chaque objet lorsque nous mettons à jour le chevauchement de l'objet. des zones.
// échange le dernier élément avec celui que nous supprimons var tmp = area [area.Count - 1]; area [area.Count - 1] = obj; area [objIndexInArea] = tmp;
Nous devons maintenant trouver la zone qui nous concerne dans la liste des zones de l’objet échangé et modifier l’index de la liste des ids en index de l’objet supprimé..
var tmpIds = tmp.mIdsInAreas; var tmpAreas = tmp.mAreas; pour (int i = 0; i < tmpAreas.Count; ++i) if (tmpAreas[i] == areaIndex) tmpIds[i] = objIndexInArea; break;
Enfin, nous pouvons supprimer le dernier objet de la partition, qui est maintenant une référence à l’objet que nous devions supprimer..
area.RemoveAt (area.Count - 1);
La fonction entière devrait ressembler à ceci:
annulation publique RemoveObjectFromArea (Vector2i areaIndex, int objIndexInArea, MovingObject obj) var area = mObjectsInArea [areaIndex.x, areaIndex.y]; // échange le dernier élément avec celui que nous supprimons var tmp = area [area.Count - 1]; area [area.Count - 1] = obj; area [objIndexInArea] = tmp; var tmpIds = tmp.mIdsInAreas; var tmpAreas = tmp.mAreas; pour (int i = 0; i < tmpAreas.Count; ++i) if (tmpAreas[i] == areaIndex) tmpIds[i] = objIndexInArea; break; //remove the last item area.RemoveAt(area.Count - 1);
Revenons à la fonction UpdateAreas.
Nous savons quelles zones le caractère recouvre ce cadre, mais le dernier cadre auquel l'objet aurait déjà pu être affecté aux mêmes zones ou à des zones différentes. Commençons par parcourir les anciennes zones et, si l’objet ne les chevauche plus, supprimons-les de ces objets..
zones var = obj.mAreas; var ids = obj.mIdsInAreas; pour (int i = 0; i < areas.Count; ++i) if (!mOverlappingAreas.Contains(areas[i])) RemoveObjectFromArea(areas[i], ids[i], obj); //object no longer has an index in the area areas.RemoveAt(i); ids.RemoveAt(i); --i;
Passons maintenant en revue les nouvelles zones, et si l’objet ne leur a pas encore été affecté, ajoutons-les maintenant..
pour (var i = 0; i < mOverlappingAreas.Count; ++i) var area = mOverlappingAreas[i]; if (!areas.Contains(area)) AddObjectToArea(area, obj);
Enfin, effacez la liste des zones qui se chevauchent afin qu’elle soit prête à traiter le prochain objet..
mOverlappingAreas.Clear ();
C'est tout! La fonction finale devrait ressembler à ceci:
public void UpdateAreas (MovingObject obj) // récupère les zones situées aux coins de l'aabb var topLeft = GetMapTileAtPoint (obj.mAABB.center + new Vector2 (-obj.mAABB.HalfSize.x, obj.mAABB.HalfSizeY)); var topRight = GetMapTileAtPoint (obj.mAABB.center + obj.mAABB.HalfSize); var bottomLeft = GetMapTileAtPoint (obj.mAABB.center - obj.mAABB.HalfSize); var bottomRight = new Vector2i (); topLeft.x / = mGridAreaWidth; topLeft.y / = mGridAreaHeight; topRight.x / = mGridAreaWidth; topRight.y / = mGridAreaHeight; bottomLeft.x / = mGridAreaWidth; bottomLeft.y / = mGridAreaHeight; bottomRight.x = topRight.x; bottomRight.y = bottomLeft.y; // voir combien de zones différentes nous avons si (topLeft.x == topRight.x && topLeft.y == bottomLeft.y) mOverlappingAreas.Add (topLeft); else if (topLeft.x == topRight.x) mOverlappingAreas.Add (topLeft); mOverlappingAreas.Add (bottomLeft); else if (topLeft.y == bottomLeft.y) mOverlappingAreas.Add (topLeft); mOverlappingAreas.Add (topRight); else mOverlappingAreas.Add (topLeft); mOverlappingAreas.Add (bottomLeft); mOverlappingAreas.Add (topRight); mOverlappingAreas.Add (bottomRight); var zones = obj.mAreas; var ids = obj.mIdsInAreas; pour (int i = 0; i < areas.Count; ++i) if (!mOverlappingAreas.Contains(areas[i])) RemoveObjectFromArea(areas[i], ids[i], obj); //object no longer has an index in the area areas.RemoveAt(i); ids.RemoveAt(i); --i; for (var i = 0; i < mOverlappingAreas.Count; ++i) var area = mOverlappingAreas[i]; if (!areas.Contains(area)) AddObjectToArea(area, obj); mOverlappingAreas.Clear();
Tout d’abord, nous devons nous assurer d’appeler UpdateAreas
sur tous les objets du jeu. Nous pouvons le faire dans la boucle de mise à jour principale, après l'appel de mise à jour de chaque objet.
void FixedUpdate () for (int i = 0; i < mObjects.Count; ++i) switch (mObjects[i].mType) case ObjectType.Player: case ObjectType.NPC: ((Character)mObjects[i]).CustomUpdate(); mMap.UpdateAreas(mObjects[i]); break;
Avant de créer une fonction dans laquelle nous vérifions toutes les collisions, créons une structure qui contiendra les données de la collision..
Cela sera très utile, car nous pourrons conserver les données telles quelles au moment de la collision, alors que si nous ne sauvegardions que la référence à un objet avec lequel nous sommes entrés en collision, nous n'aurions pas seulement trop peu de ressources pour travailler, mais aussi la position et d'autres variables pourraient avoir changé pour cet objet avant le moment où nous devons réellement traiter la collision dans la boucle de mise à jour de l'objet.
public struct CollisionData public CollisionData (MovingObject other, Vector2 overlap = default (Vecteur2), Vector2 speed1 = default (Vector2), Vector2 speed2 = default (Vector2), Vector2 oldPos1 = default (Vector2), Vector2 oldPos2 = default (Vector2), Vector2 pos1 = par défaut (Vector2), Vector2 pos2 = par défaut (Vector2)) this.other = other; this. overlap = chevauchement; this.speed1 = speed1; this.speed2 = speed2; this.oldPos1 = oldPos1; this.oldPos2 = oldPos2; this.pos1 = pos1; this.pos2 = pos2; public MovingObject autre; public Vector2 se chevauchent; vecteur public2 vitesse1, vitesse2; public Vector2 oldPos1, oldPos2, pos1, pos2;
Les données que nous sauvegardons sont la référence à l'objet avec lequel nous sommes entrés en collision, le chevauchement, la vitesse des deux objets au moment de la collision, leurs positions, ainsi que leurs positions juste avant l'heure de la collision..
Passons au MovingObject
classe et créer un conteneur pour les données de collision fraîchement créées que nous devons détecter.
liste publiquemAllCollidingObjects = nouvelle liste ();
Revenons maintenant à la Carte
classe et créer un CheckCollisions
une fonction. Ce sera notre fonction lourde où nous détectons les collisions entre tous les objets du jeu..
public null CheckCollisions ()
Pour détecter les collisions, nous allons parcourir toutes les partitions.
pour (int y = 0; y < mVerticalAreasCount; ++y) for (int x = 0; x < mHorizontalAreasCount; ++x) var objectsInArea = mObjectsInArea[x, y];
Pour chaque partition, nous allons parcourir tous les objets qu'il contient.
pour (int y = 0; y < mVerticalAreasCount; ++y) for (int x = 0; x < mHorizontalAreasCount; ++x) var objectsInArea = mObjectsInArea[x, y]; for (int i = 0; i < objectsInArea.Count - 1; ++i) var obj1 = objectsInArea[i];
Pour chaque objet, nous vérifions tous les autres objets qui se trouvent plus bas dans la liste dans la partition. De cette façon, nous ne contrôlerons chaque collision qu'une seule fois.
pour (int y = 0; y < mVerticalAreasCount; ++y) for (int x = 0; x < mHorizontalAreasCount; ++x) var objectsInArea = mObjectsInArea[x, y]; for (int i = 0; i < objectsInArea.Count - 1; ++i) var obj1 = objectsInArea[i]; for (int j = i + 1; j < objectsInArea.Count; ++j) var obj2 = objectsInArea[j];
Maintenant, nous pouvons vérifier si les AABB des objets se chevauchent.
Vecteur 2 se chevauchent; pour (int y = 0; y < mVerticalAreasCount; ++y) for (int x = 0; x < mHorizontalAreasCount; ++x) var objectsInArea = mObjectsInArea[x, y]; for (int i = 0; i < objectsInArea.Count - 1; ++i) var obj1 = objectsInArea[i]; for (int j = i + 1; j < objectsInArea.Count; ++j) var obj2 = objectsInArea[j]; if (obj1.mAABB.OverlapsSigned(obj2.mAABB, out overlap))
Voici ce qui se passe dans les AABB SuperpositionSigné
une fonction.
public bool OverlapsSigned (autre AABB, chevauchement hors Vector2) overlap = Vector2.zero; if (HalfSizeX == 0.0f || HalfSizeY == 0.0f || other.HalfSizeX == 0.0f || other.HalfSizeY == 0.0f || Mathf.Abs (center.x - other.center.x)> HalfSizeX + other.HalfSizeX || Mathf.Abs (center.y - other.center.y)> HalfSizeY + other.HalfSizeY) renvoie la valeur false. overlap = new Vector2 (Mathf.Sign (center.x - other.center.x) * ((other.HalfSizeX + HalfSizeX) - Mathf.Abs (center.x - other.center.x)), Mathf.Sign (centre .y - other.center.y) * ((other.HalfSizeY + HalfSizeY) - Mathf.Abs (center.y - other.center.y))); retourne vrai;
Comme vous pouvez le constater, si la taille d'un AABB sur un axe est zéro, vous ne pouvez pas entrer en collision avec lui. Vous pouvez également remarquer que même si le chevauchement est égal à zéro, la fonction renvoie true, car elle rejette les cas dans lesquels l’écart entre les AABB est supérieur à zéro. C'est principalement parce que si les objets se touchent et ne se chevauchent pas, nous voulons toujours avoir l'information que c'est le cas, nous avons donc besoin que cela passe.
Enfin, une fois la collision détectée, nous calculons le degré de chevauchement entre les AABB et les autres AABB. Le chevauchement est signé. Ainsi, dans ce cas, si le chevauchement des AABB se trouve sur le côté droit de ce AABB, le chevauchement sur l’axe des x sera négatif et si l’autre AABB se trouve sur le côté gauche de cet AABB, le chevauchement sur l’axe des x sera positif. Cela facilitera ultérieurement la sortie de la position qui se chevauche, car nous savons dans quelle direction nous voulons que l’objet se déplace..
Revenir à notre CheckCollisions
fonction, s'il n'y a pas de chevauchement, c'est tout, nous pouvons passer à l'objet suivant, mais si un chevauchement se produit, nous devons ajouter les données de collision aux deux objets..
if (obj1.mAABB.OverlapsSigned (obj2.mAABB, chevauchement imminent)) obj1.mAllCollidingObjects.Add (new CollisionData (obj2, chevauchement, obj1.mSpeed, obj2.mSpeed, obj1.mOldPosition, obj1.mOldPosition, obj2.mOldPosition, obj2.mO, obj2.mPosition)); obj2.mAllCollidingObjects.Add (new CollisionData (obj1, -overlap, obj2.mSpeed, obj1.mSpeed, obj2.mOldPosition, obj1.mOldPosition, obj2.mPosition, obj1.mPosition));
Pour nous faciliter la tâche, supposons que les 1 (vitesse1, pos1, ancienPos1) de la structure CollisionData se réfèrent toujours au propriétaire des données de collision et que les 2 correspondent aux données concernant l'autre objet..
L'autre chose est que le chevauchement est calculé du point de vue de l'objet. Le chevauchement d'obj2 doit être annulé. Par conséquent, si obj1 doit se déplacer vers la gauche pour sortir de la collision, obj2 devra se déplacer vers la droite pour sortir de la même collision..
Il reste encore une petite chose à régler: nous parcourons les partitions de la carte et un objet peut se trouver dans plusieurs partitions en même temps (jusqu'à quatre dans notre cas), il est possible que nous détections un chevauchement pour le même objet. deux objets jusqu'à quatre fois.
Pour supprimer cette possibilité, nous vérifions simplement si nous avons déjà détecté une collision entre deux objets. Si c'est le cas, nous sautons l'itération.
if (obj1.mAABB.OverlapsSigned (obj2.mAABB, sur le chevauchement)) &&! obj1.HasCollisionDataFor (obj2)) obj1.mAllCollidingObjects.Add (nouveau CollisionData (obj2, chevauchement, obj1.mSpeed, obj1.mrite) obj2.mOldPosition, obj1.mPosition, obj2.mPosition)); obj2.mAllCollidingObjects.Add (new CollisionData (obj1, -overlap, obj2.mSpeed, obj1.mSpeed, obj2.mOldPosition, obj1.mOldPosition, obj2.mPosition, obj1.mPosition));
le HasCollisionDataFor
la fonction est implémentée comme suit.
public bool HasCollisionDataFor (MovingObject autre) pour (int i = 0; i < mAllCollidingObjects.Count; ++i) if (mAllCollidingObjects[i].other == other) return true; return false;
Il parcourt simplement toutes les structures de données de collision et recherche si des objets appartiennent déjà à l'objet pour lequel nous allons vérifier la collision..
Cela devrait convenir dans le cas d'utilisation courant, car nous ne prévoyons pas qu'un objet entrera en collision avec de nombreux autres objets. Par conséquent, parcourir la liste va être rapide. Cependant, dans un scénario différent, il pourrait être préférable de remplacer la liste des CollisionData
avec un dictionnaire, donc au lieu d'itérer, nous pourrions dire immédiatement si un élément est déjà présent ou non.
L'autre chose est que cette vérification nous évite d'ajouter plusieurs copies de la même collision à la même liste, mais si les objets n'entrent pas en collision, nous vérifierons quand même le chevauchement plusieurs fois si les deux objets appartiennent aux mêmes partitions..
Cela ne devrait pas être un gros problème, car la vérification des collisions est bon marché et la situation n’est pas si commune, mais si c’était un problème, la solution pourrait être simplement de disposer d’une matrice des collisions vérifiées ou d’un dictionnaire à double sens. que les collisions soient vérifiées, et réinitialisez-le juste avant d'appeler le CheckCollisions
une fonction.
Appelons maintenant la fonction que nous venons de terminer dans la boucle principale du jeu..
void FixedUpdate () for (int i = 0; i < mObjects.Count; ++i) switch (mObjects[i].mType) case ObjectType.Player: case ObjectType.NPC: ((Character)mObjects[i]).CustomUpdate(); mMap.UpdateAreas(mObjects[i]); mObjects[i].mAllCollidingObjects.Clear(); break; mMap.CheckCollisions();
C'est tout! Maintenant, tous nos objets devraient avoir les données sur les collisions.
Pour vérifier si tout fonctionne correctement, faisons en sorte que si un personnage entre en collision avec un objet, le sprite du personnage deviendra semi-transparent..
Comme vous pouvez le constater, la détection semble bien fonctionner!
Voilà pour une autre partie de la série de physique des plateformes 2D simples. Nous avons réussi à mettre en place un mécanisme de partitionnement spatial très simple et à détecter les collisions entre chaque objet..
Si vous avez une question, une astuce sur la façon de faire quelque chose de mieux ou juste un avis sur le tutoriel, n'hésitez pas à utiliser la section commentaire pour me le faire savoir.!