Coroutine problem with elevator
Hi everyone.
Can someone resolve my problem ? I ve made an elevator but it doesn't behave as i've expected. there is the code :
public Animator anim, doorAnim;
public bool IsEntered;
public GameObject Player;
void Start () {
IsEntered = false;
}
void OnTriggerEnter () {
IsEntered = true;
}
void OnTriggerExit () {
IsEntered = false;
}
public void onUpperClick () {
if (IsEntered) {// Have to be in the Elevator to activate the button
Player.GetComponent<CharactControl>().SetCanForward (false);// My Player stop walking
doorAnim.SetTrigger ("Close"); // Close the Door of the Elevator
StartCoroutine(wait2seconds()); // Wait that the door is close
anim.SetTrigger ("Up");//Elevator goes to 1th Floor
}
StartCoroutine(wait3seconds()); //Wait that the Elevator has climbed
doorAnim.SetTrigger ("Open");//Open the Door
}
public void onDownClick () {
if (IsEntered) {
Player.GetComponent<CharactControl>().SetCanForward (false);
doorAnim.SetTrigger ("Close");
StartCoroutine(wait2seconds());
anim.SetTrigger ("Down");
}
StartCoroutine(wait3seconds());
doorAnim.SetTrigger ("Open");
}
IEnumerator wait3seconds () {
yield return new WaitForSeconds (3);
}
IEnumerator wait2seconds () {
yield return new WaitForSeconds (2);
}
} Actually the coroutine works great but doesn't stuck the code below the method calling... :'( I understand the problem but i can't resolve it... Thanks
Answer by corn · Jan 28, 2016 at 04:01 PM
You misunderstood how Coroutines work. They do not stop the execution flow of the function that calls them, they are executed separately, on a frame-by-frame basis. Now inside a Coroutine you can indeed stop the execution flow for a designated period of time.
In this case you want to delay execution of some code. You just have to write said code inside the Coroutine, after WaitForSeconds.
Coroutines can also have arguments, so be sure to take advantage of that ! There's no need to write several singular-purpose coroutines, while you can just define one that will work for all your use cases :
IEnumerator DelayedTrigger(Animator anim, string trigger, float delay)
{
yield return new WaitForSeconds(delay);
anim.SetTrigger(trigger);
}
Then you just have to replace
doorAnim.SetTrigger ("Close"); // Close the Door of the Elevator
StartCoroutine(wait2seconds()); // Wait that the door is close
anim.SetTrigger ("Up");//Elevator goes to 1th Floor
With
doorAnim.SetTrigger ("Close");
StartCoroutine(DelayedTrigger(doorAnim, "Up", 2f));
And do the same for all similar operations.
Hi man, i'm currently using what you told me :
public class Elevator_Controller : $$anonymous$$onoBehaviour {
public Animator anim, doorAnim;
public bool isEntered;
public GameObject player;
public bool lastOperation;
public GameObject buttonSound;
public GameObject doorSound;
void Start () {
isEntered = false;
lastOperation = false;
}
void OnTriggerEnter () {
isEntered = true;
}
void OnTriggerExit () {
isEntered = false;
}
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: public void onUpperClick () {
if (isEntered) { // Have to be in the Elevator to activate the button
player.GetComponent<CharactControl>().SetCanForward(false);// $$anonymous$$y Player stop walking
buttonSound.GetComponent<AudioSource>().Play();
if (!lastOperation) {
StartCoroutine (DelayedTrigger (doorAnim, "Close", 0.6f, doorSound, 0.5f));
StartCoroutine (DelayedTrigger (anim, "Up", 2.5f));
StartCoroutine (DelayedTrigger (doorAnim, "Open", 6f, doorSound, 0.05f));
lastOperation = true;
}
}
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: public void onDownClick() {
if (isEntered) { // Have to be in the Elevator to activate the button
player.GetComponent<CharactControl>().SetCanForward(false);// $$anonymous$$y Player stop walking
buttonSound.GetComponent<AudioSource>().Play();
if (lastOperation) {
StartCoroutine (DelayedTrigger (doorAnim, "Close", 0.6f, doorSound, 0.05f));
StartCoroutine (DelayedTrigger (anim, "Down", 2.5f));
StartCoroutine (DelayedTrigger (doorAnim, "Open", 7f, doorSound, 0.2f));
lastOperation = false;
}
}
}
///:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: IEnumerator DelayedTrigger (Animator anim2, string trigger, float delay, GameObject sound, float offset) {
yield return new WaitForSeconds(delay);
anim2.SetTrigger(trigger);
yield return new WaitForSeconds (offset);
sound.GetComponent<AudioSource>().Play();
}
IEnumerator DelayedTrigger (Animator anim2, string trigger, float delay) {
yield return new WaitForSeconds(delay);
anim2.SetTrigger(trigger);
}
} but it doesn't work so well because it can be good for first time and second (not always) and after can goes worse and worse, why ?
hey, i 've also tried something else... Same issue...
public class elevator2 : $$anonymous$$onoBehaviour {
private float timeToDoorAct = 2.25f;
private float timeToDoorAct2 = 2.65f;
private float timeToElevatorUp = 3.0f;
private float timeToElevatorDown = 2.5f;
public Animator anim,doorAnim;
public bool hasLifted;
public bool isEntered;
void Start () {
hasLifted = false;
anim = GetComponent<Animator>();
}
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: void LaunchRaising () {
anim.SetTrigger ("Up");
Invoke ("LaunchOpening", timeToElevatorUp);
hasLifted = true;
}
void LaunchLanding () {
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: anim.SetTrigger ("Down"); Invoke ("LaunchOpening", timeToElevatorUp); hasLifted = false;
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void LaunchOpening () {
doorAnim.SetTrigger ("Open");
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
public void OnUpperClick () {
if (!hasLifted) {
if (isEntered) {
doorAnim.SetTrigger ("Close");
Invoke ("LaunchRaising", timeToDoorAct);
}
}
}
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
public void OnDownClick () {
if (hasLifted) {
if (isEntered) {
doorAnim.SetTrigger ("Close");
Invoke ("LaunchLanding", timeToDoorAct2);
}
}
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void OnTriggerEnter () {
//Quand le Player rentre dans l'ascenseur on peut lancer les interactions
isEntered = true;
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void OnTriggerExit () {
//Quand le Player sort on stoppe les possibilités d'interactions
isEntered = false;
}
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: }
@arkea What's the problem exactly ? (Tu peux écrire en français et en anglais si tu n'es pas très à l'aise avec l'anglais)
En fait, j'ai des décalages qui peuvent surgir de nulle part et du coup les animations prennent plus de temps. C'est trop bizarre en fait,genre par exemple : premier aller retour tout se passe bien, le deuxieme par exemple quand je vais redescendre je vais cliquer sur le boutton "Down" la porte va se fermer et puis peut très bien attendre 2 secondes avant de descendre et du coup faire ouvrir la porte alors que l'ascenseur ne sera pas encore arrivé en bas ><
Your answer
Follow this Question
Related Questions
C# coroutine not waiting on waitForSeconds? 2 Answers
Could not load source 'Coroutines.cs': No source available. 1 Answer
Am I using this Coroutine and IEnumerator correctly? 1 Answer
Trying to make my code pause using coroutines, what am i doing wrong? 2 Answers
Performance Issue with Coroutines 2 Answers