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 Khena_B · Jul 20, 2018 at 04:13 AM · scripting problemvariablecoroutineloop

Simplify this code

Here's a coroutine, it has two very similar loops that lerps the cam.LerpX or cam.LerpY depending on the CameraBoundary.Mode, the code works fine but whenever I see repeating lines of code it usually means that there is room for improvement, can this be simplified to a single loop? I don't understand how to have a variable that references either cam.LerpX or cam.LerpY.

    IEnumerator TransitionCoroutine(CameraBoundary.Mode mode, bool transitionIn)
     {
         float time = transitionIn ? transitionTime : -transitionTime;
         float lerpValue = transitionIn ? 1 : 0;
 
         if (mode == CameraBoundary.Mode.Vertical)
         {
             while (cam.lerpX != lerpValue)
             {
                 if(cam.lerpX == 1)
                     yield return new WaitForSeconds(0.1f);
                 if (controller.transitioning)
                      yield break;
 
                 cam.lerpX = Mathf.Clamp01(cam.lerpX + time * Time.deltaTime);
                 yield return null;
             }
         }
         else if (mode == CameraBoundary.Mode.Horizontal)
         {
             while (cam.lerpY != lerpValue)
             {
                 if(cam.lerpY == 1)
                     yield return new WaitForSeconds(0.1f);
                 if (controller.transitioning)
                     yield break;
                     
                 cam.lerpY = Mathf.Clamp01(cam.lerpY + time * Time.deltaTime);
                 yield return null;
             }
         }
     }
Comment
Add comment · Show 2
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 Piyush_Pandey · Jul 20, 2018 at 05:57 AM 1
Share

I don't know about the loop but your yield return new WaitForSeconds(0.1f); is not optimised if this Coroutine is called multiple times. Ins$$anonymous$$d you can use

 WaitForSeconds waitOn$$anonymous$$illiSec;
     void Start()
     {
         waitFor$$anonymous$$illiSec = new WaitForSeconds(0.1f);
     }



and now you can use yield return waitFor$$anonymous$$illiSec; ins$$anonymous$$d of yield return new WaitForSeconds(0.1f); everytime

In this way it will not create a new class of WaitForSeconds every time this coroutine is called.

avatar image Khena_B Piyush_Pandey · Jul 20, 2018 at 06:51 AM 0
Share

Thanks, the coroutine is not called often but I didn't know about caching WaitForSeconds, interesting

3 Replies

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

Answer by Khena_B · Jul 20, 2018 at 07:32 AM

I've decided to go with what Strotosome and Sonky108 have suggested:

  IEnumerator TransitionCoroutine(CameraBoundary.Mode mode, bool transitionIn)
 {
     float time = transitionIn ? transitionTime : -transitionTime;
     float lerpValue = transitionIn ? 1 : 0;
     float lerpTarget = mode == CameraBoundary.Mode.Vertical ? cam.lerpX : cam.lerpY;
     WaitForSeconds waitForMillisecond = new WaitForSeconds(0.1f);

     while (lerpTarget != lerpValue)
     {
         if (lerpTarget == 1)
             yield return waitForMillisecond;
         if (controller.transitioning)
             yield break;

         lerpTarget = Mathf.Clamp01(lerpTarget + time * Time.deltaTime);

         if (mode == CameraBoundary.Mode.Vertical)
             cam.lerpX = lerpTarget;
         else
             cam.lerpY = lerpTarget;

         yield return null;
     }
 }

Thanks for the suggestions!

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
2

Answer by Harinezumi · Jul 20, 2018 at 07:28 AM

It is a very good instinct to react to repeating lines with "that could be improved" - it usually is true. In this case a simple factoring out of the block of the branch and eliminating differences with a common variable should do it:

 private IEnumerator TransitionCoroutine (CameraBoundary.Mode mode, bool transitionIn) {
     float time = transitionIn ? transitionTime : -transitionTime;
     float lerpValue = transitionIn ? 1 : 0;

     if (mode == CameraBoundary.Mode.Vertical) { yield return LerpRoutine(cam.lerpX, lerpValue); }
     else if (mode == CameraBoundary.Mode.Horizontal) { yield return LerpRoutine(cam.lerpY, lerpValue); }
 }

 private IEnumerator LerpRoutine (float camLerp, float lerpValue) {
     while (camLerp != lerpValue) {
         if (camLerp == 1)
             yield return new WaitForSeconds(0.1f);
         if (controller.transitioning)
             yield break;

         camLerp = Mathf.Clamp01(cam.lerpY + time * Time.deltaTime);
         yield return null;
     }
 }

Some further possible improvements:
- instead of if-else-if-else... chain use a switch-case for branching on the value of CameraBoundary.Mode (I'm assuming it is an enum)
- as Piyush_Pandey said, cache the wait object (common type is YieldInstruction), even if just as a local variable before the while loop

Comment
Add comment · Show 1 · 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 Khena_B · Jul 20, 2018 at 07:34 AM 0
Share

I've already chosen a solution but thanks for the suggestion, I appreciate it, always happy to discover new ways of doing things

avatar image
1

Answer by Sonky108 · Jul 20, 2018 at 07:10 AM

Without repeating code you try something like this:

     IEnumerator TransitionCoroutine(CameraBoundary.Mode mode, bool transitionIn)
     {
         float time = transitionIn ? transitionTime : -transitionTime;
         float lerpValue = transitionIn ? 1 : 0;
 
         float lerpTarget;
 
         if (mode == CameraBoundary.Mode.Vertical)
         {
             lerpTarget = cam.lerpX;
         }
         else
         {
             lerpTarget = cam.lerpY;
         }
 
         while (lerpTarget != lerpValue)
         {
             if(lerpTarget == 1)
                 yield return new WaitForSeconds(0.1f);
             if (controller.transitioning)
                 yield break;
 
             lerpTarget = Mathf.Clamp01(lerpTarget + time * Time.deltaTime);
             yield return null;
         }
     }

Comment
Add comment · Show 3 · 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 Khena_B · Jul 20, 2018 at 07:17 AM 0
Share

The problem is that this is just going to set lerpTarget and not my camera's LerpX and LerpY variables, cam is my camera script and I'm trying to set the two variables in that script during the loop, lerpTarget would have to be a direct reference to one of those variables, I'm not sure if this is possible, thanks for giving it a try!

avatar image Stratosome · Jul 20, 2018 at 07:18 AM 1
Share

I was thinking about something like that too, but that isn't actually updating the cam.lerpX or cam.lerpY variables (like $$anonymous$$henaB said). I guess this could be added right before the yield return null:

 if (mode == CameraBoundary.$$anonymous$$ode.Horizontal) {
     cam.lerpX = lerpTarget;
 }
 else if (mode == CameraBoundary.$$anonymous$$ode.Vertical) {
     cam.lerpY = lerpTarget;
 }

$$anonymous$$aybe?

avatar image Khena_B Stratosome · Jul 20, 2018 at 07:29 AM 0
Share

That works, it's slightly harder to read but I prefer that over the two loops, thank you both for the suggestions.

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

163 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Looping a Script 2 Answers

How to use a float value from coroutine 1 and use in coroutine 2? 1 Answer

Rerun a script after it finishes, when it already has multiple Coroutines? 1 Answer

How to change a large number of booleans as fast as possible without sacrificing framerate? 1 Answer

pubblic variable don't get change from script with OnTriggerStay 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