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 ulissesnascim · Dec 02, 2019 at 03:30 AM · physicsvelocityspring

Stabilize physics results?

I am making a 2D physics puzzle game where the player sets specific settings in the scenario and then clicks a button to execute a plan, like a Goldberg machine or the The Incredible Machine games.

Now I added a new object (a Spring) which takes into account into account the last known velocity of the object that hit it based on the latest FixedUpdate in order to calculate the force to apply on the rigidbody hit.

For my game to work, I need the physics to work the same way whenever the player selects the same scenario twice. For now, this is going well, but the Spring mentioned above is not working well. I suspect that this is because my FixedUpdates run on slightly different times each time I play, and then the velocity registered is slightly different, leading to different results in the puzzle.

Are there any known solutions to work around this?

Thanks!

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 ulissesnascim · Dec 02, 2019 at 03:36 AM

Note: after a lot of testing, I noted that zeroing the drag and angular drag of the game objects seemes to solve the issue. However, I cannot use this as a solution since the puzzle uses friction as an important component in some of the puzzles.

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 lgarczyn · Dec 02, 2019 at 09:04 PM

The more complex your interactions, the more likely it will be that small differences accumulate. If you want something to act the same every time, you need a scripted event and as little complex math as possible. This is called being deterministic. Unfortunately Unity physics are not deterministic, or at least not if you deal with them in "bad" ways.


Dangerous actions that might break determinism include user input, calls to Random having any effect on the simulation, and doing anything physical in Update.

Using Time.deltaTime instead of Time.fixedDeltaTime in update is considered bad, but won't affect your results. See the documentation.


One of your problem might be that the object does not always hit your spring at the same time of the frame, and therefore the action is slightly different. For example, it may bounce further away during one frame, and therefore receive the force later, giving it a stronger boost. You can solve that by replacing the unity bounce by your own:

When receiving an OnCollisionEnter event with the spring, calculate the position of the ball during collision. This can be done in multiple ways, but the easiest would be to get the last position and velocity, and to do a raycast in the direction of the velocity.

Once that is done, simply Mirror the velocity along the normal of your spring pushing surface.

Set your rigidbody's position to the calculated position, and the velocity to the mirrored velocity.


If you're ok with replacing all bounces by your system, simply set the bounce factor of your ball to 0, and use the collision information to get the impact velocity. Set the velocity to be used for the next frame.


Another simpler way is to detect a collision, then revert your rb's position and velocity back one frame. For the next frame, set the bounce factor of your physics material to a value higher than 1. This is simpler, but if two bounces happen in a single frame you'll have problems. You could try this first to check if it helps you at all.

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 ulissesnascim · Dec 02, 2019 at 10:02 PM 0
Share

Thanks for the help! I was actually already doing my own "bounce" system, which does something really similar to what you suggested: it inverts the ball's velocity vector depending on the sin/cos of the Spring angle.

$$anonymous$$y issue seems to be that, as you said, the collision sometimes registers at different times during the frame, thus getting a different last$$anonymous$$nownVelocity to be inverted. Currently, I'm using FixedUpdate to update my last$$anonymous$$nownVelocity. Should I be using LateUpdate ins$$anonymous$$d?

Also, you have a great point about Unity's native bounce against the Spring which may be a cause for the issue as well. Currently, my ball has a Physics$$anonymous$$aterial2D with zero bounce and my Spring has no custom Physics$$anonymous$$aterial2D. In that scenario, I think the native bounce is already not being simulated, right?

Here is my current code for registering my last$$anonymous$$nownVelocity. The method down below called SetLastImpactForce is called when the spring collides with the ball. The velocityWhenHitVariable is then inverted (according to the Spring angle) and applied to the ball.

  private void FixedUpdate()
      {
          foreach (SpringInteractableData
  springInteractable in
  rigidbodiesInRange)
          {
              Rigidbody2D rb = springInteractable.rigidbody;
              springInteractable.currentVelocity =
  rb.velocity;
          }
  
  
      }
  
  private void
  SetLastImpactForce(Rigidbody2D
  rigidbody)
      {
          foreach (SpringInteractableData
  springInteractable in
  rigidbodiesInRange)
          {
              if (springInteractable.rigidbody ==
  rigidbody)
              {
                  velocityWhenHit = springInteractable.currentVelocity;
                  break;
              }
  
          }
      }

avatar image lgarczyn ulissesnascim · Dec 04, 2019 at 12:30 AM 0
Share

Do not use LateUpdate for physics.


Unless a collision happens, the last known velocity won't change through the frame. The object will simply continue in a straight line, as forces are only applied to the velocity in-between frames. This is very important, objects in unity only follow an approximation of a parabola, made of segments for each frame. The only thing that can change that velocity during the frame is a collision or maybe a Joint (not sure).


I don't know when a rigidbody applies its gravity, but it likely happens at the end of a frame, before the next FixedUpdate. Simply disable it and implement your own gravity to make sure.


I thought about it, the problem might actually come from your custom bounce. From what I'm seeing here it is pretty much spaghetti code. There is absolutely no need for a giant loop or public variables to do this, and I have trouble seeing what you're trying to do. This can all happen using OnCollisionEnter.


If ins$$anonymous$$d of using a script to make the spring bouncy you used a physics material on the head of the spring, you could get the exact same effect. Simply make the ball bounce normally, and the head of the spring very bouncy, with a "$$anonymous$$aximum" bounce combine.


I'm sorry for switching from "don't use Unity's bounces" to "use Unity's bounces", but the reveal of your own bounce system makes it a more likely culprit than Unity's physics engine.

avatar image ulissesnascim lgarczyn · Dec 07, 2019 at 10:22 PM 0
Share

Actually, I can't do that inside the OnCollisionEnter because the velocity is already much slower due to the collision itself. What I then needed to do was create a class that would store the last known velocity. This was also useful for doing a "moving average" of sorts in order to get a more stable last velocity each time. Oh, and the loops aren't an issue as my game has very few interactable objects near the springs.

I like both your other suggestions (making a custom gravity or using Unity's bounce). I've run a couple of tests with the latter and it seems to work. I will post my progress when I'm sure it works.

Thanks!

Show more comments

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

263 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image 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

Adding velocity to an object in a brick breaker game 0 Answers

Stop drag on ball rolling down hill 0 Answers

[2D] Velocity increases faster after large force is applied. 0 Answers

Proper way to set a RigidBody's maximum velocity 1 Answer

Trying to get perfect jumps with Character. 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