Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by IvyHorse · Aug 19, 2015 at 07:46 PM · c#coroutineloopbooleaninvoke

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 :(

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by fafase · Aug 20, 2015 at 05:39 AM

 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.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image IvyHorse · Aug 20, 2015 at 11:58 AM 0
Share

Thanks fafase, this is really really helpful, all I had to do was take out the second while loop as my animation has no exit time. Thank you

avatar image IvyHorse · Aug 20, 2015 at 04:42 PM 0
Share

However It's not very time accurate, which unfortunately for me it needs to be, perhaps InvokeRepeating would be more precise?

avatar image fafase · Aug 20, 2015 at 05:02 PM 0
Share

Why is that not? You take the time, then cut it to integer (6 to 6.9), use $$anonymous$$athf.Round other wise (5.5 to 6.5) and check if that value is a multiple of 6. That is what you were after weren't it?

avatar image IvyHorse · Aug 20, 2015 at 05:18 PM 0
Share

Sorry, I didn't mean the maths, I meant the coroutine, for some reason it doesn't work if I collide about a second after it has stopped, basically it works, just not sure why there's that delay after. It's probably my code.

This is what I have

     void Start()
     {
 
         animator = GetComponent<Animator> ();
     }
 
     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;
 
         }
 
     
         animator.SetTrigger ("hit");
         yield return new WaitForSeconds (.1f);
         collided = false;
     
 
 
 
     }
     
 }

I just added WaitForSeconds and it works well now.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

2 People are following this question.

avatar image avatar image

Related Questions

Why isn't my simple coroutine working? (and how can I make it infinite?) 2 Answers

Generic Cooldown IEnumerator? 1 Answer

C# | How to delay a method with parameters 2 Answers

Loop Coroutine For A Demo Mode 1 Answer

trouble looping through voicelines using Coroutine 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges