Jump to content
Unity Insider Forum

Grid snapping?


Tiles

Recommended Posts

Hallo Leute,

 

So langsam verzweifel ich vor mich hin mit dem Problem. Wie man in der Projektsektion sehen kann arbeite ich ja an einem Bubbles Klon. Und mir gehn immer wieder meine Coins stiften. Meine bisherige Methode einen neuen Coin relativ zum getroffenen Coin zu setzen ist leider instabil.

 

Bisher habe ich das mit der Bulletposition beim Auftreffen berechnet. Da dachte ich noch das liegt an der Bulletposition wenn sie auf einen Coin trifft. Und tatsächlich steckte sie ab und zu im getroffenen Coin, was keine genauen Werte möglich macht. Also habe ich es mit dem Kontaktpunkt probiert, über contact.point, um die richtige Position im Grid zu berechnen. Das ist ja dann in jedem Fall immer eine genaue Zahl mit der man arbeiten kann. Eben ein Punkt auf dem Umfang der getroffenen Kugel. Tja, was soll ich sagen. Auch die Methode hat nur manchmal funktioniert. Mir gehen immer noch Coins stiften, und setzen sich an Positionen an denen sie gar nicht sein dürften.

 

Ich brauche aber eine Methode die zu 100% funktioniert. Ich bin also wieder zurück auf Null. Und probiere nun meine Bullet direkt am Grid auszurichten. In der Höhe ist das ein Abstand von 0.85. Und in der Breite ist das ein Abstand von 1. Wobei da jede zweite Zeile um 0.5 versetzt ist.

 

Aber irgendwie fehlt mir da die richtige Formel. Das geht immer noch überall hin nur nicht dahin wo ich den Coin haben möchte. Wäre von euch jemand so Nett und hilft mir da auf die Sprünge? Ich weiss da grade echt nicht mehr weiter :/

 

Es gibt auch ein auf das Problem reduziertes Projektfile mit nur dem nötigen Code und den nötigen Grafiken. Um die 400 Kb:

 

http://www.reinerstilesets.de/ext/unity/gridproblem.rar

post-744-0-21465700-1432550486_thumb.jpg

Link zu diesem Kommentar
Auf anderen Seiten teilen

Willst du sowas hinbekommen?

http://puu.sh/hZTHT/d900d37318.mp4

 

Die blaue Kugel ist ein Gizmo und hat die gleiche Größe wie die Coins.

 

Das ist aber leider 8 Richtungen statt 6. Wurde in deinem Projekt gemacht.

 

Leider konnte ich deine Scripts nicht testen da ja kein Level gibt bzw bei mir eine leere Scene. Die Prefabs gehen auch nicht und die Tags sind auch nicht da. Darum hab ich gleich was eigenes gemacht.

 

Der Code sieht so aus bis jetzt:

 // berechne die Richtung
 Vector2 dir = (TargetCoin.position - MainCoin.position).normalized;
 // Runde und merke die Werte
 float x;
 float y;
 x = Mathf.Round(dir.x );
 y = Mathf.Round(dir.y );
 // Wenn die Kugel in der Ecke ist.. müssen wir sie näher verschieben.
 // Die Formel dafür ist  Sqrt(X + Y) / 2.  Habe es aber manuell eingetragen, da manchmal NAN Fehler rauskommt.
 // Weiß nicht ob die Formel jetzt ein Zufall war 
 if( Mathf.Abs( y ) == 1 && Mathf.Abs( x ) == 1) {
  dir.x = x * 0.707f;
  dir.y = y * 0.707f;
 } else {
  // ansonsten einfach die Werte übernehmen
  dir.x = x;
  dir.y = y;
 }

 // Wir brauchen nun den relativen Position zu TargetCoin.
 Vector2 relativeTarget = (Vector2)TargetCoin.position - dir * 1f;
 // GhostCoin ist noch ein weiterer Coin zum Debuggen. Wird eventuell durch Gizmo nicht sichtbar sein.
 GhostCoin.position = relativeTarget;

Link zu diesem Kommentar
Auf anderen Seiten teilen

Danke MaZy :)

 

Huh? Leere Szene? O_O Dafür tut dein MP4 hier nicht :D

 

Wenn du wissen willst wie das funktionieren soll, hier das volle Spiel dazu: http://forum.unity-c...nibbler-valley/

 

