2017-09-04 8 views
0

Ich versuche mehrere Objekte gleichzeitig von Punkt A nach Punkt B und wieder zurück zu bewegen, um den Spieler als Hindernisse zu blockieren.Objekte hin- und herbewegen

Ich habe

versucht
StartCoroutine(Oscillate(OscillationFunction.Sine, 1f)); 
    public IEnumerator Oscillate(OscillationFunction method, float scalar) 
    right = GameObject.FindGameObjectsWithTag("MovingObs2"); 
       foreach (GameObject r in right) 
       { 
        startPos = r.transform.position;  
        v = startPos; 
        v.x = (r.transform.position.x + (Mathf.Cos(Time.time) * scalar)); 
        r.transform.position = v; 
        yield return new WaitForSeconds(2); 
        r.transform.position = startPos; 
       } 

und andere, aber sie sind alle schwer innerhalb eines gewünschten Abstand und Geschwindigkeit von der Startposition enthalten. Es ist zu schnell und zu weit.

und ich versuchte eine scheinbar einfachere Linie, die für mich leichter zu verstehen ist.

v.x = l.transform.position.x + speed * Time.deltaTime; 
      l.transform.position = v; 

aber da ich ein Array in einer foreach-Schleife verwenden, ich weiß nicht, wie jeder Gameobjects transform.position zu erhalten, so dass es als Bedingung verwendet werden kann, um die Richtung der umkehren Objekte Bewegung jedes Mal entweder Punkt A oder Punkt B

if (l.transform.position.x <= startPos.x || l.transform.position.x >= startPos.x + endPos.x) 
     { 
      speed *= -1; 
     } 

bearbeiten erreicht: ich entschuldige mich, wenn ich eine doppelte Frage gestellt, ich dachte, es aufgrund der Anzahl der Objekte in einem Array beteiligt anders war.

+1

Warum nicht jedes Objekt mit einem Skript, das an das Objekt angehängt ist, auf seine eigene Bewegung achten, anstatt ein Controller-Objekt zu haben, das versucht, alle zu bewegen? –

+0

Jede Bewegung sollte eine Funktion von 'Time.deltaTime' sein, wie Sie vermutet haben – MickyD

+0

@ScottChamberlain Ich dachte eigentlich, es wäre einfacher und organisiert, wenn es zusammen geschrieben, aber eindeutig lag ich falsch. und ich war zu beschäftigt damit, es zum Laufen zu bringen, und danke für deinen Kommentar, es war erleuchtend. – Seiren

Antwort

1

Ich habe versucht zu übernehmen, um alle Ihre Frage zu lösen, finden Sie in dem Code unten.

Time.deltaTime wird nicht benötigt, da Ihr Code (und mein) die Time.time verwendet, um jedes Mal die Position des Objekts zu berechnen.

Ich würde auch empfehlen (wenn möglich), nicht alles in Skript, sondern geben Sie jedem Objekt ein Swing-Skript und versuchen Sie auch, die CoRoutine nicht zu verwenden. Aber um deine Frage zu beantworten, zeige ich dir, wie es geht.

Ich habe eine interne Klasse erstellt, in der die Zielspielobjekte und ihre startPosition in einer Liste in "Init" gespeichert werden. Später können Sie einfach diese Liste durchlaufen und immer die Startposition haben.

Sie benötigen eine Endlosschleife in der "Osciallate" Routine und müssen jede Umdrehung warten. In Ihrem Beispiel legen Sie das Wait auf den falschen Platz, so dass es nach dem Bewegen jedes Objekts wartet und nach dem ersten Durchlauf durch alle diese Objekte stoppt.

Hier ist der Code:

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

public class OscilateObs : MonoBehaviour { 

    // internal class where all gameobjects and their startposition will be saved 
    internal class OscGameObjects 
    { 
     public GameObject gameObject; 
     public Vector3 startPosition; 
    } 

    // Here the information of all gameObjects stored in a list 
    private List<OscGameObjects> objectList; 

    public float updateSpeed = 0.05f; 
    public float oscScalar = 2f; 

    public enum OscillationFunction { 
     Sine = 1 
    } 

    void Start() { 
     // First, the gameobjects have to saved to our internal List 
     InitializeOscGameObjects(); 

     // Start the Corotine 
     StartCoroutine(Oscillate(OscillationFunction.Sine, oscScalar)); 
    } 

    private void InitializeOscGameObjects() 
    { 
     var objects = GameObject.FindGameObjectsWithTag("MovingObs2"); 

     objectList = new List<OscGameObjects>(); 
     foreach (var o in objects) 
     { 
      var oscObject = new OscGameObjects(); 
      oscObject.gameObject = o; 
      oscObject.startPosition = o.transform.position; 

      objectList.Add(oscObject); 
     } 
    } 

    public IEnumerator Oscillate(OscillationFunction method, float scalar) 
    { 
     // Loop forever 
     while(true) 
     { 
      foreach (var element in objectList) 
      { 
       var currentPosition = element.gameObject.transform.position; 
       currentPosition.x = element.startPosition.x + Mathf.Cos(Time.time) * scalar; 
       element.gameObject.transform.position = currentPosition; 

      } 
      yield return new WaitForSeconds(updateSpeed); 
     } 

    } 

} 

