I am working on this Unity 3D game I have been making were you, the player can click random buttons(Don't ask why). In this game I made it were the player can enter a trigger and press E to make the animation trigger only once while clicking it, which perfectly went well. but the only problem is that the "Player" can only make the animation trigger once and than have to leave the trigger and re-enter it to make the animation trigger and work again when pressing E.
My Goal is to have the animation always work when clicking, not holding E everytime when only in the trigger.
this is the code for the button that I have made.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fixedpress : MonoBehaviour
{
public Animator Tributton;
private Coroutine routine;
private void OnTriggerEnter(Collider other)
{
// in general rather use CompareTag instead of ==
// it is slightly faster and also shows an error if the tag doesn't exist instead of failing silent
if (!other.CompareTag("Player")) return;
// just in case to prevent concurrent routines
if (routine != null) StopCoroutine(routine);
// start a new Coroutine
routine = StartCoroutine(WaitForKeyPress());
}
private IEnumerator WaitForKeyPress()
{
// check each FRAME if the key goes down
// This is way more reliable as OnTriggerStay which is called
// in the physics loop and might skip some frames
// This also prevents from holding E while entering the trigger, it needs to go newly down
yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.E));
// set the trigger once and finish the routine
// There is no way to trigger twice except exit the trigger and enter again now
Tributton.SetTrigger("Fiveyon");
Debug.Log("Fiveyon!");
// If you even want to prevent this from getting triggered ever again simply add
enabled = false;
// Now this can only be triggered ONCE for the entire lifecycle of this component
// (except you enable it from the outside again of course)
}
void OnTriggerExit(Collider other)
{
if (!other.CompareTag("Player")) return;
// when exiting the trigger stop the routine so later button press is not handled
if (routine != null) StopCoroutine(routine);
}
}
CodePudding user response:
Instead of starting a coroutine inside onTriggerEnter, just have a bool to be set as true when the player enters the trigger and retrieve the input inside the Update with that bool as a condition. PS: you can also add a cooldown timer so that the player cannot spam E inside the trigger. Example:
bool canAnimate;
private void OnTriggerEnter(Collider other)
{
// in general rather use CompareTag instead of ==
// it is slightly faster and also shows an error if the tag doesn't exist instead of failing silent
if (!other.CompareTag("Player")) return;
// just in case to prevent concurrent routines
if (routine != null) StopCoroutine(routine);
canAnimate = true;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.E) && canAnimate)
{
Tributton.SetTrigger("Fiveyon");
}
}
void OnTriggerExit(Collider other)
{
if (!other.CompareTag("Player")) return;
// when exiting the trigger stop the routine so later button press is not handled
if (routine != null) StopCoroutine(routine);
canAnimate = false;
}
PS: I am sure that there would be a better way to achieve this. Let me know if it helps :)
CodePudding user response:
You need
OnTriggerStay()
You can refer Unity Docs for more details.