Jump to content
Unity Insider Forum

Kein Dauer klick bei gedrücktem Button/Taste?


kruemel

Recommended Posts

hi.

 

Ich bin etwas am verzweifeln...

ich suche zwar schon im internet nach ner lösung aber irgendwie weis ich nicht so 100% wie ich es in der suche richtig suchen soll ^^°

 

ich habe folgendes script:

...

if (Input.GetButtonDown("Jump") == true) 
		{
			anim.SetBool ("Jump", true);
			MOVE = false;
			speed = 0.0f;
		}

if (Input.GetButtonUp("Jump") == true)
		{
			anim.SetBool ("Jump", false);
			MOVE = true;
			speed = SAVEspeed;
		}

...

 

leider springt dann der Player per animation andauernd ohne pausen wenn ich den button gedrückt halte.

ich suche nach einer lösung das der button nur einmal auslöst und erst wieder den Player erneut springen lässt wenn der button kurz los gelassen wurde.

 

ich verstehe nur nicht so genau wie ich das anstellen soll...

ich habe schon viel probiert was ich gehofft habe was hilft, aber leider klappt es nicht so wie erhofft 🙁

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

GetButtonDown ist schon richtig, das ist nur im ersten Frame true, in dem gedrückt wird, und dann erst wieder beim nächsten Drücken. Wenn deine Animation also nicht richtig ist, liegt's nicht an diesem Code, sondern vermutlich an deinem Animator Controller. Kannst ja zum Testen mal dieses Script deaktivieren und im Play Mode per Hand das Häkchen bei "Jump" im Animator-Fenster setzen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das Problem liegt an der boolschen Variable.
Sobald du drückst, wird die Jump Variable im Animator auf true gesetzt. Sie wird aber erst wieder auf false gesetzt, wenn du den Button loslässt. Da du den Button aber nicht loslässt, bleibt die Variable auf true.
Im Animator hast du ja eine Transition von einem State zu dem Sprungstate, wo genau dieses true  der Jump Variable abgefragt wird. In der Regel baut man den Animator ja so auf, dass vom Jump State automatisch, nach abspielen der Animation, zurück geblendet wird, z.B. in eine Idle Animation.
Wenn das bei dir auch so ist, wird wahrscheinlich dort wieder eine Transition zum Jump sein, und weil ja Jump immer noch true ist, gehts sofort zurück zur Jump Animation.

Du hast da mehrere Möglichkeiten, dagegen an zu gehen.
Du kannst z.B. die Transition die von Jump zurück geht auf Jump== false hören lassen. Dann musst du erst den Knopf gehen lassen, bevor du wieder in die Idle kommst. Die Jumpanimation würde dann im letzten Frame stehen bleiben, wenn sie nicht loopt.
Du kannst aber auch eine Trigger Variable anstatt der boolschen Variable nutzen. Ein Trigger wird einmalig ausgeführt und setzt sich von alleine zurück.
Du kannst aber auch im Code die Variable ganz schnell zurück setzen, nachdem du sie gesetzt hast, z.B. nach einer 10tel Sekunde.
Oder aber du erzeugst ein Event innerhalb deiner Animation, bei dem in eine Methode im Script rein gesprungen wird. In dieser Methode würde dann die Variable auf false gesetzt.

Was der beste Weg ist, hängt von dem Aufbau deines Animators ab und wie komplex das alles ist.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Sah für mich irgendwie absichtlich aus. Ich hätte jetzt einfach angenommen, dass die Sprunganimation im Animator von alleine in eine Fall-Animation übergeht, aus der der Animator wieder rausgeht, wenn Jump wieder false ist. Naja, so kann's natürlich auch sein.

@kruemel Der Code kann so funktionieren, aber dann muss der Animator Controller halt dazu passen. Wenn du das Problem immer noch hast und noch Hilfe brauchst, solltest du mal deine Animator-State Machine posten.

Link zu diesem Kommentar
Auf anderen Seiten teilen

schonmal vielen dank für die tipps.

 

Mit dem jump auf false setzen hatte ich schon probiert und in der tat da bleibt das letzte frame hängen und sieht dann natürlich dämlich aus ^^°

 

Das mit der trigger variablen hört sich allerding intressant und plausibel an.

Das werde ich wohl mal testen. 😃

 

ist das dann auch ein false/true oder ein wert?

 

