Jump to content
Unity Insider Forum

Objekt automatisch fahren lassen


Haji17

Recommended Posts

Hallo in die Runde :)

Ich fange gerade an, mich in Unity einzuarbeiten und hätte eine kleine Frage. Ich möchte ein GameObject( ich nehme einfach Mal einen Cube) eine "Strecke" fahren lassen, bzw. folgendes Szenario umsetzen:

Der Cube soll bis zu einem gewissen Punkt geradeaus fahren. Am Punkt sich um 90 Grad drehen, wieder geradeaus fahren bis zu einem Punkt, dort wieder sich um 90 Grad drehen und das ganze Prozedere noch zwei mal wiederholen, bis er wieder am Startpunkt angelangt ist. Letztendlich ist der Cube einmal im "Viereck" gefahren. Ich hab mir schon ein paar Tutorials angeschaut und kann den Würfel zum Bsp. mit den Pfeiltasten steuern: Dies mach ich hiermit :

Vector3 movementVector = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));

 

Aber hiermit bekomm ich nicht die Rotation am Eckpunkt hin und muss das ganze ja auch immer mit den Pfeiltasten steuern. Wie kann ich das ganze automatisch ablaufen lassen? 

Könnt ihr mir hier bei diesem einfachen Beispiel weiterhelfen? 

 

VG

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Moin!

Abläufe, wo Dinge über mehrere Frames hinweg passieren sollen, kann man wunderbar mit Coroutinen bauen. Da Coroutinen andere Coroutinen ausführen können, kannst du eine "Hinbewegen"- und eine "Drehen"-Coroutine bauen, und eine dritte Coroutine, die diese beiden immer wieder aufruft.

Das könnte z.B. so aussehen:

private const float ROTATE_SPEED = 90f;
private const float WALK_SPEED = 2f;
public float walkDistance = 10f;

private void Start()
{
  StartCoroutine(RunAround());
}

private IEnumerator RunAround()
{
  while (enabled)
  {
    yield return TurnTowards(Vector3.forward);
    yield return RunTowards(Vector3.forward * walkDistance);
    
    yield return TurnTowards(Vector3.left);
    yield return RunTowards(Vector3.left * walkDistance);
    
    yield return TurnTowards(Vector3.backward);
    yield return RunTowards(Vector3.backward * walkDistance);
    
    yield return TurnTowards(Vector3.right);
    yield return RunTowards(Vector3.right * walkDistance);
  }
}

private IEnumerator TurnTowards(Vector3 direction)
{
  var targetRotation = Quaterion.LookRotation(direction);
  
  while (transform.rotation != targetRotation)
  {
    transform.rotation = Quaternion.RotateTowards(transform.rotation, targtetRotation, ROTATE_SPEED * Time.deltaTime);
    yield return null;
  }
}

