Jump to content
Unity Insider Forum

Schlaganimation bleibt einfach stecken


Simsala Animationen

Recommended Posts

Hallo, für ein Kampffspiel möchte ich eine Schlaganimation einbauen, bei der der Chara während des Schlages sofort anhält. Auch wenn man währenddessen nach vorne drückt.

Das Script dafür ist dieses.

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class AlienDragon : MonoBehaviour {

public GameObject Hitbox;

bool canMove;

float speedFactor = 5;

public Animator anim;

void Start()

{

anim.gameObject.GetComponent<Animator>();

canMove = true;

}

 

 

void Update()

{

 

 

 

 

if (Input.GetKeyDown(KeyCode.Space) && anim.GetBool("attack 0") == false || Input.GetKeyDown(KeyCode.Space) && anim.GetInteger("a") != 3)

{

attacke();

}

else if (canMove == true)

{

if (canMove == true)

{

if (Input.GetKey(KeyCode.RightArrow))

{

 

anim.SetBool("walk 0", true);

transform.Translate(Vector3.forward * Time.deltaTime * speedFactor);

 

}

if (Input.GetKey(KeyCode.LeftArrow))

{

 

anim.SetBool("walk back 0", true);

transform.Translate(Vector3.back * Time.deltaTime * speedFactor);

 

}

if(Input.GetKeyUp(KeyCode.RightArrow)|| Input.GetKeyUp(KeyCode.LeftArrow))

{

 

anim.SetBool("walk 0", false);

anim.SetBool("walk back 0", false);

}

if (Input.GetKey(KeyCode.RightArrow) && Input.GetKey(KeyCode.LeftArrow))

{

 

anim.SetBool("walk 0", false);

anim.SetBool("walk back 0", false);

}

}

}

print(anim.GetInteger("a"));

}

void attacke()

{

canMove = false;

Hitbox.SetActive(true);

anim.SetBool("attack 0",true) ;

 

}

void attackeEnde()

{

 

anim.SetBool("walk 0", false);

anim.SetBool("walk back 0", false);

anim.SetBool("attack 0", false);

Hitbox.SetActive(false);

canMove = true;

}

}

 

mit void attacke() und void attackeende() greife ich auf das Evensystem im prefab zu. Das ganze klappt auch ganz gut. In der idle schlägt er und beendet den Angriff. Drücke ich nach vorne stoppt er, greift an und läuft erst dann weiter. Das gleiche passiert auch beim rückwärts laufen. Also erst mal alles so wie es sein soll.

Doch wenn ich in bei idle-animation angreife und dann nochmal kurz bevor er die Angriffsanimation beendet auf Space drücke, dann bleibt er einfach bei dem Endframe stecken und macht nicht die geringsten anstallten irgend etwas zu unternehmen. Wenn ich nix drücke geht er nicht in die idle zurück und auch bei allem anderen was ich drücke passiert nix.

Dabei müsste er doch selbst wenn der Endframe erwischt wird doch trotzdem wieder irgendwann automatisch zurückspringen. Doch wie eine Statue steht er einfach unbeweglich nur da.

Hatte jemand auch schon mal dieses Problem und weiß woran das liegt und noch besser was man dagegen machen kann?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Poste bitte mal ein Bild von deinem Charakter Controller. Also dem Animator. Dann kann man sich ein besseres Bild von der Gesamtsituation machen :)

Ich guck es mir dann später mal an, evlt postet zwischenzeitlich jemand anders. Aber in "Start" initialisierst du canmove mit true. Das kannst du oben in der Global schon festlegen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Sorry daß ich etwas verspätet schreibe.

Ich hab deinen Code mal bei mir reingeladen in Unity. Ich kann mich jetzt auch nur kurz fassen, da ich aufn Sprung zur Arbeit bin. Hab dich aber nicht vergessen :D

Das Problem das du beschreibst, hat damit zu tun, dass er versucht die Animation erneut zu starten, obwohl er noch gar nicht fertig ist. Dann hängt sich die Animation auf und bleibt nur noch starr. Ich hatte glaub mal ein ähnliches Problem. Ich hab dann einfach eine Coroutine mit eingebaut die eine kleine Pause mit einbaut so lange wie die Animation dauert. Dann gab es da keine Probleme mehr. Dafür kannst du ja wundbar das  

attackeEnde()

mit einbauen. Ein inneres Gefühl sagt mir zwar, dass es vermutlich noch einfacher geht, aber bin selbst noch Anfänger.

Du kannst auch mal gucken bei "Fixed Duration" und der "Exit Time".

Ich hoffe das schubst dich in die richtige Richtung.

 

PS: Du kannst, wenn du unten "Wähle die Dateien hier aus ..." anklickst, mehrere Bilder markieren die dann eingefügt werden. Dann musst du nicht für jedes Bild einen seperaten Post erstellen ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

