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 /
  • Help Room /
avatar image
0
Question by Nikolasio · Mar 13, 2016 at 01:02 PM · coroutineloops

Coroutine with multiple Loops

Hi,
I've checked the documentation, tutorials and read relating Q/A but it seems I can't find a solution.
I use a coroutine to place a number in the center of the screen and then move a letter from the center to the one of the four corners of the screen.
The code iterates only once (blink of nr 1 and moves the first letter). But I can't get the print "reached the target" on the console. It seems stuck in the while loop.
Can anybody help me?
Cheers
Nikola

 public IEnumerator PlaceLetter() {
 
             foreach (GameObject nrTemp in numbers) {
                 // Blink for 1sec in the center of the screen
                 GameObject number = Instantiate (nrTemp) as GameObject;
                 number.SetActive (true);
                 yield return new WaitForSeconds (1);
                 number.SetActive (false);
                 Destroy (number); 
                 yield return new WaitForSeconds (1);
 
                     foreach (GameObject goTemp in letters) {
                         // place letter in a corner of the screen
                         GameObject letter = Instantiate (goTemp) as GameObject;
                         letter.SetActive (true);
                         Vector3 currentPosition = letter.transform.position;
 
                             foreach (Vector3 tpTemp in targetPositions) {
                                 while (Vector3.Distance (currentPosition, tpTemp) > 0.1f) { 
                                 letter.transform.position = Vector3.Lerp (letter.transform.position, tpTemp, speed * Time.deltaTime);
                                 yield return null;
 
                                 }
                                 print ("reached the target");
 
                             }
                     }
             }
     }
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

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by Bunny83 · Mar 13, 2016 at 01:21 PM

Yes, of course. That's because you check "currentPosition" in your while loop which isn't updated inside the while loop at all. So you compare two constant values "currentPosition" and "tpTemp". You either want to update currentPosition as well:

 while (Vector3.Distance (currentPosition, tpTemp) > 0.1f)
 {
     currentPosition = Vector3.Lerp (currentPosition, tpTemp, speed * Time.deltaTime);
     letter.transform.position = currentPosition;
     yield return null;
 }

or check for letter.transform.position instead of "currentPosition":

 while (Vector3.Distance (letter.transform.position, tpTemp) > 0.1f)
 {
     letter.transform.position = Vector3.Lerp (letter.transform.position, tpTemp, speed * Time.deltaTime);
     yield return null;
 }

Note: using Lerp that way will result in a non linear motion. The movement will be framerate dependent as it's a non linear function. You basically move towards the target and each step you reduce the distance by a certain percentage of the remaining distance. Since the distance is getting smaller and smaller, the amount you move each step also gets smaller and smaller. Such a progression can't be linearly scaled with Time.deltaTime.

Extreme example: If you have only 1 FPS then Time.deltaTime will be "1". That means after 1 frame (1 sec) you have reached your target. If you have 10 FPS that deltaTime is "0.1". So you reduce the distance by 10% each step. After 1 second You haven't reached your target. Since 0.9^10 is about "0.3487". So the initial distance has been reduced by only 65%. Mathematically you will never reach the target since the amount you get closer gets smaller and smaller. If the initial distance was 1 unit it would take 22 frames (or 2.2 seconds) at a framerate of 10. The time gets longer the higher the framerate is as the percentage is getting smaller at higher rates.

edit

Instead you might want to actually lerp the position in a for loop:

 Vector3 startPos = letter.transform.position;
 for(float t = 0; t < 1f; t += Time.deltaTime/delay)
 {
     letter.transform.position = Vector3.Lerp (startPos, tpTemp, t);
 }

This will move the the letter linearly to the target position within "delay" seconds. If you don't want it to move linearly you can use some hermite spline interpolation. Usually the "blue one" is the one you want:

 public static float Hermite(float t)
 {
     t = Mathf.Clamp01(t);
     return t*t*3f - t*t*t*2f;
 }

Now just replace t in the Lerp with Hermite(t) and your movement will fade in at the start and fade out at the end.

If you don't want a fade in but only a fade out you can use

 public static float FadeOut(float t)
 {
     t = Mathf.Clamp01(t);
     return t*2 - t*t;
 }

This will start linearly and gets slower at the end.

Comment
Add comment · 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
0

Answer by Nikolasio · Mar 14, 2016 at 06:23 PM

Thank's! This clarifies a lot. I indeed prefer to lerp the postion in a for loop. Cheers

Comment
Add comment · 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

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

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

C# Yield WaitForSeconds within For Loop 1 Answer

Using a coroutine to increment a for loop? 0 Answers

My Coroutine Ignores the Boolean 1 Answer

Dynamically update the elements of a List 3 Answers

How to show a "warning" effect before enemy spawns in a 2D shooter? 0 Answers


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