In dit deel van de serie gaan we eraan werken dat objecten niet alleen fysiek kunnen werken met de tilemap, maar ook met elk ander object, door een botsingsdetectiemechanisme tussen de game-objecten te implementeren.
De demo toont het eindresultaat van deze tutorial. Gebruik WASD om het personage te verplaatsen. De middelste muisknop zorgt voor een eenrichtingsplatform, de rechtermuisknop zorgt voor een massieve tegel en de spatiebalk zorgt voor een karakterkloon. De schuifregelaars veranderen de grootte van het personage van de speler. De objecten die een botsing detecteren, zijn semi-transparant gemaakt.
De demo is gepubliceerd onder Unity 5.4.0f3 en de broncode is ook compatibel met deze versie van Unity.
Voordat we het hebben over enige vorm van botsingreactie, zoals het onmogelijk maken dat de objecten door elkaar gaan, moeten we eerst weten of die specifieke objecten elkaar overlappen.
Dit kan een erg dure operatie zijn als we elk object eenvoudig vergelijken met elk ander object in het spel, afhankelijk van het aantal actieve objecten dat het spel momenteel moet verwerken. Dus om de slechte processor van onze spelers een klein beetje te verzachten, gebruiken we ...
In feite splitst dit de ruimte van het spel in kleinere gebieden, waardoor we de botsingen tussen objecten die alleen bij hetzelfde gebied horen, kunnen controleren. Deze optimalisatie is hard nodig in games als Terraria, waar de wereld en het aantal mogelijke botsende objecten enorm is en de objecten schaars worden geplaatst. In spellen met één scherm, waarbij het aantal objecten sterk wordt beperkt door de grootte van het scherm, is het vaak niet nodig, maar nog steeds nuttig.
De populairste ruimtelijke partitioneringsmethode voor 2D-ruimte is quad tree; je vindt de beschrijving in deze tutorial. Voor mijn spellen gebruik ik een platte structuur, wat in feite betekent dat de spelruimte is opgesplitst in rechthoeken van een bepaalde grootte, en ik controleer op botsingen met objecten die zich in dezelfde rechthoekige ruimte bevinden.
Er is één nuance aan dit: een object kan in meer dan één subruimte tegelijk aanwezig zijn. Dat is helemaal goed - het betekent alleen dat we objecten moeten detecteren die behoren tot een van de partities waar ons vorige object mee te maken heeft.
De basis is eenvoudig. We moeten weten hoe groot elke cel moet zijn en een tweedimensionale array, waarvan elk element een lijst is met objecten die zich in een bepaald gebied bevinden. We moeten deze gegevens in de klasse Map plaatsen.
public int mGridAreaWidth = 16; public int mGridAreaHeight = 16; openbare lijst[,] mObjectsInArea;
In ons geval heb ik besloten om de grootte van de partitie in tegels uit te drukken, en dus is elke partitie 16 bij 16 tegels groot.
Voor onze objecten willen we een lijst met gebieden die het object momenteel overlapt, evenals de index in elke partitie. Laten we deze toevoegen aan de MovingObject
klasse.
openbare lijstmAreas = nieuwe lijst (); openbare lijst mIdsInAreas = nieuwe lijst ();
In plaats van twee lijsten kunnen we een enkel woordenboek gebruiken, maar helaas laat de prestatieoverhead van het gebruik van complexe containers in de huidige iteratie van Unity te wensen over, dus we houden ons aan de lijsten voor de demo.
Laten we verder gaan met het berekenen van het aantal partities dat we nodig hebben om het hele gebied van de kaart te dekken. De veronderstelling hierbij is dat geen object buiten de grenzen van de kaart kan zweven.
mHorizontalAreasCount = Mathf.CeilToInt ((float) mWidth / (float) mGridAreaWidth); mVerticalAreasCount = Mathf.CeilToInt ((float) mHeight / (float) mGridAreaHeight);
Afhankelijk van de kaartgrootte hoeven de partities natuurlijk niet exact overeen te komen met de kaartgrenzen. Daarom gebruiken we een maximum aan berekende waarde om ervoor te zorgen dat we op zijn minst genoeg hebben om de hele kaart te dekken.
Laten we de partities nu starten.
mObjectsInArea = nieuwe lijst[mHorizontalAreasCount, mVerticalAreasCount]; voor (var y = 0; y < mVerticalAreasCount; ++y) for (var x = 0; x < mHorizontalAreasCount; ++x) mObjectsInArea[x, y] = new List ();
Er is hier niets speciaals aan de hand - we zorgen er gewoon voor dat elke cel een lijst met objecten heeft waarop we kunnen opereren.
Nu is het tijd om een functie te maken die de gebieden die een bepaald object overlapt, zal bijwerken.
openbare ongeldige UpdateAreas (MovingObject obj)
Allereerst moeten we weten met welke kaarttegels het object overlapt. Omdat we alleen AABB's gebruiken, hoeven we alleen maar te controleren op welke tegel elke hoek van de AABB terechtkomt.
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 ();
Om nu de coördinaat in de gepartitioneerde ruimte te krijgen, hoeven we alleen maar de tegelpositie te delen door de grootte van de partitie. We hoeven nu niet de partituur in de rechter benedenhoek te berekenen, omdat de x-coördinaat gelijk is aan de rechterbovenhoek en de y-coördinaat gelijk is aan de linkeronderhoek..
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;
Dit alles zou moeten werken op basis van de aanname dat geen object buiten de grenzen van de kaart zal worden verplaatst. Anders hebben we hier een extra controle nodig om de objecten te negeren die buiten de grenzen vallen.
Nu is het mogelijk dat het object zich volledig in een enkele partitie bevindt, het in twee delen kan zijn, of het de ruimte kan innemen waar vier partities elkaar ontmoeten. Dit is in de veronderstelling dat geen object groter is dan de partitiegrootte, in welk geval het de hele kaart en alle partities zou kunnen bezetten als het groot genoeg zou zijn! Ik heb gewerkt onder deze veronderstelling, dus dat is hoe we dit in de tutorial zullen behandelen. De aanpassingen voor het toestaan van grotere objecten zijn echter vrij triviaal, dus ik zal ze ook uitleggen.
Laten we beginnen door te controleren met welke gebieden het personage overlapt. Als alle scheidingscoördinaten van de hoek hetzelfde zijn, neemt het object slechts een enkel gebied in beslag.
if (topLeft.x == topRight.x && topLeft.y == bottomLeft.y) mOverlappingAreas.Add (topLeft);
Als dat niet het geval is en de coördinaten op de x-as hetzelfde zijn, overlapt het object met twee verschillende partities verticaal.
if (topLeft.x == topRight.x && topLeft.y == bottomLeft.y) mOverlappingAreas.Add (topLeft); else if (topLeft.x == topRight.x) mOverlappingAreas.Add (topLeft); mOverlappingAreas.Add (bottomleft);
Als we objecten ondersteunen die groter zijn dan partities, zou het voldoende zijn als we eenvoudig alle partities van de linkerbovenhoek aan de linkeronderkant hebben toegevoegd met behulp van een lus.
Dezelfde logica is van toepassing als alleen de verticale coördinaten hetzelfde zijn.
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);
Als tenslotte alle coördinaten verschillend zijn, moeten we alle vier de gebieden toevoegen.
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);
Voordat we verder gaan met deze functie, moeten we het object van een bepaalde partitie kunnen toevoegen en verwijderen. Laten we deze functies maken, te beginnen met het toevoegen.
public void AddObjectToArea (Vector2i areaIndex, MovingObject obj) var area = mObjectsInArea [areaIndex.x, areaIndex.y]; Bewaar de index van het object in het gebied obj.mAreas.Add (areaIndex); obj.mIdsInAreas.Add (area.Count); // voeg het object toe aan het gebied. Add (obj);
Zoals u kunt zien, is de procedure heel eenvoudig: we voegen de index van het gebied toe aan de lijst overlappende gebieden van het object, we voegen de bijbehorende index toe aan de lijst met id's van het object en voegen het object uiteindelijk toe aan de partitie.
Laten we nu de verwijderingsfunctie maken.
public void RemoveObjectFromArea (Vector2i areaIndex, int objIndexInArea, MovingObject obj)
Zoals je kunt zien, gebruiken we de coördinaten van het gebied waar het personage niet langer mee overlapt, de index in de objectenlijst in dat gebied en de verwijzing naar het object dat we moeten verwijderen.
Om het object te verwijderen, wisselen we het uit met het laatste object in de lijst. Dit vereist dat we er ook voor zorgen dat de index van het object voor dit specifieke gebied wordt bijgewerkt naar het object dat ons verwijderde object had. Als we het object niet hebben geruild, moeten we de indexen bijwerken van alle objecten die achterlopen op de objecten die we moeten verwijderen. In plaats daarvan moeten we alleen de update bijwerken waarmee we hebben geruild.
Het hebben van een woordenboek zou veel moeite besparen, maar het verwijderen van het object uit een gebied is een bewerking die veel minder vaak nodig is dan itereren door het woordenboek, wat voor elk object gedaan moet worden wanneer we het overlappen van het object bijwerken. gebieden.
// verwissel het laatste item met het item dat we verwijderen var tmp = area [area.Count - 1]; gebied [area.Count - 1] = obj; gebied [objIndexInArea] = tmp;
Nu moeten we het gebied dat we betreffen vinden in de lijst met gebieden van het verwisselde object en de index in de lijst met id's wijzigen in de index van het verwijderde object.
var tmpIds = tmp.mIdsInAreas; var tmpAreas = tmp.mAreas; voor (int i = 0; i < tmpAreas.Count; ++i) if (tmpAreas[i] == areaIndex) tmpIds[i] = objIndexInArea; break;
Ten slotte kunnen we het laatste object van de partitie verwijderen, wat nu een verwijzing is naar het object dat we moesten verwijderen.
area.RemoveAt (area.Count - 1);
De hele functie zou er als volgt uit moeten zien:
public void RemoveObjectFromArea (Vector2i areaIndex, int objIndexInArea, MovingObject obj) var area = mObjectsInArea [areaIndex.x, areaIndex.y]; // verwissel het laatste item met het item dat we verwijderen var tmp = area [area.Count - 1]; gebied [area.Count - 1] = obj; gebied [objIndexInArea] = tmp; var tmpIds = tmp.mIdsInAreas; var tmpAreas = tmp.mAreas; voor (int i = 0; i < tmpAreas.Count; ++i) if (tmpAreas[i] == areaIndex) tmpIds[i] = objIndexInArea; break; //remove the last item area.RemoveAt(area.Count - 1);
Laten we teruggaan naar de UpdateAreas-functie.
We weten in welke gebieden het teken dit frame overlapt, maar in het laatste frame had het object al aan dezelfde of verschillende gebieden kunnen zijn toegewezen. Laten we eerst de oude gebieden doorlopen en als het object niet langer overlapt met hen, laten we het object hieruit verwijderen.
var areas = obj.mAreas; var ids = obj.mIdsInAreas; voor (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;
Laten we nu de nieuwe gebieden doorlopen en als het object nog niet eerder aan hen is toegewezen, laten we ze nu toevoegen.
for (var i = 0; i < mOverlappingAreas.Count; ++i) var area = mOverlappingAreas[i]; if (!areas.Contains(area)) AddObjectToArea(area, obj);
Wis ten slotte de lijst met overlappende gebieden zodat deze gereed is om het volgende object te verwerken.
mOverlappingAreas.Clear ();
Dat is het! De laatste functie zou er als volgt uit moeten zien:
public void UpdateAreas (MovingObject obj) // haal de gebieden op de hoeken van de 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; // zie hoeveel verschillende gebieden we hebben als (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 areas = obj.mAreas; var ids = obj.mIdsInAreas; voor (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();
Allereerst moeten we ervoor zorgen dat we bellen UpdateAreas
op alle game-objecten. We kunnen dit doen in de hoofdupdatalkring, na de updateaanroep van elk individueel object.
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;
Voordat we een functie creëren waarin we alle botsingen controleren, kunnen we een struct maken die de gegevens van de botsing bevat.
Dit zal zeer nuttig zijn, omdat we de gegevens kunnen bewaren zoals die zijn op het moment van de botsing, terwijl als we alleen de verwijzing naar een object zouden opslaan waar we mee botsten, we niet alleen te weinig zouden hebben om mee te werken, maar ook de positie en andere variabelen kunnen voor dat object zijn gewijzigd voordat de tijd komt dat we de botsing daadwerkelijk in de updatelus van het object kunnen verwerken.
public struct CollisionData public CollisionData (MovingObject other, Vector2 overlapping = standaard (Vector2), Vector2 speed1 = standaard (Vector2), Vector2 speed2 = standaard (Vector2), Vector2 oldPos1 = standaard (Vector2), Vector2 oldPos2 = standaard (Vector2), Vector2 pos1 = standaard (Vector2), Vector2 pos2 = standaard (Vector2)) this.other = other; this.overlap = overlapping; this.speed1 = speed1; this.speed2 = speed2; this.oldPos1 = oldPos1; this.oldPos2 = oldPos2; this.pos1 = pos1; this.pos2 = pos2; openbaar MovingObject anders; openbare Vector2 overlapping; openbare Vector2 snelheid1, snelheid2; openbare Vector2 oudPos1, oudPos2, pos1, pos2;
De gegevens die we opslaan, zijn de verwijzing naar het object waarmee we in botsing kwamen, de overlapping, de snelheid van beide objecten op het moment van de botsing, hun posities en ook hun posities vlak voor het tijdstip van de botsing..
Laten we naar de MovingObject
klasse en maak een container voor de vers gecreëerde collisiegegevens die we moeten detecteren.
openbare lijstmAllCollidingObjects = nieuwe lijst ();
Laten we nu teruggaan naar de Kaart
klasse en maak een CheckCollisions
functie. Dit wordt onze heavy duty-functie waarbij we de botsingen tussen alle game-objecten detecteren.
openbare ongeldige CheckCollisions ()
Om de botsingen te detecteren, zullen we door alle partities heen gaan.
voor (int y = 0; y < mVerticalAreasCount; ++y) for (int x = 0; x < mHorizontalAreasCount; ++x) var objectsInArea = mObjectsInArea[x, y];
Voor elke partitie, itereren we door elk object erin.
voor (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];
Voor elk object controleren we elk ander object dat zich verderop in de lijst in de partitie bevindt. Op deze manier controleren we elke botsing slechts één keer.
voor (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];
Nu kunnen we controleren of de AABB's van de objecten elkaar overlappen.
Vector2 overlapping; voor (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))
Dit is wat er gebeurt in de AABB's OverlapsSigned
functie.
public bool OverlapsSigned (AABB other, out Vector2 overlapping) 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) return false; overlapping = nieuwe Vector2 (Mathf.Sign (center.x - other.center.x) * ((other.HalfSizeX + HalfSizeX) - Mathf.Abs (center.x - other.center.x)), Mathf.Sign (center .y - other.center.y) * ((other.HalfSizeY + HalfSizeY) - Mathf.Abs (center.y - other.center.y))); geef waar terug;
Zoals je kunt zien, kan de AABB-afmeting op geen enkele as nul zijn, maar er kan niet mee worden gebotst. Het andere wat je zou kunnen opmerken is dat zelfs als de overlap gelijk is aan nul, de functie waar zal terugkeren, omdat het de gevallen zal verwerpen waarin de kloof tussen de AABB's groter is dan nul. Dat komt vooral omdat als de objecten elkaar raken en elkaar niet overlappen, we toch de informatie willen hebben dat dit het geval is, dus we hebben dit nodig om door te gaan.
Als laatste punt berekenen we, zodra de botsing is gedetecteerd, hoeveel de AABB overlapt met de andere AABB. De overlapping is ondertekend, dus in dit geval als de overlappende AABB zich aan de rechterkant van deze AABB bevindt, is de overlapping op de x-as negatief en als de andere AABB zich op deze linkerkant van de AABB bevindt, is de overlapping op de x-as positief. Dit maakt het later gemakkelijk om uit de overlappende positie te komen, omdat we weten in welke richting we willen dat het object beweegt.
Teruggaan naar onze CheckCollisions
functie, als er geen overlapping was, dat is het, dan kunnen we naar het volgende object gaan, maar als er een overlapping optreedt, moeten we de collisiegegevens aan beide objecten toevoegen.
if (obj1.mAABB.OverlapsSigned (obj2.mAABB, out overlapping)) obj1.mAllCollidingObjects.Add (nieuwe CollisionData (obj2, overlapping, obj1.mSpeed, obj2.mSpeed, obj1.mOldPosition, obj2.mOldPosition, obj1.mPosition, obj2.mPosition)); obj2.mAllCollidingObjects.Add (nieuwe CollisionData (obj1, -overslag, obj2.mSpeed, obj1.mSpeed, obj2.mOldPosition, obj1.mOldPosition, obj2.mPosition, obj1.mPosition));
Om het ons gemakkelijk te maken, gaan we ervan uit dat de enen (speed1, pos1, oldPos1) in de CollisionData-structuur altijd verwijzen naar de eigenaar van de collisiegegevens, en de 2's de gegevens over het andere object.
Het andere is dat de overlapping wordt berekend vanuit het perspectief van de obj1. De overlap van de obj2 moet worden genegeerd, dus als obj1 links moet bewegen om uit de botsing te komen, moet obj2 naar rechts bewegen om uit dezelfde botsing te komen.
Er is nog steeds een klein ding om voor te zorgen - omdat we door de partities van de kaart heen gaan en één object in meerdere partities tegelijk kan zijn, tot vier in ons geval, is het mogelijk dat we een overlap voor dezelfde partitie detecteren twee objecten tot vier keer.
Om deze mogelijkheid te verwijderen, controleren we eenvoudig of we al een botsing tussen twee objecten hebben gedetecteerd. Als dat het geval is, slaan we de iteratie over.
if (obj1.mAABB.OverlapsSigned (obj2.mAABB, out overlapping) &&! obj1.HasCollisionDataFor (obj2)) obj1.mAllCollidingObjects.Add (nieuwe CollisionData (obj2, overlap, obj1.mSpeed, obj2.mSpeed, obj1.mOldPosition, obj2.mOldPosition, obj1.mPosition, obj2.mPosition)); obj2.mAllCollidingObjects.Add (nieuwe CollisionData (obj1, -overslag, obj2.mSpeed, obj1.mSpeed, obj2.mOldPosition, obj1.mOldPosition, obj2.mPosition, obj1.mPosition));
De HasCollisionDataFor
functie is als volgt geïmplementeerd.
public bool HasCollisionDataFor (MovingObject other) for (int i = 0; i < mAllCollidingObjects.Count; ++i) if (mAllCollidingObjects[i].other == other) return true; return false;
Het itereert eenvoudigweg door alle botsingsdatastructuren en zoekt op of er al een onderdeel is van het object dat we gaan controleren op een botsing voor.
In het algemeen zou dit goed moeten zijn, omdat we niet verwachten dat een object botst met veel andere objecten, dus het kijken door de lijst zal snel gaan. In een ander scenario is het misschien beter om de lijst met te vervangen CollisionData
met een woordenboek, dus in plaats van itereren konden we meteen zien of een element al aanwezig is of niet.
Het andere ding is, deze controle bespaart ons van het toevoegen van meerdere kopieën van dezelfde botsing aan dezelfde lijst, maar als de objecten niet botsen, zullen we hoe dan ook meerdere overlappingen controleren als beide objecten tot dezelfde partities behoren.
Dit zou geen grote zorg moeten zijn, omdat de collisioncheck goedkoop is en de situatie niet zo gewoon is, maar als het een probleem was, zou de oplossing kunnen zijn om gewoon een matrix van gecontroleerde botsingen of een tweerichtingswoordenboek te hebben, te vullen als de botsingen worden gecontroleerd en opnieuw ingesteld vlak voordat we de CheckCollisions
functie.
Laten we nu de functie aanroepen die we net in de hoofdgame-lus hebben voltooid.
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();
Dat is het! Nu zouden al onze objecten de gegevens over de botsingen moeten hebben.
Om te testen of alles goed werkt, laten we ervoor zorgen dat als een personage tegen een object botst, de sprite van het personage semi-transparant wordt.
Zoals je ziet, lijkt de detectie goed te werken!
Dat is het voor een ander deel van de eenvoudige 2D-platformer physics-serie. We zijn erin geslaagd om een zeer eenvoudig mechanisme voor ruimtelijke partitionering te implementeren en de botsingen tussen elk object te detecteren.
Als je een vraag hebt, een tip over hoe iets beter te doen, of gewoon een mening hebt over de tutorial, voel je vrij om het gedeelte met reacties te gebruiken om me te laten weten!