wenn ich später oder morgen zeit habe setze ich mich mal ran und versuche mal eure tips umzusetzen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 6 Minuten schrieb kruemel:

ist das dann auch ein false/true oder ein wert?

True und False sind auch Werte :)

Ein Trigger-Parameter ist genau dasselbe wie ein Bool-Parameter, aber man kann ihn nur auf True setzen, und False wird er beim nächsten Update dann automatisch.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 3 Stunden schrieb Sascha:

True und False sind auch Werte :)

Ein Trigger-Parameter ist genau dasselbe wie ein Bool-Parameter, aber man kann ihn nur auf True setzen, und False wird er beim nächsten Update dann automatisch.

 

ja stimmt da hast du recht das sind auch werte 😅

 

habe das gerade mit dem trigger getestet und es funktioniert tadellos.

vielen dank nochmal dafür. 😄

 

nur jetzt weis ich nicht wie ich das beim zb xbox controller mit den LT und RT tasten genau so machen kann das die aktion nur einmalig ausgeführt wird und erst beim loslassen und erneutem drücken wieder geht.

habe da schon ziemlich gesucht damit die tasten überhaupt so angesteuert werden ^^°

habe voll vergessen das diese ja auch einen axen druckpunkt haben.

diesen brauche ich aber allerdings so nicht sondern nur an/aus 😓

Link zu diesem Kommentar
Auf anderen Seiten teilen

GetButtonDown macht nur sehr wenig auf Basis von GetButton. Du kannst dir so etwas problemlos selber bauen:

private bool wasPressed = false;

private void Update()
{
  var isPressed = Input.GetAxis("Trigger") >= 0.5f;
  
  if (!wasPressed && isPressed)
  {
    OnTriggerDown();
  }
  
  wasPressed = isPressed;
}