@SyntaxTalkstoMe Danke erst mal für deine Antwort und viel Spaß bei der Arbeit( wenn man bei Arbeit Spaß haben kann)

 

Das es dieses Problem ist hatte ich bereits auch als Vermutung. Doch wenn ich die Schlagtaste mehrfach spamme, wird die Animation dennoch zu ende ausgeführt. Nur wenn ich durch das spammen genau den Endframe erwische bleibt es stecken. Ich hatte bei meinen Posts leider vergessen die Settings zu zeigen. Man kann aber im ersten Bild sehen das ich bereits "Fixed Duration" aktiviert habe. Dadurch wurde es zwar schon etwas schwerer das ganze zu verursachen doch das Problem ist dennoch da. Die "Exit Time" habe ich auch extra deaktiviert weil es die ganze Situation minimal besser machte. Doch das Problem bleibt.

Mit StartCoroutine habe ich leider nur schlechte Erfahrungen gemacht. Jedes mal wenn ich das benutzt habe, hat es die eingegeben Sekunden nur kurz nach start des Spiels abgefragt und dann endloss das ausgeführt was es nur alle paar Sekunden machen sollte. Bevor ich die Evenst bei Animationen kannte habe ich es sogar damit versucht. Doch das war auch eine Katastrophe. Mal konnte man den Schlag mittendrin abbrechen und mal lief er bis zum Ende. Dann wurde es mal doppelt abgespielt.

Eine andere Methode für eine Zeitverzögerung wäre auch folgendes >

float nextFire;

void (Update)

if(Input.getKeyDown(KeyCode.Space) && Time.time > nextFire)

 

{ nextfire = Time.time + 0.11f(Animationslänge}

Doch leider gibt es immer wieder neue Probleme wenn man bei Schlägen mit Zeitverzögerung arbeitet. Bei meinem Beispiel wäre es das man wieder einen Fehler beim laufen und dann Schlagen hat.

Genau deshalb hatte ich mir eigentlich etwas von den Events bei den Animationen erhofft.

Außerdem ist mir noch ein seltsamer Fehler aufgefallen. Das eigentliche Script habe ich ja schon gepostet. Doch darüber habe ich jetzt noch eine If-Bedingung über alle anderen eingebaut.

if ( anim.GetBool("attack 0") == true && canMove == false)

{

canMove = true;

anim.SetBool("attack 0", false);

anim.SetBool("walk 0", false);

anim.SetBool("walk back 0", false);

print("Warum zur Hölle geht das nicht???!!!!");

 

}

Das und ich habe "CanMove" auf public gesetzt. Wodurch ich beide Booleans ansehen konnte. Sämtliche Bedingungen waren erfüllt. Doch weder "attack 0" wurde auf False gesetzt und auch  "canMove" wurde nicht auf true gesetzt. Allerdings wurde die print-Ausgabe ausgegeben.

Also muss ich entweder doch auf deine Idee zurückgreifen oder sehen ob man die Events doch irgendwie noch fixen kann.

Danke erst mal für die Antwort.

Das das ganze Eventsystem bei den Animationen wohl doch irgendwie verbuggt zu sein scheint, habe ich mich jetzt letztendlich wirklich für eine Zeitverzögerungstacktick entschieden.

public Animator anim;

float nextFire;

bool canMove = true;

float speedFactor = 5;

// Use this for initialization

void Start ()

{

anim.gameObject.GetComponent<Animator>();

}

 

// Update is called once per frame

void Update ()

{

 

if(Input.GetKeyDown(KeyCode.Space) && Time.time > nextFire)

{

canMove = false;

nextFire = Time.time + 1f;

anim.SetBool("attack 0",true);

}

else if (canMove == true)

{

if(Input.GetKey(KeyCode.RightArrow))

{

anim.SetBool("walk 0", true);

transform.Translate(Vector3.forward * Time.deltaTime * speedFactor);

}

if(Input.GetKeyUp(KeyCode.RightArrow))

{

anim.SetBool("walk 0", false);

}

if (Input.GetKey(KeyCode.LeftArrow))

{

anim.SetBool("walk 0", true);

transform.Translate(Vector3.back * Time.deltaTime * speedFactor);

}

if (Input.GetKeyUp(KeyCode.LeftArrow))

{

anim.SetBool("walk 0", false);

}

if (Input.GetKey(KeyCode.LeftArrow) && Input.GetKey(KeyCode.RightArrow))

{

anim.SetBool("walk 0",false);

 

}

}

else if(canMove == false && Time.time > nextFire)

{

canMove = true;

anim.SetBool("attack 0", false);

anim.SetBool("walk 0", false);

}

 

}

}

 Das klappt anscheind wenn man es so macht bisher doch recht gut.

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hehe. Das mit der Coroutine ist ein ein netter Anfängerfehler. Ist mir am Anfang auch passiert. Du hast da offenbar die Coroutine in "Update" reingemacht.