Mit was für einer Unity Version hast du das denn auf gemacht? Das Projekt ist mit Unity 5.0.1 gemacht. Vielleicht ist das das Problem :)

 

Hier tut jedenfalls alles. Ich habe es gerade extra noch mal runtergeladen um nachzusehen ob ich nicht vielleicht doch die falsche Version hochgeladen habe. Auch der Bullet Tag ist dran wo er drangehört. Und die Szene ist voll funktionsfähig. LInker Mausklick und es ballert einen Coin. Wo ich den Tag allerdings vergessen habe war die erste unsichtbare Reihe oben. Aber hier gehts ja um die grundsätzliche Methode. Und abräumen kann man hier eh nicht.

 

Aus deiner Methode werde ich ehrlich gesagt nicht ganz schlau. Wozu der Vector2? Ich habe irgendwie das Gefühl dass hier noch ein wenig Code fehlt. Wenn ich das richtig sehe verwendest du hier den Zielcoin als Ausgangspunkt für die Berechnung wo die Bullet dann landen soll. So ähnlich hatte ich das alles schon. Und das ging in die Hose. Das war die Methode die nicht stabil genug war.

 

Ich suche eine Methode wie ich die Kugel bei Kontakt mit einem Coin einfach ans Grid einschnappen lassen kann. Ohne den Zielcoin und dessen Position irgendwie in die Berechnung einbauen zu müssen. Am nächsten möglichen Punkt im Grid halt. Und das Grid ist dabei eben das Spielfeld mit den Coins. Mit dem Versatz jede zweite Zeile.

Link zu diesem Kommentar
Auf anderen Seiten teilen

So, ich habs! :)

Hat leider etwas länger gedauert, weil mein USB-Hub meinen Rechner 2 Mal zum abschmieren gebracht hat. Ärgerlich!

 

Meine Idee dabei ist, dass du ja eigentlich ein 2D Raster hast. Es ist zwar jede 2te Zeile um 0.5 verschoben, aber das kann man ja abrunden, dass es rechnerisch so aussieht, als wären alle Bullets auf einem geraden Raster.

 

Dafür bekommt jedes Bullet ein kleines Script, welches ich writeIntoArray genannt habe:

#pragma strict
var myX:int;
var myY:int;

// Dieses Script muss auf jeden Coin, der schon in der Szene ist
function Start () {
// Werte von der position holen und übergeben
var xx=transform.position.x;
var yy=transform.position.y;
// Damit ganze Zahlen raus kommen muss gerundet werden
 myX=Mathf.FloorToInt(xx);
 myY=Mathf.RoundToInt(yy/-0.85);
 //das hier muss nicht, kann aber nützlich sein um zu überprüfen wo nachbarn sind
 bulletarray.BA[myX,myY]=1; // hier setze ich mich mit einer 1 in ein 2D Array
 // Das Array im Script bulletarray ist static und von außen Aufrufbar

}

 

Jedes Bullet würde sich außerdem in ein 2D Array rein schreiben, um später evtl. besser auswerten zu können, welche Items nebeneinander liegen. Muss aber nicht sein. Ist nur ein Vorschlag.

 

Das Array sähe jedenfalls so aus und würde bulletarray heissen:

#pragma strict
static var BA:int[,]=new int[19,30];  // ein 2D array, wo sich jedes bullet rein schreiben kann [x,y]bekommt einen Wert

 

Das abgeschossene Bullet hat jetzt dieses Script:

 

#pragma strict

var speed:float = 5.0;
var rb: Rigidbody;

var rechts:boolean; // treffe ich von rechts?
var unten:boolean; // treffe ich von unten?
var myX:int; //
var myY:int;

var HasHitSome : boolean = false;


function Awake(){
rb.AddForce(transform.forward * speed); // Move the bullet
}