private void OnTriggerDown()
{
  // ...
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

hm... also das es klappt habe ich schon hin bekommen...

 

...nur leider hängt die animation beim gedrückt halten so auch in einer dauer schleife fest 😕

 

diese soll ja auch nur einmalig ausgefürt werden und dann erst wieder wenn der button kurz los gelassen wird.

da bin ich gerade ziemlich überfragt weil es ja die LT und RT achsen betrifft.

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Der Sascha hat dir doch das Cdebeispiel für das Drücken des Triggers gegeben. Für ein Gehenlassen des Triggers brauchst du natürlich auch wieder eine Abfrage.

Jetzt ist aber die Bedingung

if(wasPressed && !isPressed) 

Also war im Frame davor noch der Trigger gedrückt und ist es jetzt nicht mehr.

Ja und wenn dem so ist, dann springst du z.B. in eine andere Methode rein. Die könnte OnTrggerUp heissen.

Und dann brauchst du noch die dritte Art. Wenn ein Button oder Trigger gehalten wird. Denn dann ist im Frame davor gedrückt gewesen und jetzt auch. Also:
 

if(wasPressed && isPressed)

Alle 3 Abfragen springen entweder in eine Methode rein oder starten ein Event oder setzen eine Varaible auf true. Und da sich alle 3 gegeneinander ausschließen, solltest du ganz einfach jede mögliche Taste oder Achse eines Eingabegerätes definieren können.

Da du einem Spieler immer auch die Möglichkeit geben solltest, sich seine Tasten selbst zu definieren, musst du sowieso etwas bauen, was eine Funktion, wie der Jump, definiert und dann die vom Spieler eingestellte Taste oder Achse in ihrerem Status abfragt. Und da Achsen keine Button sind, musst du mit definierten Werten arbeiten und das Down, Up und Hold eben selbst definieren.

Ach so: LT und RT heben sich gegenseitig auf. Denn der eine Hebel geht von 0 bis 1 und der Andere Hebel von 0 bis -1. Drückst du beide gleichzeitig ist der Rückgabewert die 0.

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 28 Minuten schrieb malzbie:

Ach so: LT und RT heben sich gegenseitig auf. Denn der eine Hebel geht von 0 bis 1 und der Andere Hebel von 0 bis -1. Drückst du beide gleichzeitig ist der Rückgabewert die 0.

Hierzu sei gesagt, dass das an DirectInput liegt, was Unitys Input Manager standardmäßig benutzt. Ich hab bei meinen Projekten einen Wrapper für XInput 1.3, damit ist der XBox-Controller-Support um einiges besser. Das ist also keine Limitierung der Hardware, sondern von der Software, die Unity da benutzt... also kein Problem, das man nicht lösen könnte.

Hat eigentlich mal jemand das neue Input-System ausprobiert, ist das da schlauer? Ich bin von der Funktionsweise des Dings kein Fan, deshalb hab ich damit noch nicht so viel gemacht...

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich habe das neue System noch nicht probiert. Ich nutze momentan XInput.net, weil es zu viele Probleme mit dem alten System gab.
Zusätzlich gab es noch ein Problem mit der Tastatur, denn die 2 Shifttasten haben sich gegenseitig beeinflusst ( Was für einen Flipper sau doof ist).
Das lies sich dann mit PInvoke lösen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

ok ich habe es jetzt so übernommen und soweit klappt es zumindest mit nem dauer loop

 

...

var isPressed = Input.GetAxis("Fire1") >= 0.5f;

		if (!wasPressed && isPressed)
		{
			OnTriggerDown();
		}

		if(wasPressed && !isPressed) 
		{
			OnTriggerUp();
		}

		if(wasPressed && isPressed) 
		{
			OnTriggerStay();
		}


		wasPressed = isPressed;

...


	private void OnTriggerDown()
	{
		anim.SetFloat ("LT_Fire", 1);
	}

	private void OnTriggerUp()
	{
		anim.SetFloat ("LT_Fire", 0);
	}

	private void OnTriggerStay()
	{
		//???
	}

 

nur bekomme ich es nicht wirklich hin das nach einem durchlauf die animation stopt obwohl der button noch gedrückt ist.

entweder kommt ein dauer loop oder aber es klappt garnichts 😥

 

ich hab es mal mit einem WaitForSeconds befehl probiert aber da kommt nur ein fehler bei raus.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ist das vielleicht eine Loop-Animation?

Hier mal ein paar Basics:
Zum Spielstart ruft der Animatior eine Animation auf. Das ist die orangene Animation, die als Default State markiert ist.
Bei einer Character Animation ist das meist die Idle Animation, wo die Figur da so steht und eigentlich nicht viel tut.
Diese Animation ist im Inspector meist auf Loop gestellt, weil er dieses Atmen und runstehen ja die ganze Zeit tun soll.
Ein State muss aber nicht unbedingt eine Animation beinhalten. Das kann auch ein empty State sein, von dem aus dann andere Animationen gestartet werden.

Soweit so gut.

Du übergibst per Code dem Animator irgendeinen Parameterwert, auf den der Animator reagieren soll. Dieser Parameterwert wird bei einer Transition dazu genutz um in einen anderen State überzublenden.
Damit überhaupt von einem State zum anderen State übergeblendet werden kann, muss natürlich eine Transition von jetzigem State zum anderen State bestehen. Kleines Beispiel:
Du hast eine Idle-Animation, eine Duck-Animation und eine Hüpf-Animation. Von der Idle gehen Transitions zu Hüp und auch zu Duck. Von Duck und Hüpf geht es auch wieder zurück zu Idle.
Aber von Hüpf zu Duck (und umgekehrt) gibt es keine Transitions. Würde also z.B. ein Duckparameter anstehen, würde von Idle aus zur Duckanimation geblendet werden. Wenn jetzt auch ein Jumpparameter anstehen würde, dann würde nichts weiter passieren, den Jump kann nur von Idle aus erreicht werden. Der Animator muss also erst irgendwie wieder zur Idle blenden um dann zur Hüpfanimation gehen zu können. Soll aber direkt von Hüpf zu Duck geblendet werden können, musst du extra Transitions anlegen.
Es gibt einen vorgefertigten State der AnyState heisst. Das ist ein besonderes Dingen, denn wenn es eine Transition zur Hüpfanimation gibt, würde bei entsprechendem Parameter auch zum HüpfState geblendet werden, egal in welchem State die Figur gerade ist. Das kann gut sein, muss es aber nicht.

Da der Animator nur das macht, was du ihm sagst, musst du für jedes Überblenden auch Bedingungen (Conditions) abfragen (oder einfach nur die Exittime der Animation nutzen, falls angehakt). Gibt es keine Transition oder hat die Transition keine Bedingung, macht der Animator auch nix und bleibt in dem State, in dem er gerade ist. Ist die Animation da drin auf loop geschaltet, dann wiederholt die sich dauernd. Ist da kein Loop eingestellt, dann hört sie einfach auf.

Willst du beim Drücken z.B. nur eine Salve abschießen und danach soll es wieder zu Idle gehen, dann brauchst du eine Bedingung um zurück zu kommen. Wenn jetzt kein Parameter kommt, der der Transition sagt, dass das Schießen nun vorbei ist, dann kannst du das noch über die Exittime der Animation steuern. Die Animation würde genau einmal durchlaufen und dann würde es automatisch zum anderen State gehen. Steht der Parameter für das Starten der Schussanimation dann aber noch an, wird sofort wieder da hin geblendet. Für dich sieht es dann vielleicht so aus, als würde der Typ dauernd schießen, ohne wieder zu Idle zu gehen.
Das kannst du aber sehen, wenn du dein Spiel nicht im Vollbildmodus startest und nach dem Start mal den Komponente mit dem Animator anklickst. Da siehst du was sich im Animator gerade tut. Du kannst da auch manuell die Parameter steuern und zusehen, wie die Transitions funktionieren.

Bei dir da oben, wird es wahrscheinlich so sein, denn du setzt eine Float Variable die erst dann zurück gesetzt wird, wenn du den Knopf wieder gehen lässt.

Wie ich einige Beiträge davor schon geschrieben habe, kannst du deine Animation mit einem Event bestücken ( dieses senkrechte Rechteck) wo du dann einstellst, in welche public Methode reingesprungen werden soll. Wenn die Animation an dem Event angekommen ist, wird das Event automatisch ausgeführt und wenn dabei dann in eine Methode gesprungen würde, die einfach nur dem Animator sagt, dass LTFire wieder auf 0 gesetzt werden soll. Wäre alles schon gut.
Oder du nutzt einen Trigger oder setzt den Parameter nach einer gewissen Zeit zurück.
 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

wie genau das mit den animationen alles abläuft und mit den conditionen etc da habe ich mich schon länger mit beschäftigt und das system dahinter wann ,was und vor allem wie ablaufen soll aus dem idle modus etc soweit ganz gut verstanden 😊

 

das einzige problem was ich allerdings habe ist das die hinteren schulter tasten ja eine achse haben und somit ich es zwar dank eurer hilfe jetzt schon angesteuert bekomme, die animation aber dann wenn ich die taste LT oder RT gedrückt halte sich endlos wiederholt.

 

Da es sich bei der animation um einen zauber handelt der ca 2 sek in einer animation aufbaut bis er ausgeführt wird und in der zeit aber durch loslassen der LT oder RT tasten abgebrochen werden kann ist es für mich so etwas komplizierter leider 😕

 

bei allen anderen tasten klappt das bisher soweit ganz gut mit der trigger variablen nur eben verstehe ich das system dahinter nicht mit den LT und RT achsen 😩

wieso können die nicht einfach genau so einfach angesteuert werden wie die üblichen tasten 😐

Link zu diesem Kommentar
Auf anderen Seiten teilen

Weils keine Taste ist, sondern eine Achse. Die Trigger sind nichts anderes als ein Joystick, der von rechts nach links oder von oben nach unten geht.
Der Sinn dieser beiden Tasten ist es ein Fahrzeug zu beschleunigen oder zu bremsen und sowas soll ja auch nicht wie ein Schalter passieren, sondern wie ein Pedal.

Aber egal. Dein Problem liegt entweder im Verständnis, wie man aus einem quasi analogen Signal ein digitales Signal macht, oder aber an der Animation selbst.

Hast du denn mal probiert dein gewünschtes Szenario mit ein Button hin zu kriegen? Wenn nein, dann mach das mal, denn ich kann nur vermuten was bei dir nicht funktioniert. Ob ich damit richtig liege kann ich nicht sagen, denn außer deinem Code habe ich nichts gesehen und auch jetzt erst von deinem Zauber erfahren. Und das wäre eine wichtige Info gewesen.

Also teste es mal mit nem Button. Wenns da auch nicht geht, brauchen wir über den Trigger nicht mehr reden. ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

joa das die hinteren tasten für zb autorennen gedacht sind wegen der stufenlosen beschleunigung etc ist mir ja klar.

ich hatte nur gehofft das ich diese auch genau so ansteuern kann wie einen  A, B, X oder Y button 😕 da ich in meinem spiel nunmal die 4 schulter tasten so belegen muss damit die steuerung nicht zu kompliziert wird.

 

oder meintest du mit deiner antwort das man diese auch wie ein button ansteuern kann??? 😳

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 14 Stunden schrieb kruemel:

auf die idee bin ich jetzt noch ned gekommen... 😓

Öh... hatte ich doch weiter oben schon gepostet?

vor 14 Stunden schrieb kruemel:

weil bisher dachte ich immer das diese LT und RT tasten nur float werte geben können.

Ja, können sie ja auch nur. Deshalb musst du eine Grenze setzen (im Beispiel 0.5, also 50%), wie weit man den Trigger runterdrücken muss, damit er wie ein Knopf als "gedrückt" zählt.

Hier landet man aber eben ganz schnell in der Falle, die @malzbie beschrieben hat. Drückst du beide Trigger exakt gleichzeitig runter, bleibt der Wert immer auf 0. Um beide Trigger gleichzeitig und unabhängig voneinander abfragen zu können, musst du vom alten Standard-Input-System weg. Ob das neue System da besser ist, weiß ich nicht. Wie gesagt, @malzbie und ich benutzen beide Plugins für Controller-Support. So eins zu bauen oder auch nur zu besorgen ist jetzt nicht mehr unbedingt Anfängerstoff.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 8 Stunden schrieb Sascha:

Öh... hatte ich doch weiter oben schon gepostet?

äh... ok das hatte ich etwas falsch verstanden dann ^^°

beide hinteren schulter tasten werden zum glück nicht gleichzeitig gebraucht und sollten so eigentlich kein problem geben wenn dann nichts passiert ^^

 

 

ich habe es jetzt mal so probiert wie ich es aus deinem post verstanden habe...

 

...

float RT_Fire = Input.GetAxis ("Fire2");

		if (Input.GetAxis("Fire2") >= 0.5f)
		{
				anim.SetBool ("RT_Fire", true);
				MOVE = false;
				speed = 0.0f;
		}

		if (Input.GetAxis("Fire2") <= 0.4f)
		{
				anim.SetBool ("RT_Fire", false);
				MOVE = true;
				speed = 1.0f;
		}
                                          
 ...                                       

 

Leider springt so der Trigger immer wieder an,aus,an,aus...

obwohl ich den RT Button fest halte.

 

das liegt dann wohl am update per frame wie ich mal stark vermute.

langsam bin ich echt am verzweifeln 😰

 

aber ich habe mir nun gedacht das ich es etwas eigenständig umbauen werde.

 

Ich baue das ganze jetzt so um das ich den float weiterhin benutze und aber nach dem ende der animation eine abfrage starte ob noch genug magie für einen weiteren zauber vorhanden ist.

wenn nein dann setze ich den float auf 0.0f und somit kommt ja dann keine weitere animation.

 

das sollte ja eigentlich die lösung sein.

 

ich habe auch schon etwas im internet gesucht aber leider nicht so ganz verstanden wie man die genaue animations zeit in einem " void Update ()" aus liest.

 

hättet ihr da evtl einen tipp für mich? 😊

 

ansonsten weis ich langsam echt nicht mehr weiter wie ich es anstellen soll 🙁

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 2 Stunden schrieb kruemel:

Leider springt so der Trigger immer wieder an,aus,an,aus...

obwohl ich den RT Button fest halte.

 

das liegt dann wohl am update per frame wie ich mal stark vermute.

langsam bin ich echt am verzweifeln 😰

Klingt, als wäre es eventuell ein Problem in deiner Animation-State Machine.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Grundlegender Hinweis: Wenn etwas nicht funktioniert, und du glaubst, es sei ein Bug in Unity oder so, dann liegt's mit 99.893% Wahrscheinlichkeit in Wirklichkeit an dem, was du gemacht hast ;)

Mit

if (Input.GetAxis("Fire2") >= 0.5f)

kann man einfach nicht sonderlich viel falsch machen. Kannst ja einfach mal einen UI-Text irgendwo hintun und da so ein Script drankleben:

private void Update()
{
  GetComponent<UnityEngine.UI.Text>().text = Input.GetAxis("Fire2") + "";
}

(Kurz und hässlich hingeschrieben...)

Wenn dein Controller nicht irgendwie kaputt ist, dann solltest du damit recht sinnvolle Werte sehen können.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...