Das bedeutet, dass die Coroutine so und so viel ausgeführt wird pro Frame. Das zwingt deinen Rechner in die Knie. Bei mir zumindest. Da blieb nur ein Unity Restart.

Du machst die Coroutine einfach in "Start" rein.

So in etwa: 

void Start()
{
StartCoroutine(Platzhalter());
}



IEnumerator Platzhalter()
    {
		Attack();

		attack = true;

		yield return new WaitForSeconds(animationslänge);

		attack = false;

    }

So in etwa.  Das packst du in Start oder Awake rein und dann müsste es klappen.

Aber evlt wartest du noch auf die Antwort eines kompetenteren Ansprechpartners :)  

 

Edit: 

Hab auch nochmal nachgeschaut. Ich hatte eigentlich das gleiche Problem und habe es über diesen Weg gelöst gehabt. Evtl nicht die eleganteste, aber es hat gewirkt. Bei mir wurde der Schwerthieb jedesmal unterbrochen und neu gestartet, sobald ich die Attack-Taste gedrückt habe. Das hatte zur Folge, dass die Animation überhaupt nicht fertig abgespielt wurde und immer nur der "Ansatz" davon zu sehen war.

 

Gruß

Link zu diesem Kommentar
Auf anderen Seiten teilen

Stimmt. Du kannst aber trotzdem die Coroutine nutzen. Die Coroutine wird nur dann ständig aufgerufen, sofern du keine Bediengung einbaust. Du brauchst sie ja nur, um eine Pause einzubauen für die Länge der Animation.

Die Coroutine bindest du wie gesagt an irgendeine Bedingung. Dann wird sie einmal ausgeführt. Zum Beispiel  bei dir Attack();

 

Hier ist ein Codefragment aus meinem Spiel wo ein Feuerball geschossen wird. Die Delayzeit ist sowohl die die Schussrate sowohl auch für die Animation gedacht.

Das veranschaulicht was ich meine

 			 canFire = false;

            anima.SetBool("cast2", true);

            AudioSource.PlayClipAtPoint(castFire, gameObject.transform.position);

     CreateFireball();

              yield return new WaitForSeconds(shootRate);
       

            canFire = true;

            anima.SetBool("cast2", false);

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Nach so einigen Tests glaube ich habe ich es endlich.

public GameObject Hitbox;

public bool canMove = true;

public bool canAttack = true;

float speedFactor = 5;

public Animator anim;

public float zeitanpasserfixer;

 

void Start()

{

anim.gameObject.GetComponent<Animator>();

 

}

 

 

void Update()

{

 

if (Input.GetKeyDown(KeyCode.Space) && anim.GetBool("attack 0") == false && canMove && canAttack == true)

{

attacke();

}

else if (canMove == true)

{

if (canMove == true)

{

if (Input.GetKey(KeyCode.RightArrow))

{

 

anim.SetBool("walk 0", true);

transform.Translate(Vector3.forward * Time.deltaTime * speedFactor);

 

}

if (Input.GetKey(KeyCode.LeftArrow))

{

 

anim.SetBool("walk back 0", true);

transform.Translate(Vector3.back * Time.deltaTime * speedFactor);

 

}

if(Input.GetKeyUp(KeyCode.RightArrow)|| Input.GetKeyUp(KeyCode.LeftArrow))

{

 

anim.SetBool("walk 0", false);

anim.SetBool("walk back 0", false);

}

if (Input.GetKey(KeyCode.RightArrow) && Input.GetKey(KeyCode.LeftArrow))

{

 

anim.SetBool("walk 0", false);

anim.SetBool("walk back 0", false);

}

}

 

}

 

 

}

 

 

void attacke()

{

if (canAttack)

{

canAttack = false;

canMove = false;

Hitbox.SetActive(true);

anim.SetBool("attack 0", true);

StartCoroutine("verzogerung");

}

}

IEnumerator verzogerung()

{

 

yield return new WaitForSeconds(0.5f);

anim.SetBool("walk 0", false);

anim.SetBool("walk back 0", false);

anim.SetBool("attack 0", false);

 

yield return new WaitForSeconds(0.5f);

attackeEnde();

}

 

void attackeEnde()

{

Hitbox.SetActive(false);

canMove = true;

canAttack = true;

}

 

}

Bisher konnte ich absolut keinen Fehler bei meinen Tests dabei entdecken. Dazu habe ich nur noch ein einziges Event aktiv, da "attackeEnde" letztendlich durch die 'StartCourontine' aktiviert wird. Danke! Jetzt scheint es endlich voran zu gehen mit meinem Kampfsystem.  Letztendlich haben mir doch die "Courontinous" geholfen die ich so lange vermieden habe, dank dir!

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...