Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question Spring Joint and Hooke's law

Discussion in 'Physics' started by guarnergonzalo, Nov 14, 2022.

  1. guarnergonzalo

    guarnergonzalo

    Joined:
    Nov 15, 2019
    Posts:
    4
    Dear Unity forum,

    I am currently working on simulating springs (a spring-mass-damper system) in Unity. Unfortunately, the in-built spring joint component is not reliably following Hooke's law. This is the case even if setting the damping, tolerance and the rigidbody's drags to zero. Has anyone managed to make it work reliably? Are there any other ways to use the inbuilt physics system for harmonic oscillations? That is, using forces instead of coding the equations directly and using position translations.

    Thanks!
     
  2. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,975
    Any physics simulation (instead of analytic solution) is an approximation. How much of an approximation depends on the timestep size and the quality of the integrator used. See:
    https://gafferongames.com/post/integration_basics/

    So long story short: you won't be able to exactly match any analytic results using a traditional physics engine, not Unity's, not others. You can get close though, by using a smaller fixed delta time. (found in Unity's Time settings)
     
  3. guarnergonzalo

    guarnergonzalo

    Joined:
    Nov 15, 2019
    Posts:
    4
    Hi arkano22, thank you for your reply! Certainly I expect to have an approximated simulation given its time step nature. However, I do not think that this approximation should output such a different resting-state result, it should be pretty much independent of the timestep chosen, should have pointed this concern earlier.

    What I mean by that is given a spring damper system of the form F = -kx - cẋ and F = 9.81 and k = 10, when ẋ = 0 (resting state) x should be x = - F/k = - 0.981. However with the spring joint component it is approx -0.984. If I code the equation in the form below, the output is as expected. Perhaps I'm making a wrong assumption that the "Spring" variable of the component is k in hooke's law.

    Code (CSharp):
    1.     void FixedUpdate()
    2.     {
    3.         float distanceDifference = ConnectedBody.position.y - startPosition;
    4.         float hooke = - K * distanceDifference;
    5.         float dampening = - C * ConnectedBody.velocity.y;
    6.         Vector3 direction = Vector3.up * (hooke + dampening);
    7.         ConnectedBody.AddForce(direction);
    8.     }
    upload_2022-11-15_16-4-57.png upload_2022-11-15_16-7-30.png
     
  4. karliss_coldwild

    karliss_coldwild

    Joined:
    Oct 1, 2020
    Posts:
    606
    0.984/0.981=1.003. 0.3% is probably good enough for most games.

    Just tinkered with it and seems that in the default setup most limiting factor after the spring tolerance option is rigidbody going to sleep once it's speed is bellow certain threshold. Default value is 0.005. Meaning that once the speed for object of mass 1kg falls bellow 0.1 m/s it will stop simulating until its woken up by interactions from script or other physics objects hitting it. You can change the sleep threshold either globally in in Project Settings physics page, or only for individual objects using rigidbody sleepThreshold property.

    The reason you didn't observe this problem when applying force manually is probably because interacting with physics API using methods like AddForce cause the object to wake up. There are of course API for controlling sleep directly.
     
  5. guarnergonzalo

    guarnergonzalo

    Joined:
    Nov 15, 2019
    Posts:
    4
    Hi karliss_coldwild thank you for your response!
    Unfortunately, I'm not programming this for a game but for an app that would require more precision. I set a much lower sleep threshold but the result is very similar. The behavior between the spring joint and my own lines of code is also visibly different, even if using the, in theory, same parameters, as shown above. Another weird occurrence is that increasing the damping at rest state changes the final position. This shouldn't happen since the dampening should only depend on the velocity. Perhaps Unity is modeling the dampening as a force? In any case, I am hesitant to use the spring joint component since I cannot guess the equation behind it, which is relevant to tweak its parameters reliably.
     
  6. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,975
    You might want to check other physics engines, designed with engineering/simulation in mind instead of games. AgX used to have a plugin for Unity, their core engine is quite well designed: https://www.algoryx.se/agx-dynamics/
     
  7. guarnergonzalo

    guarnergonzalo

    Joined:
    Nov 15, 2019
    Posts:
    4
    Noted,I checked it out and their plugin might be what I'm looking for. Thanks!