Jump to content
Unity Insider Forum

GameObject Positionen als "Ursprungszustand" definieren und auswerten


Recommended Posts

Hallo Leute,

 

dieser Thread soll in erster Linie entweder etwas bestätigen oder widerlegen und ggf. Verbesserungsvorschläge hervorbringen.

 

Ich nehme nochmal Bezug auf das (mein) Würfelproblem:

 

Man hat ein Brett mit ca. 30 Würfel in Ausgangsposition. Diese kann ich bestimmen, und sofern alle in dieser sind / bleiben hält eine Variable bool noChange = false.

 

Ändert sich aber nur ein einziger Würfel seine Position / Rotation, so ist es offenkundig nicht mehr die Ausgangslage und die Variable soll true werden.

 

Der erste naive Ansatz:

So wie ich das sehe müsste man dafür 30 Vektoren (startPos01 - startPos30) anlegen (lassen wir die Rotation mal aus dem Spiel) und die Objektpositionen da reinschreiben. Nun prüfe ich fortwährend für ALLE Objekte, ob sich die aktuelle Position von der startPosition unterscheided und setze die boolsche Variable entsprechend.

 

Man bedenke: Am Ende wird es nicht bei einem solchen Rack bleiben, sondern es werden 4 sein.

 

Mir kommt das irgendwie ein bisschen "overengineered" vor und im Verhältnis relativ aufwendig, aber ich sehe aktuell auch keine andere Möglichkeit das zu realisieren....

 

Vielen Dank vorab! :)

Edited by Unifier
Link to post
Share on other sites

Wie können sie denn bewegt werden?

Per code oder weil sie jemand anrempelt oder wie?

 

Wenn du sie per Code drehst/bewegst könntest du doch bei entsprechenden Methodenaufrufen das Flag setzen.

Und wenn sie jemand anrempelt bzw. sie durch das Physiksystem bewegt werden, kannst du in der OnCollisionEnter Methode das Flag setzen.

Oder gibt's noch andere Wege Objekte zu bewegen? ^^

 

Bei beiden Möglichkeiten hast du zusätzlich Zugriff auf das bewegte/gedrehte Objekt, falls das wichtig ist.

  • Like 1
Link to post
Share on other sites

Du kannst auch einfach jedem Würfel ein Script verpassen, daß die Ausgangslage jedes Würfels beim Programmstart speichert. Nun prüft dieses Script entweder - wie Tiwaz meint - die Ausgangslage gegen die aktuelle Position, wenn es angestoßen wird, oder wenn der User etwas verschiebt, oder wenn du etwas per Code veränderst. Es in der Update-Methode oder FixedUpdate-Methode zu machen wäre dagegen nicht so performant, aber auch möglich.

public class Location : MonoBehaviour
{

   private Transform orginPosition;
   private bool hasChangedPosition = false;

   void Awake () {
     orginPosition = this.transform.position;       
     this.transform.hasChanged = false;
   }

   void Update() {
       if (this.transform.hasChanged) {
           // the transform has changed
           this.transform.hasChanged = false;
           if (orginPosition != this.transform.position) {
              // the transform position has changed
              hasChangedPosition = true;
           } else {
              hasChangedPosition = false;
           }
       }
   }

}

Link to post
Share on other sites

Hi,

 

die Idee ist die, dass jemand die aufgestapelten Würfel umschmeißt um damit seine Antwort "zu starten".

 

Hintergrund:

Wenn sich also etwas geändert hat, dann gehe ich davon aus, dass der Spieler versucht möglichst viele von den Würfeln umzuwerfen. - Wird nichts geändert, kennt der Spieler die Antwort nicht oder er will aus sonstigen Gründen nicht antworten.

 

Denn wenn sich was geändert hat, soll ein Timer einsetzen - x Sekunden. Nach Ablauf überprüfe ich, ob a) der minCount erreicht ist und nur wenn ja ob B) es der richtige Ständer war (der die richtige Antwort repräsentiert). Entsprechend bekommt der Spieler positives oder negatives Feedback.

 

Durch Code werden die Würfel nur wieder in Ihre Ursprungsposition befördert, sodas eine neue Runde gespiellt werden kann. Von der Ursprungsposition weg werden sie nur durch Spielereinfluss bewegt.

 

Topic:

"wenn es angestoßen wird, oder wenn der User etwas verschiebt"

"Es in der Update-Methode oder FixedUpdate-Methode zu machen wäre dagegen nicht so performant, aber auch möglich."

--> Genau darum geht es :). Ich denke das geht nur über die Update-Methode... wie sonst soll man die Lageänderung erkennen ? (wenn nicht manuell angestoßen)

 

Meint ihr, die Update oder FIxedUpdate ist hierfür besser geeignet?

 

Ich nehme vorerst mal die Update()

 

 