function OnCollisionEnter (col : Collision){

//Just count ONE collision. The first contact ...
if(HasHitSome){
	return;
}

if(col.gameObject.CompareTag("Bullet")){

// --------------------------------------------- set coin at position in grid ---------------------------------------
	// turn position into grid.

	// bilde eine Referenz vom writeIntoArray und frage einfach
	// die Werte von dem getroffenen Bullet ab

	var myscript:writeIntoArray;
	myscript=col.gameObject.GetComponent(writeIntoArray);

	//übergib die position vom getroffenen objekt

	var xx=myscript.myX;
	var yy=myscript.myY;

	//abfragen ob ich rechts vom Objekt bin oder links davon

	if(transform.position.x>=col.gameObject.transform.position.x ){
		rechts=true;
	}

	//abfragen ob ich unterhalb vom Objekt bin

	if(transform.position.y<=col.gameObject.transform.position.y-0.25){
		unten=true;
		myY=yy+1; // bin da drunter und setzte meine variable +1

	}else{
		myY=yy; // bin nicht da drunter und nutze das yy vom getroffenen Bullet
	}
	transform.position.y=myY*-0.85; // einfach die Zahl nutzen und mit dem Raster malnehmen
	if(unten){ // ich bin unterhalb
		if(rechts){ // ich bin außerdem rechts
			if(myY%2==1){ // ungerade reihe?
				myX=xx;
				transform.position.x=xx+0.5;
			}else{
				myX=xx+1;
				transform.position.x=xx+1;
			}
		}else{ // ich bin auf gleicher höhe
		   if(myY%2==1){ // ungerade reihe?
				myX=xx-1;
				transform.position.x=xx-0.5;
			}else{
				myX=xx;
				transform.position.x=xx;
			}
		}
	}else{ // ich bin auf gleicher höhe
		if(rechts){
			if(myY%2==1){
				myX=xx+1;
				transform.position.x=xx+1.5;
			}else{
				myX=xx+1;
				transform.position.x=xx+1;
			}
		}else{
		   if(myY%2==1){
				myX=xx-1; //
				transform.position.x=xx-0.5;
			}else{
				myX=xx-1;
				transform.position.x=xx-1;
			}
		}
	}
	rb.velocity= new Vector3(0,0,0);
	rb.isKinematic=true;
	HasHitSome = true;

	// gib mir auch das script, damit ein neues Bullet meine Position abfragen kann

	gameObject.AddComponent.<writeIntoArray>();
}

}

 

Beim Treffen auf ein Bullet, werden die 2 gerundeten Werte vom script ausgelesen um die später für das genaue Platzieren zu nutzen.

Ich schaue gleichzeitig wo ich den Bullet treffe und nutze dann angepasste Werte um mich selber zu setzen. Je nachdem ob ich unterhalb, neben dran, rechts oder links treffe, setze ich mich an einen etwas anderen Punkt.

Aber immer auf Basis der Werte vom getroffenen Bullet.

Und damit dann ein neuer Bullet mich auch treffen kann, gebe ich mir auch das writeIntoArray Script.

Das ist alles! :)

 

Ich habe alles soweit kommentiert. Wenn Fragen sind, dann frag. :)

dieScripte.zip

Link zu diesem Kommentar
Auf anderen Seiten teilen

Danke Malzbie :)

 

Aber das ist auch wieder die Methode die nicht ausreichend stabil funktioniert. Die über die Zielkugel. Das hatte ich doch schon. Das ist im Grunde die Methode bei der du mir die schönen Screenshots gezeigt hast mit den Fehlermeldungen :)

 

Ich arbeite im Trefferfall zwar direkt mit der Transform Position, und nicht über eine Array. Mein Code ist dementsprechend auch viel kürzer. Anmerkung, ich instanziere hier einen statischen Coin statt die Bullet zu setzen, aber das Prinzip sollte klar sein:

 

 //---------------------------------- now we sort position ----------------------------------------------
 var clone : Transform; // transform for instantiate.
 // higher contact point. Balls gets placed in next row

 if (transform.position.y < col.transform.position.y-0.65){
  if (transform.position.x > col.transform.position.x){
clone = Instantiate(bulletstatic, Vector3(col.transform.position.x+0.5, col.transform.position.y-0.85,0), Quaternion.identity);
  }
  else if (transform.position.x <=col.transform.position.x){
clone = Instantiate(bulletstatic, Vector3(col.transform.position.x-0.5, col.transform.position.y-0.85,0), Quaternion.identity);
  }
 }

 // lower contact point. Ball gets placed in same row.
 else if (transform.position.y >= col.transform.position.y-0.65){
  if (transform.position.x > col.transform.position.x){
clone = Instantiate(bulletstatic, Vector3(col.transform.position.x+1, col.transform.position.y,0), Quaternion.identity);
  }
  else if (transform.position.x <=col.transform.position.x){
clone = Instantiate(bulletstatic, Vector3(col.transform.position.x-1, col.transform.position.y,0), Quaternion.identity);
  }
 }

 