private IEnumerator RunTowards(Vector3 direction)
{
  var targetPosition = transform.position + direction;
  
  while (transform.position != targetPosition)
  {
    transform.position = Vector3.MoveTowards(transform.position, targetPosition, WALK_SPEED * Time.deltaTime);
    yield return null;
  }
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Am 15.9.2021 um 11:50 schrieb Sascha:
private IEnumerator TurnTowards(Vector3 direction)
{
  var targetRotation = Quaterion.LookRotation(direction);
  
  while (transform.rotation != targetRotation)
  {
    transform.rotation = Quaternion.RotateTowards(transform.rotation, targtetRotation, ROTATE_SPEED * Time.deltaTime);
    yield return null;
  }

Sry, so ganz versteh ich diese Anweisung noch nicht 😅

Durch den IEnumerator Turntowards (vector3 direction) habe ich eine Methode für mehrere Frames mit der Variable "direction" vom Typ vector3 erzeugt.

Darin definiere ich eine Variable targetrRotation als Quaterion.Lookrotation von direction. 

In der folgenden while- Schleife wird überprüft, ob die aktuelle Rotationsposition (transform.rotation) mit der Zielposition übereinstimmt. Falls nicht, wird das Gameobject durch Quaternion.RotateTowards gedreht, bis die Bedingung erreicht ist. Mit yield return null wird der aktuelle Stand gespeichert, so dass die nächste Coroutine von da weitermachen kann.

Ich hoffe, bis hierhin habe ich das richtig verstanden. Was genau macht aber der Befehl Quaterion.Lookrotation? Ich habe das im Manual aufgerufen( https://docs.unity3d.com/ScriptReference/Quaternion.LookRotation.html), aber ich steh gerade etwas aufm Schlauch, wie habe ich dadurch meine Zielposition definiert? 

Bei einem Cube als Beispiel hat das keinen Unterschied gemacht, aber jetzt habe ich einfach als Asset einen Roboter aus dem Store importiert, dieser ist aber um 90 Grad verdreht, er schaut sozusagen in die falsche Richtung bei der Bewegung. Ich dachte, ich kann dem im Inspector entgegenwirken indem ich die Y- Rotate  Komponente um 90 verändere, aber das hat bei der Ausführung nix verändert :D

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor einer Stunde schrieb Haji17:

In der folgenden while- Schleife wird überprüft, ob die aktuelle Rotationsposition (transform.rotation) mit der Zielposition übereinstimmt. Falls nicht, wird das Gameobject durch Quaternion.RotateTowards gedreht, bis die Bedingung erreicht ist. Mit yield return null wird der aktuelle Stand gespeichert, so dass die nächste Coroutine von da weitermachen kann.

Fast richtig - es gibt hier nur eine Coroutine, die pausiert wird. "yield return null;" darf man übersetzen mit "Warte einen Frame".

vor einer Stunde schrieb Haji17:

Was genau macht aber der Befehl Quaterion.Lookrotation?

Du steckst einen Vektor rein und kriegst eine Rotation zurück, die ein Objekt so ausrichtet, dass es in die Richtung dieses Vektors schaut.

Das hier:

transform.rotation = Quaternion.LookRotation(direction);

macht dasselbe wie

transform.forward = direction;

Da wir ja aber schrittweise da hindrehen wollen, erzeuge ich erstmal die Drehung (das Quaternion) und benutze RotateTowards, um das Objekt immer weiter dieser Rotation anzunähern.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 4 Stunden schrieb Sascha:

Da wir ja aber schrittweise da hindrehen wollen, erzeuge ich erstmal die Drehung (das Quaternion) und benutze RotateTowards, um das Objekt immer weiter dieser Rotation anzunähern.

Vielen Dank, dann habe ich das jetzt verstanden :)

Kannst du mir vielleicht noch sagen, warum mein Asset um 90 Grad verdreht ist? Muss ich beim Import was beachten oder wo liegt da der Fehler?

Ich möchte als Ziel gerne ein GameObject erstellen, welches ich mit Daten von einem Server kontrollieren kann. Sprich, mein Würfel/ Asset bewegt sich dann nicht mehr starr im Viereck, sondern so wie meine Daten es ihm vorgeben. Ich dachte mir als Vorgehensweise schau ich erst Mal, wie ich generell ein GameObject kontrollieren kann. Einen automatischen Ablauf habe ich jetzt.

Im nächsten Schritt möchte ich ein Skript erstellen, bei welchem ich die "Vektordaten" selber eingebe. X, Y und Z- Komponente kann ich ja als Public- Variable so deklarieren, dass ich die im Inspector selber eingeben kann. Wenn ich das richtig verstanden habe, gibt es bei Unity ein Mal die eulerAngles (das wären die Grad-Zahlen, die ich bei Transform eingeben kann) und die "Quaterion- Funktion". Wie könnte ich dieses Vorgehen am Besten lösen?

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 53 Minuten schrieb Haji17:

Kannst du mir vielleicht noch sagen, warum mein Asset um 90 Grad verdreht ist? Muss ich beim Import was beachten oder wo liegt da der Fehler?

Gerade bei Blender ist das bekannt. Da ist die Z-Achse ja oben, während bei Unity Y die vertikale Achse ist. Und aus irgendeinem Grund schafft Unity das nicht, dem FBX Exporter beim automatischen Export zu sagen, dass er das fixen soll. Als Resultat haben wir um -90° gedrehte importierte Objekte, damit sie richtig herum sind. Tatsächlich habe ich mal einen AssetPostProcessor geschrieben, der das reparieren soll, aber der ist nie brauchbar geworden, weil es brutal viele Sonderfälle zu beachten gibt...

Wenn du dann ein solches Objekt auf eine normale Rotation setzt, die diesen Umstand nicht beachtet, dann gehen diese -90° flöten und das Objekt ist falsch ausgerichtet. Der beste Weg ist, das Objekt selber zu exportieren: https://unity3d.college/2017/07/08/fix-bad-90-x-rotation-unity3d-blender/

Wenn das aber nicht drin ist, ist es nicht unüblich, ein leeres Objekt zu nehmen, das Modell als Child mit der -90°-Drehung hinzuzufügen, und dann den Parent normal zu drehen.

vor einer Stunde schrieb Haji17:

X, Y und Z- Komponente kann ich ja als Public- Variable so deklarieren, dass ich die im Inspector selber eingeben kann.

Ja, das kannst du, aber du kannst auch einfach einen Vector3 statt drei floats deklarieren ;)

vor einer Stunde schrieb Haji17:

Wenn ich das richtig verstanden habe, gibt es bei Unity ein Mal die eulerAngles (das wären die Grad-Zahlen, die ich bei Transform eingeben kann) und die "Quaterion- Funktion".

Beides sind Repräsentationen derselben Sache. Euler-Winkel sind nur doof, weil sie "Gimbal-locken" können. Quaternions sind schwerer zu verstehen, aber ansonsten einfach nur besser. Um eine Ausrichtung im Editor einzugeben, sind Euler-Winkel in Ordnung. Aber sobald du im Code angekommen bist, wirfst du die recht schnell weg. Mit Quaterion.Euler kannst du einen Euler-Vector3 in ein Quaternion umwandeln. Aber willst du wirklich Ausrichtungen im Editor definieren? Oder vielleicht doch lieber Punkte zum Hinlaufen, und dann die Ausrichtung mit z.B. Quaternion.LookRotation errechnen lassen?

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 28 Minuten schrieb Sascha:

Gerade bei Blender ist das bekannt. Da ist die Z-Achse ja oben, während bei Unity Y die vertikale Achse ist. Und aus irgendeinem Grund schafft Unity das nicht, dem FBX Exporter beim automatischen Export zu sagen, dass er das fixen soll. Als Resultat haben wir um -90° gedrehte importierte Objekte, damit sie richtig herum sind. Tatsächlich habe ich mal einen AssetPostProcessor geschrieben, der das reparieren soll, aber der ist nie brauchbar geworden, weil es brutal viele Sonderfälle zu beachten gibt...

Wenn du dann ein solches Objekt auf eine normale Rotation setzt, die diesen Umstand nicht beachtet, dann gehen diese -90° flöten und das Objekt ist falsch ausgerichtet. Der beste Weg ist, das Objekt selber zu exportieren: https://unity3d.college/2017/07/08/fix-bad-90-x-rotation-unity3d-blender/

Wenn das aber nicht drin ist, ist es nicht unüblich, ein leeres Objekt zu nehmen, das Modell als Child mit der -90°-Drehung hinzuzufügen, und dann den Parent normal zu drehen.

Genau, das hab ich auch hier im Forum gelesen, dass es das beim Import aus Blender zu beachten gibt. In meinem Fall habe ich das Asset aus dem Unity-Store runtergeladen, aber ich werd mich da mal noch ransetzen wieso das Problem auftritt. 

vor 30 Minuten schrieb Sascha:

Wenn das aber nicht drin ist, ist es nicht unüblich, ein leeres Objekt zu nehmen, das Modell als Child mit der -90°-Drehung hinzuzufügen, und dann den Parent normal zu drehen.

Stimmt danke dir, damit werde ich es auch versuchen.

 

vor 31 Minuten schrieb Sascha:

Beides sind Repräsentationen derselben Sache. Euler-Winkel sind nur doof, weil sie "Gimbal-locken" können. Quaternions sind schwerer zu verstehen, aber ansonsten einfach nur besser. Um eine Ausrichtung im Editor einzugeben, sind Euler-Winkel in Ordnung. Aber sobald du im Code angekommen bist, wirfst du die recht schnell weg. Mit Quaterion.Euler kannst du einen Euler-Vector3 in ein Quaternion umwandeln. Aber willst du wirklich Ausrichtungen im Editor definieren? Oder vielleicht doch lieber Punkte zum Hinlaufen, und dann die Ausrichtung mit z.B. Quaternion.LookRotation errechnen lassen?

Wie meinst du das mit Punkte zum Hinlaufen? 😅

Also ich habe mir nur überlegt, dass mit den Vektoren darzustellen, da mir kein anderer Weg in den Sinn kam :D 

Wie würdest du denn bei meinem Szenario zum Kontrollieren eines Gameobjects mit Hilfe von vorgegeben Daten  am besten vorgehen? :) 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also, wenn die Daten vom Server kommen sollen, dann kannst du im Editor nicht gerade sinnvoll etwas einstellen. Sonst kann man gut GameObjects in der Szene verteilen, diese in ein Array packen und in der Coroutine das Array durchlaufen. Mit OnDrawGizmos kann man da noch schön Linien zwischen malen, um den Pfad zu visualisieren. Generell gilt, dass der Editor hervorragend dazu geeignet ist, kleine und große Tools und Visualisierungen einzubauen, um einen ganz eigenen, zum Projekt passenden Design-Workflow zu schaffen. Aber wie gesagt... mit Daten vom Server wird das eher schwieriger.

