Home > OS >  Creating a function where on collision enemy will be slow and after a set amount of time it reverts
Creating a function where on collision enemy will be slow and after a set amount of time it reverts

Time:11-29

Hello my code is basically on collision it will start the coroutine of slowing the enemy then after 3.2 seconds it reverts back to original.

 private void OnTriggerEnter2D(Collider2D collision)
{
     if (collision.tag == "slowProjectile")
    {
        StartCoroutine(slowEnemy());
    }
}

// FROZEN ENEMY BEHAVIOUR
public bool isFrozen = true;
IEnumerator slowEnemy()
{
    if (isFrozen == true)
    {
        isFrozen = false;
        Debug.Log("FROZEN");
        // Turns the enemy into color blue
        this.GetComponent<SpriteRenderer>().color = Color.blue;
        enemyMovementSpeed = enemyMovementSpeed / 2;

        // waits for 3.2 seconds 
        yield return new WaitForSeconds(3.2f);

        // Then return the enemy movement speed and color to its original state.
        enemyMovementSpeed = enemyMovementSpeed * 2;
        this.GetComponent<SpriteRenderer>().color = Color.white;     
    }
    else
    {
        isFrozen = true;
    }
}

problem is the coroutine is stacking meaning it will run x2 and lost the original value also the projectile fires every 3 seconds. Think of it as A shooter that shoots every 3 seconds and on impact slows the enemy for 3 seconds. ( Like a Snow Pea if you play Plants Vs Zombie )

CodePudding user response:

Other answer is right but adds many coroutines. Here is a solution that uses only one coroutine at a time.

private float m_timer;
private IEnumerator m_coroutine;

private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.tag == "slowProjectile")
    {  
        m_timer = 0f;
        if (m_coroutine == null){
             m_coroutine = FreezeTime();
             StartCoroutine(m_coroutine);
        }        
    }
}

IEnumerator FreezeTime()
{
    while (m_timer < 3.2f){
         m_timer  = Time.deltaTime;
         yield return null;
    }
    m_coroutine = null;
}

When a collision occurs, reset to 0 and if no coroutine is already running, create a new one.

The coroutine keeps increasing the timer, if a collision occurs, it will reset to 0. When done, it resets the coroutine reference.

CodePudding user response:

if what you want is the Frozen effect doesn't stack :

public bool isFrozen = false;

private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.tag == "slowProjectile")
    {
        if (!isFrozen)
        {
            StartCoroutine(slowEnemy());
        } 
    }
}

IEnumerator slowEnemy()
{
    isFrozen = true;
        
    Debug.Log("FROZEN");
    // Turns the enemy into color blue
    this.GetComponent<SpriteRenderer>().color = Color.blue;
    enemyMovementSpeed = enemyMovementSpeed / 2;

    // waits for 3.2 seconds 
    yield return new WaitForSeconds(3.2f);

    // Then return the enemy movement speed and color to its original state.
    enemyMovementSpeed = enemyMovementSpeed * 2;
    this.GetComponent<SpriteRenderer>().color = Color.white;  
        
    isFrozen = false;
}

The downside of the code above is that while the Speed Change doesn't stack, the Frozen Time neither.

If you want to stack the Frozen Time and not stack Speed Change at the same time, maybe you need to add a Forzen Stack Counter to check whether the Frozen time is ended :

public int forenStackCount = 0;

private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.tag == "slowProjectile")
    {          
        StartCoroutine(slowEnemy());
    }
}

private IEnumerator slowEnemy()
{
    if (forenStackCount == 0)
    {
        StartFrozenEffect();
    }

    forenStackCount  ;

    yield return new WaitForSeconds(3.2f);

    forenStackCount--;

    if (forenStackCount == 0)
    {
        EndFrozenEffect();
    }
}

private void StartFrozenEffect()
{
    Debug.Log("FROZEN");
    // Turns the enemy into color blue
    this.GetComponent<SpriteRenderer>().color = Color.blue;
    enemyMovementSpeed = enemyMovementSpeed / 2;
}

private void EndFrozenEffect()
{
    enemyMovementSpeed = enemyMovementSpeed * 2;
    this.GetComponent<SpriteRenderer>().color = Color.white;
}    
  • Related