Garzec Geschrieben 11. September 2017 Melden Share Geschrieben 11. September 2017 Guten Abend, ich versuche die Libelle Sparx aus Spyro nachzubauen, wer nicht weiß, wer das ist hier ein Video Nähert sich Spyro (der Drache) Kristallen, so fliegt Sparx (die Libelle) zu den Kristallen und lässt diese zum Spieler fliegen. Die Logik, dass ein Kristall zum Spieler fliegt habe ich bereits, sagen wir einfach mal die Methode heißt bei mir collectable.StartMovingToPlayer(); So nun hat der Follower einen Rigidbody, damit die Items von seinem Trigger erfasst werden. Da diese Items alle von der abstracten Klasse "Collectable" erben, kann ich im Trigger prüfen, ob das Objekt ein Collectable ist und kann die benötigten Methoden des Items aufrufen. private List<Collectable> collectablesToCollect = new List<Collectable>(); // alle gefundenen Collectables private bool isCollecting = false; // sammelt der Follower aktuell schon ein Collectable ein? private float movementSpeed = 10; // Sammelgeschwindigkeit private void Update() { if (CollectablesInRange()) // Irgendwelche Collectables in Reichweite? { if (!isCollecting) // Aktuell noch nicht am Einsammeln? MoveToCollectable(); // Dann das Item einsammeln } } private void OnTriggerEnter(Collider col) { Collectable collectable = col.GetComponent<Collectable>(); if (collectable != null) // ist das gefundene Objekt ein Collectable? { if (!collectable.GetMovementState()) // Ist das Item noch nicht "aktiviert"? collectablesToCollect.Add(collectable); // Dann der Liste zum Einsammeln hinzufügen } } private void OnTriggerExit(Collider col) { Collectable collectable = col.GetComponent<Collectable>(); if (collectable != null) collectablesToCollect.Remove(collectable); // Item aus der Liste entfernen } private void MoveToCollectable() { isCollecting = true; // Sammelprozess aktivieren Collectable collectable = collectablesToCollect.First(); // das erste Objekt der Liste nehmen Vector3 defaultPosition = transform.position; // Die Ursprungsposition des Followers CollectionMovement(transform.position, collectable.GetCollectablePosition()); // Follower zum Item bewegen collectable.StartMovingToPlayer(); // Item zum Spieler bewegen CollectionMovement(transform.position, defaultPosition); // Follower zurück bewegen collectablesToCollect.Remove(collectable); // eingesammeltes Collectable aus der Liste entfernen isCollecting = false; // Sammelprozess beenden if (CollectablesInRange()) // Noch ein weiteres Item in der Liste? MoveToCollectable(); // Weiter sammeln } private IEnumerator CollectionMovement(Vector3 startPos, Vector3 endPos) { transform.position = Vector3.MoveTowards(startPos, endPos, movementSpeed * Time.deltaTime); yield return null; } private bool CollectablesInRange() // Befinden sich irgendwelche Objekte in Reichweite / in der Liste? { return collectablesToCollect.Count > 0; } Bewege ich mich mit dem Follower zu einem Collectable, so bewegt sich dieses problemlos auf den Spieler zu und wird eingesammelt. Mein Follower bewegt sich aber nicht zum Collectable hin und wieder zurück. Ich gehe davon aus, dass ich die Routine Vector3.MoveTowards() so steuern muss, dass der restliche Code erst danach ausgeführt wird. Wie mache ich denn sowas am geschicktesten? Vielleicht gibt es auch Verbesserungsvorschläge für den Code? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Garzec Geschrieben 13. September 2017 Autor Melden Share Geschrieben 13. September 2017 So, ich habs dann mit der freundlichen Hilfe von @Sascha hinbekommen, sollte es jemanden interessieren, sieht der aktuell funktionierende Code so aus private Transform player; private List<Collectable> collectablesToCollect = new List<Collectable>(); private bool isCollecting = false; private float movementSpeed = 10; private Vector3 currentPosition; private void Start() { player = Globals.GetPlayerObject().transform; } private void Update() { if (CollectablesInRange()) MoveToCollectable(); else FollowPlayer(); } private void OnTriggerEnter(Collider col) { Collectable collectable = col.GetComponent<Collectable>(); if (collectable != null) { if (!collectable.GetMovementState()) collectablesToCollect.Add(collectable); } } private void OnTriggerExit(Collider col) { Collectable collectable = col.GetComponent<Collectable>(); if (collectable != null) collectablesToCollect.Remove(collectable); } private void MoveToCollectable() { Collectable collectable = collectablesToCollect.First(); StartCoroutine(CollectionMovement(collectable)); } private IEnumerator CollectionMovement(Collectable collectable) { if (isCollecting) yield break; isCollecting = true; yield return StartCoroutine(MoveToPoint(collectable.GetCollectablePosition())); if (collectable != null) collectable.StartMovingToPlayer(); yield return StartCoroutine(MoveToPoint(currentPosition)); collectablesToCollect.Remove(collectable); if (CollectablesInRange()) MoveToCollectable(); isCollecting = false; } private IEnumerator MoveToPoint(Vector3 targetPosition) { while (transform.position != targetPosition) { transform.position = Vector3.MoveTowards(transform.position, targetPosition, movementSpeed * Time.deltaTime); yield return null; } } private void FollowPlayer() { // TEST Vector3 playerPos = player.position; currentPosition = new Vector3(playerPos.x, playerPos.y + 2, playerPos.z); transform.position = currentPosition; // TEST } private bool CollectablesInRange() { return collectablesToCollect.Count > 0; } Wobei ich die schrittweise Bewegung, also dass der Follower einen Schritt nach dem anderen abarbeitet, mithilfe von den beiden Enumeratoren löse. Dadurch kann der Follower zum Item hinlaufen, ihn einsammeln und wieder zurücklaufen. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.