vor 1 Stunde schrieb Haji17:

Wie meinst du das mit Punkte zum Hinlaufen? 😅

Es klingt, als wolltest du irgendwie die Ausrichtung des Objekts irgendwo einstellen. Dabei ist es viel einfacher, wenn du einfach nur definierst, wo das Ding hinlaufen soll, und dann richtet es sich automatisch immer zum nächsten Punkt aus.

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 2 weeks later...

Ich hätte noch eine weitere Frage. Ich hab gesehen, dass es in Unity auch Wheelcollider gibt, mit denen man Eigenschaften von Rädern festlegen kann. Wie kann ich denn ein ähnliches  Programm wie oben mit den Coroutinen starten, aber anstatt Vektoren nutze ich ein vorgegebenes Drehmoment für eine Bewegung im Viereck.

Ist das mit addtorque möglich? In meinem Szenario hätte ich 2 Reifen, das Objekt würde je nach Drehmoment der beiden Reifen geradeaus bewegen oder zum Bsp bei Drehmoment auf nur ein rad sich dementsprechend drehen. Das Drehmoment würde ich dann als Variable im Script oder als Public variable im editor einstellen. Die Zeit, wie lange das Drehmoment wirkt ebenso.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo, 

sorry, ich hätte noch eine weitere Frage und die Antworten hier im Forum sind für mich Anfänger immer am verständlichsten 😅

