Ismoh Geschrieben 11. Januar 2016 Melden Share Geschrieben 11. Januar 2016 Plan war: Puppet2D -> Bones -> Meshes verzerren/ändern -> Unitys Animator benutzen Plan verworfen, weil man beim verzerren der Meshes keine 100%tigen Pixel hinbekommt. Also wird jetzt über ein Spritesheet animiert. Simpel n-Sprites nacheinander anzeigen. Nur wie? ForSchleife und Coroutine/IEnumerator? Ich habe ein Sprite-Array und will das iterieren. Update Methode klappt nicht, da immer das letzte Sprite angezeigt wird, macht Sinn weil die ForSchleife durchgelaufen wird und dann erst gerendert. Dann dachte ich an eine IEnumertor Methode gestartet über StartCoroutine(), aber irgendwie sagt mir mein Bauchgefühl, dass es nicht wirklich die richtige Lösung ist. Kann mich jemand auf den richtigen Weg bringen? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Mark Geschrieben 11. Januar 2016 Melden Share Geschrieben 11. Januar 2016 Das mit der Coroutine erscheint mir doch ganz sinnvoll zu sein. Da kannst du wunderbar festlegen wann der nächste Frame angezeigt werden soll dank der Möglichkeit explizit einen gewisse zeitspanne bis zur Ausführung des nächsten Schrittes warten zu können. http://docs.unity3d.com/ScriptReference/WaitForSeconds.html Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Ismoh Geschrieben 11. Januar 2016 Autor Melden Share Geschrieben 11. Januar 2016 Okay cool Ich mache relativ viel mit Coroutines, deswegen dachte ich, dass es nicht gerade der beste Weg ist, weil es so extrem simpel ist. Aber wenn du das sagst, bleibe ich dann doch bei der ersten Überlegung. Danke Mark. PS: Wo sind deine coolen Profilbilder hin? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Mark Geschrieben 12. Januar 2016 Melden Share Geschrieben 12. Januar 2016 Die wechseln ab und zu Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Ismoh Geschrieben 12. Januar 2016 Autor Melden Share Geschrieben 12. Januar 2016 Ich feier die Viecher total. Ich weiß nur nicht mehr woher ich die kenne.. Ich will hier aber keine plauderrunde starten.. Das ist in diesem Teil des Forums unpassend. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Ismoh Geschrieben 16. Januar 2016 Autor Melden Share Geschrieben 16. Januar 2016 Hallo alle zusammen, ich muss das Thema nochmal aufgreifen: Die Animation - einfaches Sprite-Wechseln in einer IEnumerator Methode - des Charakters funktioniert. Problem ist das Timing: Die Taste → wird gedrückt. Es dauert n-Sekunden und die Walk Animation wird ausgeführt. Ich vermute stark, dass der Tastendruck in der Update Methode sofort ausgewertet wird, sobald das Frame beginnt. Keinen Schimmer von welchen Zeiten wir sprechen, aber ich gehe von Millisekunden aus. Die Coroutine kann sich in dem Moment jedoch in "new WaitForSeconds(n)" befinden. Ich habe leider absolut keine Idee, wie ich das Problem lösen kann. Weiß Jemand Rat? Quellcode folgt. //EDIT: Quellcode public void Start() { rb2d = GetComponent<Rigidbody2D>(); sR = GetComponent<SpriteRenderer>(); currentAnimation = AnimationState.Idle; StartCoroutine(Animate()); } void Update() { MovementTriggers(); if (Input.GetKey(ActionKeyCodes.Instance.Shoot)) { DoShoot(); } } void FixedUpdate() //RigidbodyMovement { if (isGrounded) { rb2d.velocity = velocity; velocity = new Vector2(0, 0); } } void MovementTriggers() { isGrounded = Physics2D.OverlapArea(checkGroundLeft.transform.position, checkGroundRight.transform.position, groundLayer); if (isGrounded) { if (Input.GetKey(ActionKeyCodes.Instance.MoveRight)) { velocity.x = speed; currentAnimation = AnimationState.Walk; } if (Input.GetKey(ActionKeyCodes.Instance.MoveLeft)) { velocity.x = -speed; currentAnimation = AnimationState.Walk; } if (Input.GetKey(ActionKeyCodes.Instance.Run) && (Input.GetKey(ActionKeyCodes.Instance.MoveLeft) || Input.GetKey(ActionKeyCodes.Instance.MoveRight))) { velocity.x *= 2; currentAnimation = AnimationState.Run; } if (Input.GetKey(ActionKeyCodes.Instance.JumpOrMoveUp)) { velocity.y = speed * 2; currentAnimation = AnimationState.Jump; rb2d.AddForce(velocity, ForceMode2D.Force); } } } IEnumerator Animate() { while(this != null) { if (currentAnimation == AnimationState.Idle)//velocity.x == 0)//) { for(int i = 0; i < idleSprites.Length; i++) { sR.sprite = idleSprites[i]; yield return new WaitForSeconds(0.5f); } } yield return null; //Kurze Pause in der Coroutine, da AnimationState geändert worden sein könnte if (currentAnimation == AnimationState.Walk)//velocity.x == Math.Abs(speed))// { for (int i = 0; i < walkSprites.Length; i++) { sR.sprite = walkSprites[i]; yield return new WaitForSeconds(0.5f); } } yield return null; //Kurze Pause in der Coroutine, da AnimationState geändert worden sein könnte if (currentAnimation == AnimationState.Run) //velocity.x == (speed*2))// { for (int i = 0; i < runSprites.Length; i++) { sR.sprite = runSprites[i]; yield return new WaitForSeconds(0.2f); } } yield return null; //Kurze Pause in der Coroutine, da AnimationState geändert worden sein könnte if (currentAnimation == AnimationState.Crouch) { for (int i = 0; i < crouchSprites.Length; i++) { sR.sprite = crouchSprites[i]; yield return new WaitForSeconds(0.5f); } } yield return null; //Kurze Pause in der Coroutine, da AnimationState geändert worden sein könnte if (currentAnimation == AnimationState.Jump) { for (int i = 0; i < jumpSprites.Length; i++) { sR.sprite = jumpSprites[i]; yield return new WaitForSeconds(0.5f); } } yield return null; //Kurze Pause in der Coroutine, da AnimationState geändert worden sein könnte if (currentAnimation == AnimationState.Die) { for (int i = 0; i < dieSprites.Length; i++) { sR.sprite = dieSprites[i]; yield return new WaitForSeconds(0.5f); } } yield return null; //Kurze Pause in der Coroutine, da AnimationState geändert worden sein könnte } yield break; } Ich hatte soeben mal versucht, die Coroutine zu stoppen und anschließend zu starten. Da dieser Aufruf jedoch über die Update läuft, zappelt der gute Herr einfach spaßeshalber rum. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
malzbie Geschrieben 17. Januar 2016 Melden Share Geschrieben 17. Januar 2016 Da du ja scheinbar alles auf Konfiguration (Eingabegeräte und Aussehen soll voll Änderbar sein) ausgelegt hast, nutzt du ja nicht die tollen Möglichkeiten wie z.B. den Animator. Da hättest du es viel einfacher. Nun denn. Ich würde den Spritewechsel NICHT in einer Coroutine machen, da du eben genau dieses Umschaltproblem bekommst. Mach es in der Update oder eine void, die du in der Update aufrufst. Natürlich kannst du jetzt kein WaitForSeconds nutzen, aber das geht ja auch mit der Time.time! // Beispiel für eine Walk-Animation float walkIntervall =0.5f; float walkStartTime =0f; int walkFrame =-1; string oldState ="idle"; // wird gebraucht um bei einer neuen Animation immer mit dem ersten Frame zu beginnen void Update(){ //... deine Abfragen und andere Dinge if(currentAnimation == AnimationState.Walk) Walk(); } void Walk(){ // hier wird rein gesprungen, wenn der Walkstate ansteht if(oldState != "walk"){ // vorher wurde eine andere Animation ausgeführt? Wenn ja dann beginne die Animation von vorne oldState = "walk"; // state setzen walkFrame=-1; // Animation von vorne beginnen } if(walkStartTime+walkIntervall < Time.time){ //wird nur ausgeführt, wenn die Zeit abgelaufen ist walkStartTime = Time.time; if(walkFrame< walkSprites.Length){ walkFrame++; }else{ walkFrame=0; } sr.sprite=walkSprite[walkFrame]; } } Den Code habe ich jetzt so ausm Kopf rein geballert. Könnten Fehler drin sein. Es sollte aber zur Veranschaulichung reichen. Und jetzt komm mir nicht damit, dass es zuviel Code sei! Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Ismoh Geschrieben 17. Januar 2016 Autor Melden Share Geschrieben 17. Januar 2016 Da du ja scheinbar alles auf Konfiguration (Eingabegeräte und Aussehen soll voll Änderbar sein) ausgelegt hast, nutzt du ja nicht die tollen Möglichkeiten wie z.B. den Animator. Da hättest du es viel einfacher. Verstehe ich nicht. Leichter Unterton vorhanden? Ich versuche lediglich einige Lösungsansätze zu suchen und Coroutine kam mir zu dem Zeitpunkt in den Kopf. In meinem jugendlichen Leichtsinn dachte ich, dass die Animation über Quellcode einfacher ist, was aber soeben widerlegt wurde. Ich setze mich dann mal an den Animator. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
malzbie Geschrieben 17. Januar 2016 Melden Share Geschrieben 17. Januar 2016 Ne, so arg war das nicht gemeint. Ich weiß einfach nicht genau, was du erreichen willst. Und wenn ich so sehe, dass du die einzelnen Sprites duchschaltest, anstatt eine Animation damit zu erzeugen und diese dann im Animator zu steuern, gehe ich eben davon aus, dass du das alles konfigurierbar machen willst und deswegen auf Animationsspuren und den Animator verzichtest. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Ismoh Geschrieben 17. Januar 2016 Autor Melden Share Geschrieben 17. Januar 2016 Achso. Nein. Bin einfach nur noch der absolute Unity Anfänger. Ich habe nun die Animationen über "Animation" erstellt und an den Animator weitergeleitet, bzw das hat UNity übernommen. Funktioniert alles wunderbar. Folgende Frage hat sich aber ergeben: Beim Anfang eines Sprungs soll ein Sprite angezeigt werden. Beim Landen des Sprungs soll aber ein anderes Sprite angezeigt werden. Also hat die Jump-Animation zwei Sprites. Ein Sprite beim Frame 0 und das andere soll nun wohin? Problem ist, dass ich irgendwie die Höhe abfragen muss. Sollte ich in dem Fall evtl nicht den Animator nutzen? Oder doch den Animator und dann über einen Parameter "float height"? Ich werkel mal ein wenig. Mal sehen was bei raus kommt. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
malzbie Geschrieben 17. Januar 2016 Melden Share Geschrieben 17. Januar 2016 Wenn das so ist, dann mach dich mit dem Animator vertraut. Erzeuge Animationsspuren für die einzelnen Gegebenheiten und steuere die dann über Transitions im Animator. Diese Transitions reagieren ja auf Variablen, die vom Code her gesetzt werden. Beim Sprung wäre es dann so, dass du z.B. 3 Animationen hintereinander abspielen würdest. Eine fur die Startphase, die immer abgespielt wird. Eine für die Flugphase (was auch nur ein Frame an Animationsdauer sein kann), die dann direkt nach der Startphase geloopt wird. Und eine fürs Landen. Ab wann gelandet wird, ermittelst du mit nem Raycast nach unten und sobald du eine gewisse Höhe erreicht hast, wird diese Landeanimation gestartet (egal wieviele Frames das wirklich sind. Wenn du nur ein Sprite dafür hast, dann ist das halt nur dieses eine Sprite). Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Ismoh Geschrieben 17. Januar 2016 Autor Melden Share Geschrieben 17. Januar 2016 Klasse! Danke werde ich direkt mal ausprobieren. Transitions sind die Verbindungen zwischen den "States", richtig? (die Pfeile) Jep. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Jar Geschrieben 18. Januar 2016 Melden Share Geschrieben 18. Januar 2016 Du könntest auch ein paar Tutorials durchgehen um heraus zu finden was unity dir alles bietet. Hier zum Beispiel ein Tutorial für den Animator Controller https://unity3d.com/learn/tutorials/modules/beginner/animation/animator-controller Beste Grüße, Jar Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Recommended Posts
Archiviert
Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.