Jump to content
Unity Insider Forum

Transform. Translate Problem


xDeejox

Recommended Posts

Grüße euch 

Hab mal wieder ein Problem 🙄

Und zwar will ich dass mein Spieler, wenn ich die Taste "A" z. B drücke, sich auf der X-Achse automatisch ein paar Koordinaten fortbewegt. Sagen wir von 

X = - 7 auf X = 7 

Habe es mit translate probiert, aber ich muss jedes mal "A" betätigen damit er vorwärts kommt. Habe es auch mit einer for-Schleife probiert aber funktioniert auch nicht wirklich. Weiß nicht ob NavMeshAgent eine Alternative wäre, kenn mich damit nur nicht wirklich aus. Vielleicht denk ich einfach zu kompliziert und stehe aufm Schlauch. 

Danke schonmal für die Hilfestellungen. 

Mfg. Deejo

Link zu diesem Kommentar
Auf anderen Seiten teilen

Du musst dir ein Bild davon machen, wie ein Spiel funktioniert. Du hast eine Dauerschleife, die pro Sekunde so oft durchläuft wie du FPS hast. Wenn die Grafikkarte also nicht überfordert ist und du einen normalen Bildschirm hast, 60-Mal in der Sekunde. In jedem Durchlauf lässt Unity die Logik deines Spiels ein Stück weiterlaufen (Update) und wenn das fertig ist, wird die veränderte Welt neu gezeichnet (Draw). Das kann man sich wie bei Stop Motion-Filmen vorstellen: Die Welt wird hier und daq geändert und dann wird ein Foto gemacht.

Wenn du willst, dass etwas über einen Zeitraum hinaus passiert, musst du dafür diese Schleife für dich nutzen. Du bewegst ein Ding viele Male ein kleines Stück, und daraus entsteht Bewegung. Du baust also keine eigene Schleife in Update, denn diese würde ja zwischen zweimal zeichnen komplett durchlaufen. Das wäre dann das Äquivalent davon, ein Objekt ganz oft zu bewegen, aber zwischendurch kein Foto zu schießen. Von den kleinen Schritten zwischen den zwei Fotos sieht man dann im Film nichts.

Im Code sieht das dann z.B. so aus:

private void Update()
{
  if (Input.GetKey(KeyCode.A))
  {
    transform.Translate(Vector3.right * speed * Time.deltaTime);
  } 
}

Hier wird in jedem Update, also immer "zwischen zwei Fotos", geschaut ob gerade A gedrückt gehalten wird, und wenn ja, wird das Objekt ein kleines Stück weiter verschoben.

Wenn ich deinen Post aber richtig verstehe, willst du einmalig A drücken und dann bewegt sich dein Objekt zu einer Zielposition, richtig? könnte man dann so machen:

private Vector3 targetPosition;

private void Awake()
{
  targetPosition = transform.position;
}

private void Update()
{
  if (Input.GetKeyDown(KeyCode.A))
  {
    targetPosition = new Vector3(7, 0, 0);
  }
  
  transform.position = Vector3.MoveTowards(transform.position, targetPosition, speed * Time.deltaTime);
}

Wir schauen in jedem Update, ob A gerade frisch gedrückt wurde (GetKeyDown) und wenn ja, wird eine neue Zielposition gesetzt. Außerdem bewegen wir uns in Update konstant auf die aktuell gesetzte Zielposition zu, wo auch immer die gerade ist.

Wie du siehst, ist hier keine eigene Schleife nötig, da Update ja bereits auf der Hauptschleife des Spiels immer wieder aufgerufen wird.

Es gibt halt auch noch die Coroutine-Variante, bei der man eine eigene Schleife schreiben kann und dann innerhalb der Schleife einen "Warte einen Frame"-Befehl einfügen kann, aber den halte ich bei diesem Beispiel für den unnötig komplizierteren Weg :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

@Sascha danke dir, genau dass richtige.

Stand wohl doch aufm Schlauch, darauf wäre ich glaub nicht so schnell gekommen.

Und jetzt wo du es sagst, logisch das Update auch ne Schleife ist "auf Stirn hau" glaub meine Logik war, einfach den For-Loop außerhalb der UpdateMethode ablaufen zulassen

aber denk das hätte glaub auch nichts gebracht.

Also vielen Dank, hast mir sehr viel Zeit und Nervenzellen erspart.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Guten Abend,

Habe jetzt leider dass nächste Problem, hätte es wohl gleich dazu schreiben sollen, aber ich bin zu ehrgeizig und Versuche es einen gewissen Zeitraum selber zu lösen.

Ich möchte jetzt dass mein player sagen wir Mal ca. 5sec wartet und dann wieder auf seine ursprüngliche Position zurück kehrt. 

Link zu diesem Kommentar
Auf anderen Seiten teilen

So selber gelöst. Hier ist der Komplette Code, für alle die es vielleicht auch mal brauchen.

public class Player : MonoBehaviour
{
    
    public float moveSpeed = 5f;
    private Vector3 targetPosition;

    // Start is called before the first frame update
    void Awake()
    {
        targetPosition = transform.position;
        
    }

    // Update is called once per frame
    public void Update()
    {
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            targetPosition = new Vector3(6, 0, 0);

            StartCoroutine(back());
        }
        

        transform.position = Vector3.MoveTowards(transform.position, targetPosition, moveSpeed * Time.deltaTime);
    }

    IEnumerator back()
    {
        yield return new WaitForSeconds(4);

        if (transform.position == targetPosition)
        {
            targetPosition = new Vector3(-7, 0, 0);  
        }

        

    }



}

Mit freundlichen Grüßen Deejo

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das ist eine schöne Variante. Man hätte auch die Coroutine für die Bewegung selbst benutzen können, aber so finde ich das auch sehr gut. Ich würde nur noch einmal draufschauen, ob dir das Verhalten passt, wenn man innerhalb der vier Sekunden Wartezeit noch einmal klickt. Dann läuft die Coroutine nämlich zweimal. Wenn man also nach zwei Sekunden ein zweites Mal klickt, dann läuft die Coroutine nur noch zwei Sekunden weiter und bewegt danach schon wieder zurück, und die neue Coroutine läuft ab dann 4 Sekunden, was wiederum die Reaktion auf den nächsten Klick beeinträchtigt.

Lange Rede, kurzer Sinn: Vielleicht willst du vor dem StartCoroutine() einmal ein StopAllCoroutines() reinpacken, damit die Wartezeit auch wirklich von vorne anfängt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...