Ich habe die Möglichkeit, über das Aufrufen einer http einen JSON- string in der Form [0:{x:1,y:1, dx:0,3, dy:0,2}] zu bekommen. Das ganze hat den Hintergrund, dass ich ein Modell habe, dessen aktuelle Position immer in dieser Json-Form mitgeteilt wird. Mit dem Tangens kann ich aus dx und dy  den Winkel für die Rotation berechnen.

Meine Idee ist es, das hier genutzte Skript mit den Coroutinen so anzupassen, dass ein Vektor3 (x,y,0) als Zielvektor gewählt wird und mein Gameobject sich genauso bewegt. 

Ich hab gesehen, dass es von unity selber eine Möglichkeit für das Implementiern von Json https://docs.unity3d.com/Manual/JSONSerialization.html gibt. Aber ich verstehe nicht, wie ich das hier benutzen kann. Eigentlich müsste ich doch erst die http irgendwie aufrufen, aus dem übertragenen json string den x- und y-wert rauspicken, das ganze als Variable speichern und daraus dann meinen Zielvektor machen?  Wie kann ich das ganze denn umsetzen? Macht das Sinn, was ich mir ausdenke?

Nochmals danke für die Hilfe immer. 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Am 2.10.2021 um 17:11 schrieb Haji17:

Mit dem Tangens

So als Tipp von mir: in 99% der Fälle braucht man keine Trigonometrie anwenden. Mit Methoden wie Quaterion.LookRotation oder Vector3.Angle spart man sich die Kopfschmerzen.

Am 2.10.2021 um 17:11 schrieb Haji17:

Ich hab gesehen, dass es von unity selber eine Möglichkeit für das Implementiern von Json https://docs.unity3d.com/Manual/JSONSerialization.html gibt. Aber ich verstehe nicht, wie ich das hier benutzen kann. Eigentlich müsste ich doch erst die http irgendwie aufrufen, aus dem übertragenen json string den x- und y-wert rauspicken, das ganze als Variable speichern und daraus dann meinen Zielvektor machen?  Wie kann ich das ganze denn umsetzen? Macht das Sinn, was ich mir ausdenke?

Die Idee ist in Ordnung. JsonUtility ist dafür auch genau richtig. Das Ding serialisiert und deserialisiert aber ganze Objekte. Da holst du nicht einzelne Variablen raus und fügst sie selber in ein Objekt ein. Ich nehme an, du hast dein Json falsch abgetippt, denn es hat Syntaxfehler. Sieht es in Wirklichkeit so aus?

[0:{x:1, y:1, dx:0.3, dy:0.2}]

Da das so oder so kein Vector3 ist, musst du einmal ein Struct definieren, das genau diese Felder hat.

[System.Serializable]
public struct Thing
{
  public float x;
  public float y;
  public float dx;
  public float dy;
}

Dann ist dein Json-String leider ein Array mit einem Objekt drin. Die Manual zu JsonUtility sagt:

Zitat

Unity does not support passing other types directly to the API, such as primitive types or arrays.

Das heißt, dein Json muss da anders gebacken werden. Entweder ohne Array

{x:1, y:1, dx:0.3, dy:0.2}

oder das Array muss in ein Objekt gepackt werden.

{points:[0:{x:1, y:1, dx:0.3, dy:0.2}]}

Dann kannst du diesen Typ wieder als Struct in C# definieren:

[System.Serializable]
public struct ThingArray
{
  public Thing[] points;
}

und letztenendes beim laden

var myThingArray = JsonUtility.FromJson<ThingArray>(myJson);

P.S. Es gibt nicht "eine HTTP", HTTP ist ein Protokoll, wie eine Sprache. Das ist, als ob du den Kundenservice anrufst und sagst "ich rufe das Deutsch an" ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Danke fürs Helfen :)

vor 10 Stunden schrieb Sascha:
[0:{x:1, y:1, dx:0.3, dy:0.2}]

Da das so oder so kein Vector3 ist, musst du einmal ein Struct definieren, das genau diese Felder hat.

[System.Serializable]
public struct Thing
{
  public float x;
  public float y;
  public float dx;
  public float dy;
}

Sorry, genau das sieht so aus wie du es beschrieben hast. Ok, das Struct "Thing" soll also dazu dienen, die Daten aus JSON zuordnen zu können, versteh ich das richtig?

vor 10 Stunden schrieb Sascha:

Das heißt, dein Json muss da anders gebacken werden. Entweder ohne Array

Sry falls ich so blöde Fragen stelle, aber was meinst du mit anders gebacken? Der JSON string soll in einer anderen Form verschickt werden? Oder muss in meinem Code nochmal verarbeitet und "umgewandelt" werden, damit ich damit arbeiten kann? 

 

