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
1
Question by Beks_Omega · Nov 23, 2017 at 04:04 PM · inputphysics2dfunctionuser interfaceexpression

Predict Where ScrollRect Will Land Based on Velocity

Hello! I know this may not be a normal question but I think you can help me figure it out.

Background: I want to create a scrollrect that snaps onto the elements it's scrolling. So that it always comes to a stop with an element in the center. The scrolling of these scroll rects is based on the velocity your finger was swiping at when it left the screen, and if you input a certain velocity it always moves the same amount (within 1 pixel).

So I figured the smoothest way to create this snapping scroll rect would be to predict where the scroll rect would land & then adjust the deceleration rate so that it landed on the nearest element instead.

So basically I would like to:

  1. Turn this loop into a math function where I can input velocity & get out the movement delta.

  2. Be able to figure out what the deceleration rate should be based on the end movement delta & velocity.

Here's the code that the scroll rect uses for its movement:

 protected virtual void LateUpdate()
 {
      //It's probably easiest if you imagine positionX always starting at 0
      //but I'm no expert

      m_VelocityX *= Mathf.Pow(m_DecelerationRate, Time.unscaledDeltaTime);
      if (Mathf.Abs(m_VelocityX) < 1)
      {
          m_VelocityX = 0;
      }
      positionX += m_VelocityX * Time.unscaledDeltaTime;
 }

Where positionX is the x position of the ScrollRect's content. (it holds the UI elements I want to snap too) ScrollRect Code

And here are some velocities and movement deltas (how far it traveled) where m_DecelerationRate is 0.135 if that's helpful:

Velocity 500 -> 490

Velocity 350 -> 343

Velocity 200 -> 195

Velocity -200 -> -195

Velocity -400 -> -391

Ty all so much for the help! This math is way to hard for me to wrap my head around but I think it will end up being cool!

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 cbauman · Jan 29, 2018 at 06:46 AM 0
Share

I'm working on a tutorial for this type of thing. I'll post a reply sometime in February.

avatar image Beks_Omega cbauman · Jan 29, 2018 at 03:26 PM 0
Share

Sweet I'd love to see it!

1 Reply

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

Answer by cbauman · Feb 15, 2018 at 02:33 AM

Notation Reference:

v0 = initial velocity

vf = final velocity

r = deceleration rate

s(t) = distance/movementDelta at time, t (I know these two terms aren't interchangeable because distance can't be negative, but I already used it this way for my tutorial so...bare with me)

v0 is the velocity when OnPointerUp is called and vf is 1 because that's when Unity manually sets the velocity to 0.

To figure out scroll duration, you can just use the velocity equation (vf = v0 * r^t) to solve for t, since we already know v0, vf, and r.

movementDelta is a little more involved. It starts with one line of calculus. Yes, I know. A little intimidating, but after that it's back to basic algebra. Calculating the distance traveled over time, t is equal to the "area under the curve" of the velocity-time graph. Taking the integral of the velocity equation (v0 * r^t) helps us determine what that area is.

Helpful links if you're not comfortable with calculus:

Video: Why distance is area under velocity-time line

Video: Motion problems with integrals

Article: Intro to Integrals

Integral Cheat Sheet (we use the last equation under "Integrals involving only exponential functions")

alt text


"1. Turn this loop into a math function where I can input velocity & get out the movement delta."

 public float CalculateMovementDelta(float v0, float vf, float r)
 {
     float movementDelta = (vf - v0) / Mathf.Log(r);

     return movementDelta;
 }  



You also have to modify the position update to use the average velocity since the last frame, instead of the end of frame velocity. Otherwise, the ScrollRect code will undershoot the calculated movementDelta every time. The following illustration shows why.


alt text

As you can see, the bigger deltaTime is, the bigger the error. The last graph still isn't perfect, but it does a much better job of balancing the under- and over-shooting of total area (error of only about 0.2 with an initial velocity of 4000, in one of my tests). So, I would modify your LateUpdate function to look like this:

 protected virtual void LateUpdate()
 {
     float prevVelocity = m_VelocityX;
     m_VelocityX *= Mathf.Pow(m_DecelerationRate, Time.unscaledDeltaTime);
     // avgVelocity = low + (high - low) / 2
     float avgVelocity = m_VelocityX + (prevVelocity - m_VelocityX) / 2;
     if (Mathf.Abs(m_VelocityX) < 1)
     {
         m_VelocityX = 0;
     }
     positionX += avgVelocity * Time.unscaledDeltaTime;
 }  




"2. Be able to figure out what the deceleration rate should be based on the end movement delta & velocity."

You just need to adjust the calculated movementDelta to compensate for the nearest element, and send that adjusted movementDelta through the following method to get the required deceleration rate:

 public float CalculateDecelerationRate(float v0, float vf, float movementDelta)
 {
     float decelerationRate = Mathf.Exp((vf - v0) / movementDelta);
 
     return decelerationRate;
 }  




Links

Here's the 3-part video tutorial I recently finished and based this post on:

Part 1: The Intro

Part 2: The Math

Part 3: The Code

Github repo

And these two articles were extremely helpful to me:

Frame Rate Independent Damping Using Lerp

Finding equation for exponential deceleration


dampingdurationdistance.png (95.2 kB)
positionupdatecomparisons-small.png (85.3 kB)
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

86 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

Related Questions

Problems with Input.acceleration in Unity 4.1 1 Answer

Shooting works with PC Keyboard, but not Mobile Touch Controls?! 1 Answer

Input in OnTriggerStay2D 1 Answer

How to successfully apply force calling a function from another script 1 Answer

Raycast from touch, return if hit a specific object. 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