Search code examples
c#unity-game-engineunity3d-2dtools

Stop background scrolling after player death animation has finished


Hi I am creating an 2D endless runner. The background has 2 animations - Scroll and stopScroll When the character collides and dies I want to do the following

  1. enable death animation - this is happening
  2. stop the timer - if I do so, all animations stop
  3. stop the background scrolling - this is happening although it happens before the death animation finishes and it jumps back to the fist frame. I want the background to stop relative to the where the character died.
  4. Destroy the character - this is happening but before the animations are completed. I think I need to use Coroutine but dont know how?

Please Help!

Here is my updated code as suggested

void OnCollisionEnter2D(Collision2D other)
{
    if (other.gameObject.name == "Obstacle(Clone)")
    {
        StartCoroutine (DoMyThings(other.gameObject, this.gameObject, false));
    }
}

IEnumerator DoMyThings(GameObject obstacle, GameObject player, bool ninjaObjBool)
{
    ninjaObj = ninjaObjBool;
    Destroy (obstacle);
    animator.SetBool("dead", true);
    yield return new WaitForSeconds(1.2f);
    Destroy (player);
    Time.timeScale=0;
    //timerIsStopped = true;
    yield break;
}

Background Animation I have duplicated a bg sprite and aligned them side by side. The RHS sprite is a child of LHS sprite in the hierarchy. Then I click on the LHS bg sprite -> windows->Animation. Use add curve to transform the bg on the X axis to get it moving infinitely.


Solution

  • First of all, it is not a good practice to find gameobject in Update(). Creating an instance of it might be expected. You can do this like-

    private Ninja ninjaClass;
    .....
    void Awake(){ //You can do it in Start() too if there is no problem it causes
        ninjaClass = GameObject.Find("Ninja").GetComponent<Ninja>();
    }
    
    //Now in Update(),
    
    void Update(){
        if(!ninjaClass.ninjaObj){
            animator.SetBool("stopScroll", true);
        }
    }
    

    Now, OnCollisionEnter2D(), you are setting the Time.timeScale = 0 which will stop every gameobject in the scene that is time dependent (it is good for pausing game). There are many ways to execute the happenings (1.2.3.4). It will be better if you provide codes to show how you are animating and using the timer. But as you mentioned coroutine, i'll show you an example-

    float timer = 0.0f;
    float bool timeIsStopped = false;
    .........
    void Update(){
        if(!timeIsStopped){timer += Time.deltaTime;}
    }
    
    void OnCollisionEnter2D(Collision2D other){
        if (other.gameObject.name == "Obstacle(Clone)")
        {
            StartCoroutine(DoMyThings(other.gameObject, this.gameObject, false));
        }
    }
    
    IEnumerator DoMyThings(GameObject obstacle, GameObject player, bool ninjaObjBool){
        ninjaObj = ninjaObjBool;
        yield return new WaitForSeconds(1.0f);
        animator.SetBool("dead", true);
        yield return new WaitForSeconds(1.5f);
        Destroy(obstacle);
        yield return new WaitForSeconds(2.0f);
        timeIsStopped = true;
        yield return new WaitForSeconds(0.5f);
        Destroy(player);
        yield break;
    }
    

    Hope it will help you to get the idea how to implement your codes.