EDIT:

ich meantion vergessen:

1) Ich würde empfehlen, "Animation" Komponente für die Bewegung zu verwenden und mit C# überhaupt nicht , so können Sie das Verhalten bei Bedarf ändern und Sie sind flexibler.

2) Ich würde auch empfehlen, wenn möglich, ein Elternteil "GameObject" zu machen und nur dieses zu bewegen und das "MovingOb2" einfach als Kindobjekte zu setzen.

EDIT2:

Hinzufügen für jedes Objekt ein Verzögerungsinkrement, so dass sie nicht syncron ausgeführt wird:

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

public class OscilateObs : MonoBehaviour { 

    // internal class where all gameobjects and their startposition will be saved 
    internal class OscGameObjects 
    { 
     public GameObject gameObject; 
     public Vector3 startPosition; 
     public float waitCount; 
    } 

    // Here the information of all gameObjects stored in a list 
    private List<OscGameObjects> objectList; 

    public float updateSpeed = 0.05f; 
    public float oscScalar = 2f; 
    public float waitIncrementTime = 0.01f; 

    public enum OscillationFunction { 
     Sine = 1 
    } 

    void Start() { 
     // First, the gameobjects have to saved to our internal List 
     InitializeOscGameObjects(); 

     // Start the Corotine 
     StartCoroutine(Oscillate(OscillationFunction.Sine, oscScalar)); 
    } 

    private void InitializeOscGameObjects() 
    { 
     var objects = GameObject.FindGameObjectsWithTag("MovingObs2"); 

     objectList = new List<OscGameObjects>(); 

     float i = 0; 
     foreach (var o in objects) 
     { 
      i += waitIncrementTime; 
      var oscObject = new OscGameObjects(); 
      oscObject.gameObject = o; 
      oscObject.startPosition = o.transform.position; 
      oscObject.waitCount = i; 
      objectList.Add(oscObject); 
     } 
    } 

    public IEnumerator Oscillate(OscillationFunction method, float scalar) 
    { 
     // Loop forever 
     while(true) 
     { 
      foreach (var element in objectList) 
      { 
       var currentPosition = element.gameObject.transform.position; 
       currentPosition.x = element.startPosition.x + Mathf.Cos(Time.time + element.waitCount) * scalar; 
       element.gameObject.transform.position = currentPosition; 

      } 
      yield return new WaitForSeconds(updateSpeed); 
     } 

    } 

} 
+0

Danke, ich schaue es gerade an, vielen Dank, ich wäre nicht in der Lage gewesen, es selbst zu reparieren. Ich hatte nicht bemerkt, dass ich die Wartefunktion am falschen Ort hatte. und ich fragte mich, warum es sich auch unregelmäßig bewegen würde. – Seiren

+0

Hallo Seiren, vielen Dank und schön zu hören, dass es funktioniert. Bitte vergessen Sie nicht, dies als richtige Antwort zu markieren, wenn dies zu Ihrer Frage passt. Wenn Sie etwas anderes brauchen, lassen Sie es mich wissen. –

+0

Vielen Dank, Christian! Du warst eine große Hilfe. Wenn es kein Problem ist, würde ich gerne fragen, in der Transform.Position für die Liste, wie verzögere ich den Start in Inkrementen? Zum Beispiel bewegt sich das Objekt 1 0,1 Sekunden nach dem Block 1, und das Objekt 3 beginnt sich nach dem Block 2 zu bewegen, und so weiter. – Seiren

0

sie sind alle schwierig, innerhalb eines wünschenswerten Entfernung und Geschwindigkeit von der Startposition zu enthalten, .Es ist zu schnell und zu weit

Bevor Sie mit der Struktur des Codes beginnen nachäffen, empfehle ich Ihnen mit der Kosinus-Funktion bleiben aber bilden Sie sich auf die (sehr einfach) Art und Weise, in der Sie die Ausgangsfrequenz manipulieren kann und Amplitude. Dieses Wissen wird Ihnen gut tun (wenn diese Frage typisch für Ihr durchschnittliches Projekt ist) und wird das Problem trivial lösen.

Wenn es zu schnell ist, können Sie die Frequenz reduzieren (oder die Wellenlänge/Periode erhöhen), indem Sie die Eingabe (die immer absolute Zeit ist) mit einem konstanten Koeffizienten zwischen 0,0 und +1,0 multiplizieren (nicht inklusive).

Wenn es zu weit ist, können Sie die Amplitude reduzieren, indem Sie die Ausgabe mit einem konstanten Koeffizienten zwischen 0,0 und +1,0 multiplizieren (nicht inklusive).

Sie müssen nur zwei Konstanten auswählen und anpassen, indem Sie das Programm ausführen und sehen, wie es Ihnen gefällt.

+0

Vielen Dank für die Erklärung, es gab mir ein wenig mehr Einblick, wie es funktioniert. Ich versuche immer noch zu verstehen, wie die mathematischen Funktionen funktionieren. – Seiren

Verwandte Themen