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 KristofferH · Dec 04, 2016 at 12:10 PM · performancecoroutinelerp

Control lerps with if-statemnts in Update or with Coroutines?

I created a project a while back where buttons in the UI of the app started programmed animations. I had a landscape model that I scaled in the Y axis to morph it from a 2D map into a 3D map and vise versa. I also blended between textures. I did this by triggering coroutines when a UI button was presses. But the problem was that each coroutine had to finish running before the opposite one could run. So when the player choose to morph the map into 3D and then clicked again to morph it back into 2D before the first morphing was complete I ran into problem. The first coroutine simply kept playing until it was finished, and then the other one kicked in, but that made a jump in time and everything became very jerky. I tried using StopSoroutine() but that didn't work. In the end I worked around it by only showing the reverse-button after the coroutine had finished.

But that's not what I want this time in my new project. I want all my lerps to be able to change direction at any time. So if the lerp has reached 75% (goring from 0.0 to 1.0) when a new button is pressed I simply want to update the lerp values so that it changes direction but uses the current value as start value, so it now goes from 0.75 down to 0.0 again.

Can this be done with coroutines, or is it better to just do it inside the Update method and control it with if statements and changing the values on the fly?

The reason I looked into coroutines was because I thought it would give better performance. If the lerp is in the Update method then Unity has to check every frame if the lerp is currently active or not. I'm not sure how expensive an if statement check is though? But morphing the landscape isn't something that the player does very often, hence my idea was simply that rather then checking every frame if the lerp is running, simply off-load it to a separate coroutine and trigger that only when it's needed.

Any advice on how to make this work and be performance gently for mobile devices? :)

Cheers!

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
2

Answer by UnityCoach · Dec 04, 2016 at 02:33 PM

I wouldn't use Coroutines for this. You can simply disable the component whenever the value isn't changing.

Here's some code, using a property that detects if the value changes, so that you only trigger the mechanics when it does change.

I've added a UI Text and a UI Slider for testing purposes.

 using UnityEngine;
 using System.Collections;
 using UnityEngine.UI;
 
 public class LerpBackAndForth : MonoBehaviour
 {
     public Text uiText;
     public Slider uiSlider;
     public float minValue;
     public float maxValue = 1f;
     public float speed = 1f;
 
     private float _lerpValue;
     private bool _forward;
 
     private float _value ;
     public float Value
     {
         get { return _value ; }
         set
         {
             if (value != _value)
             {
                 _value = value ;
                 // TODO : add your mechanics here
                 uiText.text = _value.ToString();
                 uiSlider.value = _value;
             }
         }
     }
 
     void Start ()
     {
         uiSlider.maxValue = maxValue;
         enabled = false; // component disabled upon start
     }
     
     void Update ()
     {
         _lerpValue += (_forward ? speed : -speed) * Time.deltaTime;
         Value = Mathf.Lerp(minValue, maxValue, _lerpValue);
 
         if (_lerpValue <= 0)
         {
             _lerpValue = 0;
             enabled = false;
         }
         else if (_lerpValue >=1)
         {
             _lerpValue = 1;
             enabled = false;
         }
     }
 
     public void Animate (bool forward = true)
     {
         _forward = forward;
         enabled = true;
     }
 
     public void Reverse ()
     {
         Animate (!_forward);
     }
 }

alt text


screen-shot-2016-12-04-at-153210.png (109.2 kB)
Comment
Add comment · Show 5 · 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 UnityCoach · Dec 04, 2016 at 02:53 PM 0
Share

And if you want more control over animation ti$$anonymous$$g, you can drop the Lerp and use Animation Curves ins$$anonymous$$d..

 using UnityEngine;
 using System.Collections;
 using UnityEngine.UI;
 
 public class AnimateBackAndForth : $$anonymous$$onoBehaviour
 {
     public Text uiText;
     public Slider uiSlider;
     public float speed = 1f;
 
     public AnimationCurve forth;
     public AnimationCurve back;
 
     private bool _forward;
 
     private float _time;
 
     private float _value ;
     public float Value
     {
         get { return _value ; }
         set
         {
             if (value != _value)
             {
                 _value = value ;
                 // TODO : add your mechanics here
                 uiText.text = _value.ToString();
                 uiSlider.value = _value;
             }
         }
     }
 
     void Start ()
     {
         enabled = false; // component disabled upon start
     }
     
     void Update ()
     {
         _time += Time.deltaTime;
         Value = _forward ? forth.Evaluate(_time) : back.Evaluate(_time);
 
         if (_time >= forth.keys[forth.keys.Length-1].time)
         {
             enabled = false;
             _time = 0;
         }
     }
 
     public void Animate (bool forward = true)
     {
         _forward = forward;
         _time = 0;
         enabled = true;
     }
 
     public void Reverse ()
     {
         Animate (!_forward);
     }
 }
avatar image KristofferH · Dec 04, 2016 at 10:32 PM 0
Share

Wow, nice! Thank you for such a detailed respons! I will start on this project on $$anonymous$$onday, so I will get back to you later in the week when I have tried this out :)

Follow-up question: could one use Events or Delegates for this? To register when a button has been pressed I mean and then enable/disable the component?

avatar image UnityCoach KristofferH · Dec 04, 2016 at 10:45 PM 0
Share

yes, you could totally use an event that you raise whenever the value changes. I do this very often, so I can split things up and have several behaviours subscribing to on event.

avatar image UnityCoach KristofferH · Dec 04, 2016 at 10:47 PM 0
Share

Something like this :

     public delegate void LerpChange(float lerp) ;
     public event LerpChange lerpChanged;
 
     private float _lerpWithEvent;
     public float LerpWithEvent
     {
         get { return _lerpWithEvent; }
         set
         {
             if (value != _lerpWithEvent)
             {
                 _lerpWithEvent = value;
 
                 // TODO : add your mechanics here
 
                 if (lerpChanged != null)
                     lerpChanged(_lerpWithEvent);
             }
         }
     }
avatar image KristofferH UnityCoach · Dec 04, 2016 at 11:16 PM 0
Share

Cheers mate! I'll give this a go! :)

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

77 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

Related Questions

Performance Issue with Coroutines 2 Answers

Lerping Vectorisity spline 0 Answers

Best way (performance wise) to move multiple objects in certain time 0 Answers

Object lerping forwards a set distance every 3 seconds. 1 Answer

Coroutine: delay transform rotation but start transform movement immediately 2 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