Das sollte aber keine grosse Rolle spielen ob ich das in einer Array vorberechne oder mir beim Treffer die Position der Zielkugel schnappe. Wichtig ist nur dass die Methode schlicht instabil ist. Ich versteh es ja auch nicht. Das funzt 99 mal, und beim hundertsten Mal steigt das Ding wieder aus und plaziert sich falsch :/

 

Deswegen möchte ich jetzt eben die Methode über einfaches Gridsnapping probieren. Ohne Umweg über die Zielkugel. Die Zielkugel ist in dem Fall einfach nur der Türstopper. Hier gehts nicht weiter, nun plazier dich mal richtig :)

 

Und da hänge ich halt an der Formel. Es snappt zwar, aber eben nicht so wie ich das gern hätte :(

 

Jedenfalls danke dass du dir die Mühe gemacht hast :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Du hast das nicht richtig verstanden. Das mit dem Array wäre nur ein Addon.

Ich ermittle die Positionen der Bullets und mache daraus ganz genaue Zahlen, die ich dann beim Treffen abfrage und für meine eigene Position nutze.

Da gibt es keine Fehler. Das Setzen mit den Werten ist quasi ein Gridsnapping.

 

Hast du nicht einfach mal Lust, meine Scripte zu probieren und zu verstehen, was ich da mache? Den Teil mit den Array kannste ja weg lassen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Malzbie, ich habe den Code sehr gut verstanden. In dem Moment wo du die Arrayposition der Zielkugel abfrägst gehst du aber meinen vorherigen Weg. Und der hat sich in der Praxis schon als unbrauchbar rausgestellt. Es wird einfach Zeit für Plan B :)

 

Ich weiss nicht wieso das über die Zielkugel schiefläuft. Ich weiss nur dass es schiefläuft. Und deswegen möchte ich die ganz raus lassen aus der Kalkulation. Auch wenn ich weiss dass du auf deine obige Lösung stolz bist. Hilft ja nix. Ich war auf meine Lösung auch stolz. Bis sie angefangen hat zu versagen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich weiß, warum es schief läuft. Es ist einfach Physik. Da kann es vorkommen, dass das Ganze tunnelt. Um das zu beheben, kann man die Fixed Timestep verkleinern und schon wirds besser.

 

Aber hey, wenn du denkst, mein Weg wäre genauso, wie deiner (was ich so nicht sehe), dann musst du dir was anderes einfallen lassen. Ich kann dir da nicht weiter helfen.

 

Ich habe übrigens noch eine Kleinigkeit gefixt, weil ich den Rand nicht im Blick hatte. Bei mir geht das jetzt ohne Probleme und ich schieße die Kugeln sogar mit 8000 ab, nicht wie in deinem Beispiel mit 500.

Falls wieder erwarten noch interesse besteht, kann ich es dir ja posten.

An sonsten bleibt dir nur noch eines: Mach es ohne Physik!

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ja, die vermalledeite Physik. Da habe ich eigentlich im Spiel schon alles getan um das zu verbessern. Timestep von 0.02 auf 0.01 und was es da sonst noch so gibt wie continuous Collision. Im Spiel schiesse ich übrigens mit 3000. Das habe ich nur im Beispiel verlangsamt.

 

Um das mit dem Durchtunneln zu unterbinden hatte ich ja auch schon mit der Berechnung über den Kontaktpunkt versucht. Das hat auch nicht funktioniert. Das war ehrlich gesagt fast noch schlimmer.

 

Interesse besteht immer. So einen Forenpost schreibst du ja in der Regel nicht nur für den Fragenden. Und ich finde es immer interessant in fremdem Code zu lesen. Ich will halt grade nur nicht mehr über die Trefferkugel arbeiten. Den Weg hatte ich schon.

 

Falls ich das mit dem direkten Grid nicht hinbekomme, und dafür hatte ich ja eigentlich diesen Forenpost gestartet, komme ich noch mal auf deine Methode zurück. Versprochen ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hier der Code. Kannst ja leicht am Kommentar identifizieren, wo er hingehört:

//abfragen ob ich rechts vom Objekt bin oder links davon

       if(transform.position.x>=col.gameObject.transform.position.x &&((xx<19 &&yy%2!=1)|| xx<18)){

           rechts=true;
       }
       if(!rechts && xx==0 && yy%2!=1){
           rechts=true;
       }

 

Im übrigen ist das was ich mache ein Gridsnapping. Deas Objekt wird dahin gesnappt, wo es hingehört. Fixe Werte im Bezug auf das Objekt, welches berührt wurde. Natürlich muss man irgendwelche Positionen anfragen, um zu entscheiden, wo nun der Parkplatz ist.

In deinem Fall (physik) geht das über den Collider. Und was wäre besser, als von dem Objekt, welches sich bewegt, aus zu fragen.

Ich frage keine Arrayposition ab!

Ich frage einfach nach gerundeten Werten der Zielkugel, die ich gerade berühre und platziere mich im Verhältnis dazu.

Würde man das über ein Array lösen, so müsste man auch seine Position runden um sagen zu können, in welchem Raster man gerade ist. Dann könnte man vergleichen, in welchen Nebenrastern andere Objekte sind und sich wiederum gerundet paltzieren.

Aber dann wüsste ich manchmal garnicht, welche Kugel ich gerade getroffen hätte, kenne ja nur die momentanen Nachbarn.

In anderen Spielen werden einfach die Pixel der anderen Objekte abgefragt. Und wenn ich einen Pixel von einem Objekt getroffen habe, muss ich auch dann entscheiden, ob es ein Pixel der rechten Seite oder der linken Seite des Objektes war. Und auch dann muss ich entscheiden, wo ich mich ablege und die Werte der Kugel irgendwie übermitteln. Ich kann dann zwar sagen, dass ich gerade im Raster XY bin und setze mich da hin. Aber die Info, welches Raster das ist, erzeugt wiederum die sich bewegende Kugel. Sie weiß, ob sie rechts neben der Trefferkugel ist oder nicht.

Klar könntest du ein Masterscript schreiben, welches schaut wo die Kugel gerade ist und dann erkennt um welchen Raster es sich gerade handelt. Aber es wird mit jedem Schritt mehr Aufwand in der Programmierung.

Ich habe keine Ahnung, welchen Code du erwartest und ich weiß auch nicht, wie du auswerten willst, wie und wo du ein anderes Objekt getroffen hast. Ob die Auswertung das bewegliche Objekt macht oder das stehende. Total egal. Der Punkt ist, dass es ausgewertet werden muss.

Wenn ein Collider in den anderen eindringt, dann kann es zu falschen Ergebnissen kommen und das bewegende Objekt "könnte" da platziert werden, wo schon eine andere ist. Um das auszuschleißen, wäre jetzt wirklich ein Array ganz toll, denn da kann ich schauen, ob an dieser Position schon etwas liegt und wenn ja, würde das bewegliche Objekt woanders platziert werden.

Das wäre Stufe 2.

Aber du willst ja keine Arrays. Du willst irgendetwas anderes. :)

Ich drück dir die Daumen. Vielleicht findest du einen Weg, den ich momentan nicht sehe. Ich sehe nur Collider oder aber Pixel.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Danke :)

 

Auch den Fix gibts natürlich in meiner Variante. Natürlich anders formuliert ^^

 

Ich habe keine Ahnung, welchen Code du erwartest

 

Das habe ich jetzt eigentlich oft genug gesagt. Simples Gridsnapping wenn die Kugel gestoppt ist. Zum nächstmöglichen Gridpunkt. Einfacher kann ich es nicht sagen. Und so stehts eigentlich auch im Titel. Ich will einfach nur Grid snapping, Ohne Schnörkel und Umwege :)

 

Das Raster ist hierbei alle 0.85 in der Höhe, und 1 in der Breite, wobei jede zweite Reihe versetzt ist. Und die Bullet soll dann eben so zu liegen kommen dass sie nicht mit einer schon existierenden Kugel überlappt, und im Raster sitzt. Wie dieses virtuelle Raster aussieht sieht man ja an den blauen Kugeln.

 

Das Gridsnapping an sich ist im Grunde recht simpel. Das ist das gleiche Gridsnapping wie in einem Strategiespiel wo du mit der Maus Tiles auf einem Grid plazierst.

 