vor 10 Stunden schrieb Sascha:
{points:[0:{x:1, y:1, dx:0.3, dy:0.2}]}

Wenn ich das richtig verstanden habe, wird das Array Points benötigt, damit ich mein JSON dann letztendlich durch das Struct "Thing" darstellen kann oder?

 

vor 10 Stunden schrieb Sascha:

und letztenendes beim laden

var myThingArray = JsonUtility.FromJson<ThingArray>(myJson);

Die Variable myThingArray ist doch noch nicht mein Zielvektor, den ich dann in die Coroutine einfach so einbauen kann? Im Folgeschritt müsste ich ja einen Vektor3 definieren mit den Einträgen x und y aus dem Array und dem z- Wert 0? 

vor 10 Stunden schrieb Sascha:

P.S. Es gibt nicht "eine HTTP", HTTP ist ein Protokoll, wie eine Sprache. Das ist, als ob du den Kundenservice anrufst und sagst "ich rufe das Deutsch an" ;)

Ich glaube, ich muss mir das ganze Thema so oder so nochmals genauer anschauen . Vielen Dank nochmals !

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 5 Stunden schrieb Haji17:

Ok, das Struct "Thing" soll also dazu dienen, die Daten aus JSON zuordnen zu können, versteh ich das richtig?

Ja, JsonUtility kann nur Objekte laden und alles, was drin steckt. Wenn du in deinem Json-String die Komponenten x, y, dx und dy hast, dann musst du auch eine Klasse oder Struct definieren, die diese Eigenschaften hat.

vor 5 Stunden schrieb Haji17:

Der JSON string soll in einer anderen Form verschickt werden?

Json ist nur ein Format für Strings, das angibt, wie Daten angeordnet sind. { } steht für ein Objekt. { x = 5 } steht für ein Objekt, bei dem die x-Eigenschaft den Wert 5 hat. [ ] ist ein Array. Objekte und Arrays können andere Objekte und Arrays beinhalten. JsonUtility hat als Einschränkung, dass du kein Array mit Dingen drin deserialisieren (in Objekte umwandeln) kannst, sondern nur ein Objekt. Die äußere Klammer darf also nicht [ ] sein, sondern muss { } sein.

vor 5 Stunden schrieb Haji17:

Wenn ich das richtig verstanden habe, wird das Array Points benötigt, damit ich mein JSON dann letztendlich durch das Struct "Thing" darstellen kann oder?

Fast. Es handelt sich um ein ThingArray, das ein Array "points" enthält, in dem beliebig viele Thing-Objekte enthalten sind. Wenn du allerdings nur ein Thing, also ein Objekt mit x, y, dx und dy verschickst, dann kannst du dir das Array und auch das ThingArray-Objekt drumherum sparen und einfach nur dieses eine Objekt verschicken.

vor 5 Stunden schrieb Haji17:

Die Variable myThingArray ist doch noch nicht mein Zielvektor, den ich dann in die Coroutine einfach so einbauen kann? Im Folgeschritt müsste ich ja einen Vektor3 definieren mit den Einträgen x und y aus dem Array und dem z- Wert 0? 

Ich hab halt wie gesagt den Verdacht, dass du das Array nicht brauchst. War aber halt in deinem Code drin. Wozu hast du im Objekt eigentlich dx und dy, wenn du nur x und y benutzen willst?

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 13 Stunden schrieb Sascha:

Ich hab halt wie gesagt den Verdacht, dass du das Array nicht brauchst. War aber halt in deinem Code drin. Wozu hast du im Objekt eigentlich dx und dy, wenn du nur x und y benutzen willst

Also, ich hoffe ich bekomme das richtig ausgedrückt :D

Mein Ziel ist es, ein GameObject durch die JSON- Daten bewegen zu lassen. Das ganze in der Form hat den Hintergrund, dass ich in "real-life" ein Modell hab, welches mit einem Tracker und einer Kamera lokalisiert wird (damit habe ich an sich wenig zu tun, ich weiß nur dass ich den aktuellen Standort in der oben beschriebenen JSON-Form über einen kleinen Server  bekomme. "0" ist die Bezeichnung des Modells, da es mehrere gibt. X und Y sind der Standort in 2D, mit dx und dy kann ich die Richtung ermitteln in der das Modell schaut).  

Im ersten Schritt würde ich den Server anfragen und mir von dort die JSON- Datei nehmen. Dafür kann ich doch Unitywebrequest.get (https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest.Get.html) nutzen oder? Wenn ich mir das Beispiel im Manual anschaue und richtig verstehe, dann müsste ich mit Aufrufen der Coroutine GetRequest auf das JSON zugreifen. Ich frage mich aber, wie und in welcher Form ich das JSON aufrufen kann in meinem Script. Ich verstehe dass ich das nicht direkt nutzen kann und deswegen mir ein Struct ("Thing") definiere. 

Am 4.10.2021 um 08:37 schrieb Sascha:
var myThingArray = JsonUtility.FromJson<ThingArray>(myJson);

