make events occur only at specific times

I want to make an object animate ( and a few other things) when the player collides with it, but I only want this animation to occur when the game time (Time.time) is a multiple of 6. so for instance I collide with the object 9.5 seconds into the game, but the animation doesn’t occur for another (12 - 9.5) = 2.5 seconds, then once it is animated and the player collides with it, at say 16 seconds into the game, the animation should stop again when the time reaches 18, so 2 seconds after collision, and so on infinitely. I’ve written a script that does this for the most part, the problem I’m experiencing is that it works for the first collision, but once it’s animated and collided with it stops immediately, as in at 16 seconds, from my example. I’m using Coroutines to add the delay after collision, but perhaps this is the wrong method?

I should add that it does seem to work if I collide with object within maybe a second of when it should change, so collide around 17 seconds, it stops at 18 as it should.

Here’s my code:

public class SwitchController : MonoBehaviour {

	private float rpm = 10f;
	private GameObject paperRings;
	private Animator animator;
	private bool spinActivated ;
	private float multipleof = 6f;

	void Start () 
	{

        paperRings = GameObject.FindGameObjectWithTag ("paperrings");
		animator = GetComponent<Animator> ();
	}

	// To find the delay
	private float RoundToNearestMultiple()
	{
		int multiple =  Mathf.RoundToInt(Time.time/multipleof);
		
		return multiple*multipleof;
	}
	
	private float Wait() 
	{
		return RoundToNearestMultiple () - Time.time;
	}


	void Update()
	{
		
		
		if (spinActivated == true) 
		{
			paperRings.transform.Rotate (0, 0, 6 * rpm * Time.deltaTime);
			animator.SetBool ("spinning", true);
			
		}
		
		if (spinActivated == false) 
		{
			animator.SetBool ("spinning", false);
			
		}
	}

	IEnumerator Spin()
	{
		yield return new WaitForSeconds(Wait());
		spinActivated = true;
		yield return null;

	}

	IEnumerator StopSpin()
	{
		yield return new WaitForSeconds(Wait());
		spinActivated = false;
		yield return null;
		
	}


	
	void OnCollisionEnter2D(Collision2D col)
	{
		if (col.gameObject.tag == "song" && spinActivated == false )

        {
			StartCoroutine(Spin ());
		}

		if (col.gameObject.tag == "song" && spinActivated == true) 
		{
			StartCoroutine (StopSpin());
		}
    } 

}

I’ve changed it a little, I think the problem is I need to calculate how long to wait at the point of collision, but I’m having trouble with the syntax. This is basically it

using UnityEngine;
using System.Collections;

public class SwitchController : MonoBehaviour {
	

	void OnCollisionEnter2D(Collision2D col)
	{
		if (col.gameObject.tag == "song" )
			
		{
			StartCoroutine("Spin");
		}
		
	}
	
	IEnumerator Spin()
	{
		float wait = (((Mathf.RoundToInt(Time.time/6f)) * 6f) - Time.time);
		yield return new WaitForSeconds(wait);
		Debug.Log("Hi");
		
		
	}
}

but it doesn’t work :frowning:

private bool collided = false;
void OnCollisionEnter2D(Collision2D col){
if(collided == false)
StartCoroutine(AnimationCoroutine());
}

IEnumerator AnimationCoroutine(){
    collided = true;
    while (true){
        int timer = (int)Time.time;
        if((timer % 6) == 0) {break;}
        yield return null;
    }
    // Start animation
   while ( animation.isPlaying ){
        yield return null;
   }
   collided = false;
}

So the idea is that you collide and start the coroutine. The collided bool makes sure you don’t call many times as a sprite can have two collision points (or more on complex polygon).

the first while loop waits for the time to be a multiple of 6. The second loop waits for the animation to be done.