Und es snappt ja auch schon in meinem Beispiel. Nur eben falsch. Was die Sache ein wenig kompliziert macht ist der Versatz, und dass es dadurch 6 mögliche Kontaktpunkte gibt. Dann noch das Minus dazu ... .

 

Mit 8 Gridpunkten drumrum und ohne Versatz wär die Schose natürlich viel einfacher. Und da krieg ich grade meinen Kopf nicht drumrum. Deswegen habe ich nach der Formel gefragt. In Mathe bin ich einfach ne Niete. Stattdessen hast du mir das Ding wieder auf die Kalkulation über die getroffene Kugel zurückgebaut :)

 

und ich weiß auch nicht, wie du auswerten willst, wie und wo du ein anderes Objekt getroffen hast.

 

Wieso soll ich was auswerten was nichts mit dem Problem und meiner Frage zu tun hat? Ich will dich hier doch gar nicht das Spiel nachbauen lassen. Das ist keine Frage von Pixel oder Collider. Und mit oder ohne Array. Ich will nur meine angehaltene Bullet an einem Grid snappen lassen. Alles andere ist nicht die Frage und habe ich doch eh schon lang gelöst. Du hast doch selber gesehn dass das Game im Grunde fertig ist. Die restliche Mechanik steht schon lang. Es geht nur darum die Bullet am richtigen Platz abzulegen.

 

Ich finde es ja gut dass du mitdenkst. Aber du ballerst hier grade gnadenlos übers Ziel raus. Ich brauche keine Grundsatzdebatte, sondern eine Lösung für ein konkretes und eigentlich recht triviales Problem, sieht man mal davon ab dass ich das grade nicht geregelt bekomme, hehe. Deine obigen Überlegungen habe ich eh alle schon im Laufe der Entwicklung des Spiels durchgeackert und durchprobiert. Ich mache im Spiel im Moment genau das was du hier vorschlägst, weil das auch für mich am Brauchbarsten und Einfachsten aussah. Ich berechne ja schon vom Zielcoin aus. Meine Berechnung geht einen etwas anderen Weg, aber im Grundsatz ist das gleich. Und zum xten mal, die Geschichte ging in die Hose. Deswegen brauche ich ja einen anderen Lösungsansatz.

 

Das ging so lang gut bis ich ne Beta draus gebaut hab und die Leute mir dann plötzlich Arrayfehler und falsch plazierte Kugeln um die Ohren gehauen haben. Das hast du doch selber gesehen in dem Spiel. Bis dahin dachte ich auch dass alles tadellos funktioniert.

 

Wie gesagt, ich brauche was anderes. Und diese andere Idee, der andere Ansatz ist eben das direkte Gridsnapping wenn die Bullet gestoppt ist. Kugel ist angehalten: Berechnung wo der nächste Gridpunkt liegt, und da hinsnappen. Ob das dann wirklich die Lösung wird weiss ich an dem Punkt noch gar nicht. Und ist auch uninteressant. Erst mal muss ich sie zum Laufen bekommen. Dann kann ich vergleichen und schauen. Und dann können wir da gern weiter drüber diskutieren.

 

Probiern wers halt noch mal mit der Frage. Wie snappe ich eine gestoppte Kugel an ein versetztes Bubbles Grid? OHNE über die getroffene Kugel zu kalkulieren. Sondern wirklich nur über dessen derzeitige Position.

 

Im Moment sieht mein Bullet Code so aus. Mir gehts um die Transform Position der Bullet. Dass eben die Bullet an der richtigen Stelle landet. Nicht irgendwo in der Luft, nicht über einer schon existierenden Kugel, und auch nicht ausserhalb des Spielfelds.

 

gridX und gridY dienen dazu über deren Int das Ding passend auf eine Gridzelle zu runden. Könnte man natürlich auch über Mathf.floor machen und Variablen sparen. Aber mit den Variablen kann ich nachschaun ob die Grid-Kalkulation klappt oder nicht. Und sie klappt ja auch nicht, was ein Glück :)

 

var rb: Rigidbody;
var gridX:int=0;
var gridY:int=0;
var HasHitSome : boolean = false;
function Awake(){
rb.AddForce(transform.forward * speed); // Move the bullet
}
function OnCollisionEnter (col : Collision){
//Just count ONE collision. The first contact ...
if(HasHitSome){
 return;
}

if(col.gameObject.CompareTag("Bullet")){

// --------------------------------------------- set coin at position in grid ---------------------------------------
 // turn position into grid.
 gridY=transform.position.y*-1.1766;

 //odd or even results in an offset. so we have two possibe values for x position and grid calculation

 if (gridY%2==1) {
  gridX=transform.position.x;
 }
 else {
  gridX=transform.position.x-0.5;
 }

 // now we set the coin at its position

 transform.position.x=gridX;
 transform.position.y=gridY*-0.85;

 rb.velocity= new Vector3(0,0,0);
 rb.isKinematic=true;
 HasHitSome = true;
}
}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wuhu, ich hab meine Fehler gefunden \o/

 

Das war mal echt eine schwere Geburt. Ich und Mathe und so. Ich hatte einmal vergessen den Versatz beim setzen der Position auch wieder reinzurechnen. Und um den halben Grid muss ich ja auch noch versetzen. Sowohl in X als auch in Y. Sonst landet die Kugel immer auf einer Seite, bzw, auf einer Höhe.

 

Das sieht jetzt so aus:

 

// --------------------------------------------- set coin at position in grid ---------------------------------------
 // turn position into grid.
 gridY=(transform.position.y-0.425)*-1.1766;
 //odd or even results in an offset. so we have two possibe values for x position and grid calculation
 if (gridY%2==0) {
  gridX=transform.position.x+0.5; // +0.5 means half the grid radius to the right, or the bullet will always land at one side.
 }
 else {
  gridX=transform.position.x; // odd. Here we have already an offset by the odd even story.
 }
 // now we set the coin at its position. This time the other way around with the odd and even.

 if (gridY%2==0) {
  transform.position.x=gridX;
 }
 else {
  transform.position.x=gridX+0.5;
 }

 transform.position.y=gridY*-0.85;

 rb.velocity= new Vector3(0,0,0);
 rb.isKinematic=true;
 HasHitSome = true;

 

Bis jetzt scheint alles zu funzen. Da haut nix ab, alles landet auf seinem Platz. Aber das dacht ich ja schon mal. Mal in mein Spiel einbauen und nachsehn wie sich das in der Praxis macht ^^

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich gehe mal davon aus, dass aus irgend einem Grund wieder ein Bullet in ein anderes eingedrungen ist. Erst danach kam die Collision-Auswertung und dadurch hat deine Positionsangabe nicht mehr gepasst. XWert oder YWert oder sogar beide waren jetzt soweit innerhalb des getroffenen Bullets, sodass deine Rasterberechnung nicht mehr gepasst hat.

Waren die Bullets überlappt wie in deinem Screenshot, oder lag die eine direkt auf der anderen?

Wenn sie nur überlappt waren, hast du vielleicht einen Rundungsfehler bei Y. Du weisst ja, dass 1 in Int nicht unbedingt 1 in Float ist.

Deswegen hatte ich die Positionen der Kugeln zu gerundeten Int Werten gemacht und diese Int Werte wiederum fürs Setzen des abgeschossenen Bullets genutzt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ja, ich vermute auch mal dass ich hier einfach in das gleiche Problem gerannt bin wie mit meiner vorherigen Methode. Was genau das allerdings ist, tja. Wenn ich es wüsste könnte ich es abstellen. Ich hatte ja wie erwähnt sogar schon über den Kontaktpunkt berechnet. Der Kontaktpunkt sitzt auf dem Radius der Trefferkugel. Da kann nichts verrutschen oder eindringen. Das sind dann echt exakte Werte. Und trotzdem hatte ich meine Aussetzer.

 

Ah, siehste, du siehst das nicht am Codeschnippel den ich hier reingepackt habe, aber meine gridX und gridY sind auch Ints. Rundungsfehler schliesse ich deswegen aus. Ich mache das mit der Gridmethode im Grunde so wie du. Bei meiner alten Methode arbeite ich allerdings mit den Floats der Position, das stimmt.

 

Ich bin jetzt erst mal wieder bei meiner Originalmethode, und habe jetzt noch mal den Timestep runtergesetzt. Originalwert ist 0.02. Ich hatte ihn schon auf 0.01 abgesenkt. Nun ist es 0.005. Mal sehn ob es jetzt stabiler läuft. Wenn nicht nehm ich mir mal deine Methode zur Brust ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...