Question

I'm developing a game with Unity3D.

I have an animation that plays when a sprite is touched then the sprite gets destroyed.

When the the user touches the sprite this triggers the animation and likewise when the mouse cursor touches the sprite this triggers the animation.

The animation gets played 2-3 times though when it's touched. When it's 'touched' by the mouse it works as intended - Animation plays once, sprite is destroyed.

I'm using a coroutine to implement this and this. This is the first time I've used a coroutine so I suspect I'm using it incorrectly.

So here's the code:

private void CheckForTouch()
{
    foreach (Touch item in Input.touches)
    {
        Vector3 touchPosition = 
                                Camera.main.ScreenToWorldPoint(item.position);
        if (collider2D == Physics2D.OverlapPoint(touchPosition))
        {
            StartCoroutine(PlayAnimation());
            break; //Put this in to stop any subsequent touches triggering?
        }
    }

    //Mouse code - this works fine, which is what's confusing me.
    Vector3 touchPositionKeyboard = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    if (collider2D == Physics2D.OverlapPoint(touchPositionKeyboard))
    {
        StartCoroutine(PlayAnimation());
    }
}

private IEnumerator PlayAnimation()
{
    //Setting this to true triggers the animation to be played
    animController.SetBool("Dead", true);
    yield return new WaitForSeconds(touchEvent.length);

    //This destroys the object
    TakeDamage(this.Health);

    //Finally this sets it back to it's idle state
    animController.SetBool("Dead", false);
}

This is all called within an update method

void Update() { CheckForTouch(); }

I've played around with a bool trigger, switching it after the first call of PlayAnimation, to no avail.

What's really confusing me is that it works for for mouse but not for the touch, which makes me think it's not the coroutine.. As it stands i'm pretty lost.

Any help would be appreciated.

Thanks in advance

Was it helpful?

Solution

I would suggest you to surround your platform-specific code with preprocessor directives

#if UNITY_STANDALONE
    // mouse logic
#else
    // touch logic
#endif

test if that solve the issue.

You can also:

Check corresponding Touch.phase value to prevent multiple fire.

Instead of Animator.SetBool consider using Animator.SetTrigger - you should configure it properly in the Animator View.

In the Animation View you can add events to be fired in a frame. Add one in the last frame that will destroy the object. This is the approach I commonly take.

OTHER TIPS

The touch is going through multiple stages, and you start the coroutine for each of those stages.

The touch is first in the TouchPhase.Began phase, then it may be in TouchPhase.Stationary phase, then it gets to TouchPhase.Ended phase. Your CheckForTouch() function receives the same touch for these multiple states. Instead, you can simply add an if to that function to sort this out:

foreach (Touch item in Input.touches)
{
    if (item.phase == TouchPhase.Began) 
    {
        Vector3 touchPosition = ...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top