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.
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:
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)
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.
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.
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.
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: AGX Dynamics - Algoryx