Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make Player Flash When Hit

Tags:

c#

unity3d

I'm trying to make my player flash when hit. I have hit detection working. He currently changes to red. I'm wondering how to make the actual flashing occur. Here's a snippet that handles being hit:

if(otherObject.CompareTag("Minion")) //hit by minion
    {
        if(hitFromTop(otherObject.gameObject)) //if player jumped on enemy
        {
            otherObject.GetComponent<Minion>().setMoving(false); //stop moving
            playSound(KillEnemySound); //play killing enemy sound
            jump();
            Destroy(otherObject.gameObject); //kill minion

        }
        else //otherwise, enemy hit player
        {
            if(canTakeDamage)
            {
                changeColor(Color.red);
                loseHealth(1); //lose health
                canTakeDamage=false;
                yield return new WaitForSeconds(1.5f); //delay taking damage repeatedly
                changeColor(Color.white);
                canTakeDamage=true;
            }
            //indicate lost health somehow
        }

Currently, the changing to red is constant (not flashing) and temporary, via the yield return new WaitForSeconds(1.5f);. I could put a couple of these calls, with colour changes in between them, but I was wondering if there was a neater way. I can't be the first one to make something flash in a game.

EDIT: I've added Heisenbug's Flash() code as follows:

IEnumerator FlashPlayer(float time, float intervalTime)
{
    canTakeDamage=false;
    float elapsedTime = 0f;
    int index = 0;

    while(elapsedTime < time )
    {
        Debug.Log("Elapsed time = " + elapsedTime + " < time = " + time + " deltaTime " + Time.deltaTime);
        mat.color = colors[index % 2];
        elapsedTime += Time.deltaTime;
        index++;
        yield return new WaitForSeconds(intervalTime);
    }
    canTakeDamage=true;
}

and it is called here:

void loseHealth(int damage)
{
    //irrelevant details omitted for brevity
            //the "if" checks if the player has run out of health, should not affect the else because this method is called from OnTriggerEnter...see below...
    else
    {
        StartCoroutine(FlashPlayer (1.5f, 0.5f));
    }
}

and here is where THAT is called (in OnTriggerEnter):

    if(otherObject.CompareTag("Minion")) //hit by minion
    {
        if(hitFromTop(otherObject.gameObject)) //if player jumped on enemy
        {
            //irrelevant to the problem
        }
        else //otherwise, enemy hit player
        {
            if(canTakeDamage)
            {
                     loseHealth(1); 
            }
            //indicate lost health somehow
        }
    }

The problem now is that the Flash never stops. It should stop when elapsedTime reaches 1.5f, as I specified, but because it is only incrementing by small amounts (in Time.deltaTime) then it doesn't reach 1.5f for a very long time. Is there anything I've left out that should make it reach 1.5f faster, or is there another number I can pick that I can use accurately to act as a stopping point? The numbers for elapsedTime tend to be: 0, 0.02, 0.03693, 0.054132, etc. very small, so nothing I can really pick from here.

like image 555
muttley91 Avatar asked Apr 19 '13 22:04

muttley91


1 Answers

The following code may be what you are looking for. The object should flash for the total amount of time changing its color after intervalTime

using UnityEngine;
using System.Collections;

public class FlashingObject : MonoBehaviour {

    private Material mat;
    private Color[] colors = {Color.yellow, Color.red};

    public void Awake()
    {

        mat = GetComponent<MeshRenderer>().material;

    }
    // Use this for initialization
    void Start () {
        StartCoroutine(Flash(5f, 0.05f));
    }

    IEnumerator Flash(float time, float intervalTime)
    {
        float elapsedTime = 0f;
        int index = 0;
        while(elapsedTime < time )
        {
            mat.color = colors[index % 2];

            elapsedTime += Time.deltaTime;
            index++;
            yield return new WaitForSeconds(intervalTime);
        }
    }

}
like image 85
Heisenbug Avatar answered Sep 23 '22 11:09

Heisenbug