Ich tue mich aber generell mit dem Einsatz von Json schwer, da ich das erste Mal mit sowas arbeite. Da ich das Json in der oben genannten Form bekomme, wird das durch "Thing" und "ThingArray" als meine Variable myThingArray gespeichert oder? 

Im nächsten Schritt sollte ich den Wert x und y aus dem Array aufrufen, das sollte mit dem Aufrufen eines Arrays durch variable = myThingArray[2] funktionieren? 

Am 4.10.2021 um 08:37 schrieb Sascha:
[System.Serializable]
public struct Thing
{
  public float x;
  public float y;
  public float dx;
  public float dy;
}

Hier habe ich x als float deklariert, deswegen sollte ich das wie oben beschrieben aufrufen können oder?

Bis hierhin hätte ich nur die Json Datei verwertet, im letzten Schritt will ich mein GameObject ja so bewegen lassen.

Am 15.9.2021 um 11:50 schrieb Sascha:
private IEnumerator RunAround()
{
  while (enabled)
  {
    yield return TurnTowards(Vector3.forward);
    yield return RunTowards(Vector3.forward * walkDistance);

Während ich das oben viermal mit forward, back, left und right habe da ich es im Viereck bewegen lassen wollte, reicht jetzt doch ein Mal dieser Befehl und anstatt vector3.forward nehme ich meinen definierten Vektor durch Json. Als Coroutine würde ich das ganze laufen lassen, da ich nach einige zeit ja wieder eine neue Position mit json bekomme und dementsprechend mein Zielvektor sich ändert?

Ganz schön viel Text, aber ich hoffe ich konnte mein Problem verständlich ausdrücken . Leider werde ich nur aus dem UnityManual nicht schlau was das Anfragen per http und dem Nutzen von Json angeht, bei Youtube nutzen die meisten irgendwelche Assets was mich dann komplett verwirrt :(

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 35 Minuten schrieb Haji17:

X und Y sind der Standort in 2D, mit dx und dy kann ich die Richtung ermitteln in der das Modell schaut).  

Das ergibt Sinn! Danke :)

vor 35 Minuten schrieb Haji17:

Dafür kann ich doch Unitywebrequest.get (https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest.Get.html) nutzen oder?

Jau, genau. Wenn du oft und viele Daten kriegst, ist HTTP ein bisschen meh, aber ansonsten geht das gut. Und ja. UnityWebRequest ist genau dafür da.

vor 35 Minuten schrieb Haji17:

Ich frage mich aber, wie und in welcher Form ich das JSON aufrufen kann in meinem Script.

Du kriegst vom DownloadHandler den Text zurück, den du als Antwort auf dein HTTP-Request bekommen hast. Dieser Text ist einfach dein Json-String, und den steckst du in die JsonUtility rein.

vor 35 Minuten schrieb Haji17:

Ich tue mich aber generell mit dem Einsatz von Json schwer, da ich das erste Mal mit sowas arbeite. Da ich das Json in der oben genannten Form bekomme, wird das durch "Thing" und "ThingArray" als meine Variable myThingArray gespeichert oder? 

Mal ein paar Beispiele. Das erste ist immer ein Json-String und darunter ist dann der passende C#-Code, in den du die Daten reinpressen lassen kannst. Ich prettify-e die Json-Daten, indem ich Zeilenumbrüche und Einrückung zwecks Lesbarkeit reintue, macht aber keinen Unterschied.

Json

{
  number: 0,
  word: "hi"
}

C#

[System.Serializable]
public struct Thing
{
  public int number;
  public string word;
}

Json

{
  numbers:
  [
    1, 2, 3
  ]
}

C#

[System.Serializable]
public struct Thing
{
  public int[] numbers;
}

Json

{
  things:
  [
    { number: 2 },
    { number: 6 },
    { number: 0 }
  ]
}

C#

[System.Serializable]
public struct Thing
{
  public int number;
}

[System.Serializable]
public struct ManyThings
{
  public Thing[] things;
}

Bei diesem Beispiel machst du

JsonUtility.FromJson<ManyThings>(jsonFromAbove);

und kriegst ein "ManyThings" zurück, dessen "things"-Array drei "Thing"s enthält, jeweils mit den Nummern 2, 6 und 0.

vor 38 Minuten schrieb Haji17:

Im nächsten Schritt sollte ich den Wert x und y aus dem Array aufrufen, das sollte mit dem Aufrufen eines Arrays durch variable = myThingArray[2] funktionieren? 

Je nachdem, wie viele Objekte du kriegst. In deinem Beispiel ist immer nur ein Objekt im Array. Wenn du da [2] sagst kriegst du eine IndexOutOfRangeException, weil es nur [0] gibt. Erst bei drei Objekten wäre [2] ein gültiger Index.

Um dann vom 0-ten Thing die x-Koordinate zu kriegen, einfach .x sagen:

myThingArray[0].x

 

vor 40 Minuten schrieb Haji17:

Bis hierhin hätte ich nur die Json Datei verwertet, im letzten Schritt will ich mein GameObject ja so bewegen lassen.

Joa... irgendwie muss dein Code, der den Json-Kram macht, dem Code, der das GO bewegt, die Daten übergeben. Wie man das am besten macht, kommt ganz auf die Situation drauf an.

vor 41 Minuten schrieb Haji17:

Als Coroutine würde ich das ganze laufen lassen, da ich nach einige zeit ja wieder eine neue Position mit json bekomme und dementsprechend mein Zielvektor sich ändert?

Kann man machen. Wenn etwas durchgehend läuft, ist Update auch eine Option. Aber wenn du Abläufe hast, die aufeinander warten (wie die Bewegung, die erst nach der anderen Bewegung passiert), dann ist eine Coroutine schon eine gute Sache.

vor 42 Minuten schrieb Haji17:

Ganz schön viel Text, aber ich hoffe ich konnte mein Problem verständlich ausdrücken . Leider werde ich nur aus dem UnityManual nicht schlau was das Anfragen per http und dem Nutzen von Json angeht, bei Youtube nutzen die meisten irgendwelche Assets was mich dann komplett verwirrt

Ja, ich fand's verständlich :)

Du bist da schon auf einem guten Weg. Sind nur mit Web Request, Json und dem Bewegen von Daten von A nach B einige Dinge gleichzeitig, die du dir anschauen musst.

Extra Assets brauchst du auch keine. JsonUtility ist nicht perfekt, aber es ist auch echt nicht schlecht. Also nicht zu sehr verwirren lassen ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Super, vielen lieben Dank!

vor 5 Stunden schrieb Sascha:

Mal ein paar Beispiele. Das erste ist immer ein Json-String und darunter ist dann der passende C#-Code, in den du die Daten reinpressen lassen kannst. Ich prettify-e die Json-Daten, indem ich Zeilenumbrüche und Einrückung zwecks Lesbarkeit reintue, macht aber keinen Unterschied.

Danke, damit habe ich das verstanden.

vor 5 Stunden schrieb Sascha:

Du bist da schon auf einem guten Weg. Sind nur mit Web Request, Json und dem Bewegen von Daten von A nach B einige Dinge gleichzeitig, die du dir anschauen musst.

Alles klar, dann mache ich mich an die Arbeit :D

Nochmals danke für deine Hilfe :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 7 Stunden schrieb Sascha:
[System.Serializable]
public struct Thing
{
  public int number;
}

[System.Serializable]
public struct ManyThings
{
  public Thing[] things;
}

Ich frage mich gerade, wo im Skript ich diesen Schritt mache , wenn ich mir die Json Datei durch downloadhandler.text runterlade und JsonUtility anwenden soll.

Im nächsten Beitrag poste ich mal meinen Code für das Aufrufen mit Unitywebrequest mit der darauf folgenden Fallunterscheidung ob ich was beim Aufrufen zurückbekomme Im dritten Fall , will ich mein Json-string mit downloadhandler.text aufrufen und weiter bearbeite. Ich habe verstanden, dass ich 

vor 7 Stunden schrieb Sascha:
JsonUtility.FromJson<ManyThings>(jsonFromAbove);

anwenden muss, aber hier benötige ich ja vorher diesen Schritt.

 

vor 7 Stunden schrieb Sascha:
[System.Serializable]
public struct Thing
{
  public int number;
}

[System.Serializable]
public struct ManyThings
{
  public Thing[] things;
}


 

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class Get : MonoBehaviour
{

    [System.Serializable]
    public struct Thing
    {
        public float x;
        public float y;
        public float dx;
        public float dy;
    }

    [System.Serializable]
    public struct ManyThings
    {
        public Thing[] things;
    }

    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(GetRequest("http://ip.jsontest.com/"));
    }

   
    private IEnumerator GetRequest(string uri)
    {
        using (UnityWebRequest webRequest = UnityWebRequest.Get(uri))
        {
            // Request and wait for the desired page.
            yield return webRequest.SendWebRequest();

            string[] pages = uri.Split('/');
            int page = pages.Length - 1;

            switch (webRequest.result)
            {
                case UnityWebRequest.Result.ConnectionError:
                case UnityWebRequest.Result.DataProcessingError:
                    Debug.LogError(pages[page] + ": Error: " + webRequest.error);
                    break;
                case UnityWebRequest.Result.ProtocolError:
                    Debug.LogError(pages[page] + ": HTTP Error: " + webRequest.error);
                    break;
                case UnityWebRequest.Result.Success:
                   var mythingarray =  webRequest.downloadHandler.text;
                    JsonUtility.FromJson<ManyThings>(mythingarray);
                    
                    break;
            }
        }
    }


}

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 3 Minuten schrieb Haji17:

 var mythingarray =  webRequest.downloadHandler.text;
                    JsonUtility.FromJson<ManyThings>(mythingarray);