Das zweite große Probleme ist, dass ich am Ende vier von den Ständen habe werde - und würde natürlich gerne das Skript nur einmal haben und dann an jeden der 4 Ständer hängen. Nur geht das natürlich nicht, da die Würfel der Kopien der Ständer ja dieselben Objektnamen haben werden. Nun könnte ich 30 public Variablen machen, bei jedem Stuhl die Würfelnamen ändern und manuell da reinziehen. Geht das nicht auch schöner und einfacher?

Oder Anders gefragt: Kann ich die Würfelobjekte in dem Skript irgendwie identizifieren z.B. im Format GameObject.Find("nameOfObjectWithAttachedScript/"+"childObjectName/"+"childObjectName/"+"cubeNumberXX");

 

Gefunden: this.gameObject.transform.parent.gameObject.name

 

Damit mache ich einfach eine einzige boolsche Variable in das Mutterskript und hänge das Änderungsskript an jeden Wüfel - andert sich was am Würfel, ändert er die Variable und ich kann den Timer starten :)

 

 

Danke Euch sehr! :)

 

EDIT:

Ein weiteres Problem mit der Feststellung der Position: Durch das "Neuaufbauen" der Klötze schwanken sie durch die Physik kurz hin und her, bis sie sich stabilisert haben. Somit würde nach dem Reset der Klötze eine Lageänderung festgestellt, obwohl nur der Reset statt gefunden hat und der Spieler nichts unternommen hat (false positive).

Schätze mal das wäre am Besten mit einem Yield / IEnumerator zu umgehen.....

 

Geprüft: Mit dem Yield und 2 Sekunden (1 Sekunde ist zu wenig) geht es

 

 

EDIT2: Schätze damit ist das Thema hier gelöst :)

 

EDIT3: :( Schade - das frisst bereits ab 10 Objekten derart viele Resourcen, dass die FPS auf unter 30 einbrechen. Mit allen aktiviert kreucht man so bei 15 FPS rum - für VR nicht akzeptabel.

 

Sieht jemand noch eine andere Möglichkeit, das zu realisieren? Ich muss das ja nicht in jedem Frame prüfen. Alle 2 Sekunden dürfte reichen.....

 

https://docs.unity3d.com/ScriptReference/MonoBehaviour.InvokeRepeating.html

 

Ich habe nun InvokeRepearing in die Update geschrieben - das bringt zu meiner Verwunderung auch nichts. So wie ich das sehe sollte dadurch die Evaluation nur alle 3 Sekunden stattfinden - stattdessen ist Unity damit komplett am Boden, obwohl im Taskmanger nur 13% Auslastung herrscht.

post-6156-0-28638000-1479582047_thumb.jpg

Edited by Unifier
Link to post
Share on other sites

Dann mal ein Vorschlag für einen anderen Ansatz, sofern die Würfel nur durch Spieleraktionen aus der Ausgangsposition gebracht werden können und nicht z. B. durch Sturm.: Prüfe mit dem Objekt, das der Spieler zum Verrücken der Würfel verwendet. Dabei muss das Objekt bei Kontakt mit den Würfeln immer zum Verrücken fähig sein.

Als PseudoCode:

if (Ball_trifft_Würfel)

{

WerteAntwortAus();

}

 

So brauchst Du nie(!) die Positionen der Würfel abfragen :)

Link to post
Share on other sites

Wenn mein obiges Skript an 30 Objekten hängt, solltest du das Performancetechnisch kaum merken. Da hast du wohl eher ein anderes Problem, achte darauf, daß in der Updatemethode nur wenig Code ausgeführt wird. Bei meiner Methode passiert pro Frame (also in dem Updateaufruf) nur eine Prüfung auf "this.transform.hasChanged". Das macht in Summe bei 30 Objekten mit diesem Skript, 30 Anweisungen pro Frame (d.h. deine FPS sollte sich eigentlich nicht verändern).

 

Noch ein Hinweis, wie du von der Update-Methode wegkommst:

Wenn die Veränderungen der Würfel durch den Spieler ausgelöst werden, dann gehört der Code der prüft ob die Würfelpositionen sich verändert haben in die Methode, die die Spieleraktion auslöst. Und hier macht dann ein Aufruf mit Verzögerung Sinn, über "Invoke".

Link to post
Share on other sites

Hi Ikarus und Zer0,

 

leuchtet beides ein.

 

Ich habe es jetzt so gelöst, dass ich einfach im Skript des Bodens abfrage, ob ein Würfel kollidiert ist. Dass ein Würfel nur verschoben wird und nicht herunterfällt, ist so natürlich nicht abgedeckt. Aber ich hatte bisher keinen solchen Fall.

 

@Zer0: War aber so... und am Ende sind es 120 Objekte und nicht nur 30. Daher hatte ich den Ansatz nicht weiter verfolgt.

 

Viele Grüße

Mark

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...