Ich habe nur als "Platzhalter" die Variable mythingarray genutzt, da mir Visual Studio angezeigt hat, dass ich eine Zuordnung benötige. Aber jetzt bin ich gerade komplett verwirrt, wie ich das mit JsonUtility und den "Array-Zuordnungen" mache. 

Ich hoffe, ich hab das jetzt mein Problem nicht zu kompliziert aufgezeigt mit den drei Beiträgen, aber das erschien mir übersichtlicher als alles in einem Post.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das sieht schon ganz gut aus. "Get" ist natürlich alles andere als ein guter Klassenname :)

var mythingarray = webRequest.downloadHandler.text;
JsonUtility.FromJson<ManyThings>(mythingarray);

Das stimmt noch nicht so ganz. Die Idee von myThingArray war, dass es das ManyThings-Struct beinhaltet, das die JsonUtility zusammen gebaut hat. Jetzt benutzt du die Variable für den Json-String, bevor daraus etwas gebaut wurde. Sollte eher so aussehen:

var json = webRequest.downloadHandler.text;
var downloadedThings = JsonUtility.FromJson<ManyThings>(json);

Und dann kannst du damit im Anschluss alles machen, was du willst:

Debug.Log(downloadedThings[0].x);

Wobei das natürlich nix wird, wenn du diese url benutzt, weil diese dir eine ganz andere Datenstruktur zurück gibt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 6 Stunden schrieb Sascha:

Das stimmt noch nicht so ganz. Die Idee von myThingArray war, dass es das ManyThings-Struct beinhaltet, das die JsonUtility zusammen gebaut hat. Jetzt benutzt du die Variable für den Json-String, bevor daraus etwas gebaut wurde. Sollte eher so aussehen:

var json = webRequest.downloadHandler.text;
var downloadedThings = JsonUtility.FromJson<ManyThings>(json);

Ah, jetzt hab ich es verstanden danke :)

vor 6 Stunden schrieb Sascha:

Und dann kannst du damit im Anschluss alles machen, was du willst:

Das hab ich mir zu Herzen genommen und mit den Daten weitergearbeitet , ich habe mir überlegt wie ich das Ganze für die Bewegungsumsetzung nutzen kann (siehe nächster Beitrag)

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class Get : MonoBehaviour
{
    private const float ROTATE_SPEED = 90f;
    private const float WALK_SPEED = 2f;
    private const float walkDistance = 10f;

    [System.Serializable]
    public struct Thing
    {
        public float x;
        public float y;
        public float dx;
        public float dy;
    }

    [System.Serializable]
    public struct ManyThings
    {
        public Thing[] things;
    }

    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(GetRequest("http://ip.jsontest.com/"));
    }

   
    private IEnumerator GetRequest(string uri)
    {
        using (UnityWebRequest webRequest = UnityWebRequest.Get(uri))
        {
            // Request and wait for the desired page.
            yield return webRequest.SendWebRequest();

            string[] pages = uri.Split('/');
            int page = pages.Length - 1;

            switch (webRequest.result)
            {
                case UnityWebRequest.Result.ConnectionError:
                case UnityWebRequest.Result.DataProcessingError:
                    Debug.LogError(pages[page] + ": Error: " + webRequest.error);
                    break;
                case UnityWebRequest.Result.ProtocolError:
                    Debug.LogError(pages[page] + ": HTTP Error: " + webRequest.error);
                    break;
                case UnityWebRequest.Result.Success:
                    var json = webRequest.downloadHandler.text;
                    var downloadedThings = JsonUtility.FromJson<ManyThings>(json);

                    var x_aktuell = downloadedThings.things[0].x;
                    var y_aktuell = downloadedThings.things[0].y;
                    var d_x = downloadedThings.things[0].dx;
                    var d_y = downloadedThings.things[0].dy;
                    var aktueller_Winkel = Mathf.Atan(d_y / d_x);
                    var aktueller_Vektor = new Vector3(x_aktuell, 0F, y_aktuell);
                    var aktuelle_Richtung = new Vector3(aktueller_Winkel, 0F, 0F);
                    
                    Debug.Log("Aktueller Vektor ist = " + aktueller_Vektor + "Aktueller Winkel beträgt " + aktueller_Winkel );
                    
                    StartCoroutine(RunAround(aktueller_Vektor));

                    break;
            }
        }
    }

    private IEnumerator RunAround(Vector3 Position)
    {
        while (enabled)
        {
            yield return TurnTowards(Position);
            yield return RunTowards(Position * walkDistance);

        }
    }

    private IEnumerator TurnTowards(Vector3 direction)
    {
        var targetRotation = Quaternion.LookRotation(direction);

        while (transform.rotation != targetRotation)
        {
            transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, ROTATE_SPEED * Time.deltaTime);
            yield return null;
        }
    }

    private IEnumerator RunTowards(Vector3 direction)
    {
        var targetPosition = transform.position + direction;

        while (transform.position != targetPosition)
        {
            transform.position = Vector3.MoveTowards(transform.position, targetPosition, WALK_SPEED * Time.deltaTime);
            yield return null;
        }
    }

}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...