{"id":438,"date":"2024-08-08T13:15:49","date_gmt":"2024-08-08T12:15:49","guid":{"rendered":"https:\/\/blog.powered-up-games.com\/wordpress\/?p=438"},"modified":"2024-10-25T20:03:33","modified_gmt":"2024-10-25T19:03:33","slug":"unity-impulses","status":"publish","type":"post","link":"https:\/\/powered-up-games.com\/blog\/wordpress\/archives\/438","title":{"rendered":"Unity impulses"},"content":{"rendered":"\n<p>As I covered in my <a href=\"\/blog\/wordpress\/archives\/427\">previous blog post<\/a>, the Unity physics simulation falls somewhat short when simulating classical mechanics. Having analysed the problem, it seems that the error is bounded. Unfortunately, this error is fairly significant for distances and forces in the typical range for a video game.<\/p>\n\n\n\n<p>A typical use for game physics is to simulate a jump. The average human jump height is about 40cm and the current world record for a standing jump is 170cm. Calculating the velocities required using the standard equation and running the simulation, the jump heights fall short by 2.8cm for a 40cm jump and 5.7cm for a 170cm jump.<\/p>\n\n\n\n<p>A small part of that error (less than 1mm) is due to the actual peak of the jump not landing on an exact physics frame. According to Unity, the majority of the error comes from PhysX and its use of the <a href=\"https:\/\/adamsturge.github.io\/Engine-Blog\/mydoc_symplectic_euler.html\">symplectic Euler method<\/a> to perform physics updates.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/LSBUGPG\/PhysicsBug\/42a91c5eaffbf9ce39f6f9f2ed025634201a5ada\/accuracy.png\" alt=\"a graph showing how short the peak of the jump will be for heights between 40cm and 170cm as a purple line compared to a target orange dotted line\"\/><\/figure>\n\n\n\n<p>You might think from the above graph, that the error is increasing as the size of the jump increases. And that is true in terms of the absolute error. However, the purple line, representing the peak height reached at each jump height, is actually slowly curving towards a line parallel to the target dotted line. So as you go out to 100m, the errors become relatively less significant.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/LSBUGPG\/PhysicsBug\/86a7f599d28d5bdb718e912d66f467672922f01b\/accuracy-large.png\" alt=\"A graph showing that the shortfall at distances up to 100m is barely visible\"\/><\/figure>\n\n\n\n<p>Conversely, as you go down to smaller distances, the shortfall becomes so large that attempting a jump of less than 2mm you would not even get off the ground.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/LSBUGPG\/PhysicsBug\/86a7f599d28d5bdb718e912d66f467672922f01b\/accuracy-small.png\" alt=\"a graph showing that the relative error increases at smaller scales\"\/><\/figure>\n\n\n\n<p>There go my plans for <em>Insect Adventure<\/em>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">As symplectic as possible<\/h2>\n\n\n\n<p>The symplectic Euler method applied to physics updates goes something like this:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#39404f;color:#c8d0e0\">C#<\/span><span role=\"button\" tabindex=\"0\" data-code=\"void PhysicsUpdate()\n{\n\tvelocity = velocity + acceleration * dt;\n\tposition = position + velocity * dt;\n}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PhysicsUpdate<\/span><span style=\"color: #ECEFF4\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #D8DEE9\">velocity<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">velocity<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">acceleration<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">dt<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #D8DEE9\">position<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">position<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">velocity<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">dt<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The order of the operations is important here. The position is updated with the already modified velocity.<\/p>\n\n\n\n<p>To see what effect this has on the displacement of objects over time, we&#8217;ll have to find a function which applies these modifications for each physics update. Mathematically, the displacement after <em>n<\/em> updates is:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>s(n) = \\sum_{k = 1}^n (v(k) \\cdot \\Delta{t})\n<\/pre><\/div>\n\n\n\n<p>Where <em>v(n)<\/em> is the velocity after n updates and can be calculated with:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>v(n) = u + a \\cdot \\Delta{t} \\cdot n\n<\/pre><\/div>\n\n\n\n<p>So if we expand <em>v(n)<\/em> into the sum we get:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>s(n) = \\sum_{k = 1}^n ((u + a \\cdot \\Delta{t} \\cdot k) \\cdot \\Delta{t})\n<\/pre><\/div>\n\n\n\n<p>To resolve an equation like this we can use the rules for sums. For example, we can pull out the <em>delta-t<\/em> that multiplies each step:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>s(n) = \\Delta{t} \\cdot \\sum_{k=1}^n (u + a \\cdot \\Delta{t} \\cdot k)<\/pre><\/div>\n\n\n\n<p>And where each step is itself a sum, we can split the result into two simpler sums:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>s(n) = \\Delta{t} \\cdot \\left(\\sum_{k=1}^n u + \\sum_{k=1}^n (a \\cdot \\Delta{t} \\cdot k)\\right)<\/pre><\/div>\n\n\n\n<p>Again, we can pull out the common multipliers:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>s(n) = \\Delta{t} \\cdot \\left(\\sum_{k=1}^n u + a \\cdot \\Delta{t} \\cdot\\sum_{k=1}^n k\\right)<\/pre><\/div>\n\n\n\n<p>In the first sum, <em>u<\/em> is a constant, so the sum of <em>n<\/em> instances of <em>u<\/em> is simply <em>u<\/em> times<em> n<\/em>:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>s(n) = \\Delta{t} \\cdot \\left(u \\cdot n + a \\cdot \\Delta{t} \\cdot\\sum_{k=1}^n k\\right)<\/pre><\/div>\n\n\n\n<p>The sum of the numbers between <em>1 <\/em>and <em>n<\/em> is trickier, but it has a known solution.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Naughty Gauss<\/h2>\n\n\n\n<p>There is a story that the famous mathematician Gauss was notoriously badly behaved in his mathematics classes. To keep him quiet, his teacher set him the task of adding all the numbers between 1 and 100. But to his teacher&#8217;s surprise Gauss came back quickly with the correct answer of 5,050.<\/p>\n\n\n\n<p>His trick was to pair up the numbers from opposite ends of the list:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\begin{align*}\n1+100=101\\\\\n2+99=101\\\\\n3+98=101\\\\\n4+97=101\\\\\n\\text{etc.}\\\\\n\\end{align*}<\/pre><\/div>\n\n\n\n<p>Notice that if we do this all the way to 100, we are counting each pair twice. So the total answer is half of 100 times 101.<\/p>\n\n\n\n<p>In the general case, for any sum from 1 to <em>n<\/em>, the sum of each pair will be <em>n + 1<\/em>, and so the total will be half of <em>n<\/em> times <em>(n + 1)<\/em>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Back to the math<\/h2>\n\n\n\n<p>We can therefore substitute the last sum term in our earlier equation:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>s(n) = \\Delta{t} \\cdot \\left(u \\cdot n + a \\cdot \\Delta{t} \\cdot \\frac{1}{2} \\cdot n \\cdot (n+1)\\right)<\/pre><\/div>\n\n\n\n<p>Multiply through by <em>delta-t<\/em>:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>s(n) = u \\cdot n \\cdot \\Delta{t} + \\frac{1}{2} \\cdot a \\cdot n \\cdot (n + 1) \\cdot \\Delta{t}^2 <\/pre><\/div>\n\n\n\n<p>Multiply through by <em>(n + 1)<\/em>:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>s(n) = u \\cdot n \\cdot \\Delta{t} + \\frac{1}{2} \\cdot a \\cdot n^2 \\cdot \\Delta{t}^2 + \\frac{1}{2} \\cdot a \\cdot n \\cdot \\Delta{t}^2<\/pre><\/div>\n\n\n\n<p>Gather the <em>n<\/em> and <em>delta-t<\/em> terms:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>s(n) = u \\cdot (n \\cdot \\Delta{t}) + \\frac{1}{2} \\cdot a \\cdot (n \\cdot \\Delta{t})^2 + \\frac{1}{2} \\cdot a \\cdot \\Delta{t} \\cdot (n \\cdot \\Delta{t})<\/pre><\/div>\n\n\n\n<p>And look at <em>s(1)<\/em>, that is, the first physics update frame:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>s(1) = u \\cdot \\Delta{t} + \\frac{1}{2} \\cdot a \\cdot \\Delta{t}^2 + \\frac{1}{2} \\cdot a \\cdot \\Delta{t} \\cdot \\Delta{t}<\/pre><\/div>\n\n\n\n<p>It collapses to:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>s(1) = u \\cdot \\Delta{t} + a \\cdot \\Delta{t}^2<\/pre><\/div>\n\n\n\n<p>I think this is what the PhysX developer, that Unity spoke to, meant by &#8220;PhysX uses a semi-implicit Euler integrator which leads to omission of the 0.5 factor.&#8221; Of course, this only holds for one updated frame.<\/p>\n\n\n\n<p>In the more general case, the expected displacement <em>e<\/em> for any frame <em>n<\/em> is:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>e(n) = u \\cdot (n \\cdot \\Delta{t}) + \\frac{1}{2} \\cdot a \\cdot (n \\cdot \\Delta{t})^2<\/pre><\/div>\n\n\n\n<p>So if we subtract the symplectic version <em>s<\/em> from this, we can see that the shortfall after <em>n<\/em> frames is:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>e(n) - s(n) = -\\frac{1}{2} \\cdot a \\cdot (n \\cdot \\Delta{t}) \\cdot \\Delta{t}<\/pre><\/div>\n\n\n\n<p>In this equation, <em>n<\/em> times <em>delta-t<\/em> is just another way to say the time <em>t<\/em> at frame <em>n<\/em>. If we write it in terms of time <em>t<\/em> instead, we get:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>e(t) - s(t) = - \\frac{1}{2} \\cdot a \\cdot t \\cdot \\Delta{t}<\/pre><\/div>\n\n\n\n<p>If we pull out the variable <em>t<\/em>, we can see that the shortfall is always some constant amount multiplied by <em>t<\/em>:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>e(t) - s(t) = \\left(- \\frac{1}{2} \\cdot a \\cdot \\Delta{t} \\right) \\cdot t<\/pre><\/div>\n\n\n\n<p>And a constant amount times <em>t<\/em> is just another way of saying a velocity. So what this is telling us, is that our velocity is short by this amount. Which implies we can fix it, by simply adding it to our initial velocity.<\/p>\n\n\n\n<p>Therefore, the error isn&#8217;t in the calculation of the physics update, but in the application of the impulse.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A little extra push<\/h2>\n\n\n\n<p>I concluded my previous post with a lament that there was no accurate way to calculate the force required for a given jump height in Unity. After some time, thought, and experimentation, I conclude that is not entirely accurate.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Independence Day - That&#039;s Not Entirely Accurate\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/SEbwZfkeIt8?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>The force required <em>is<\/em> accurately calculated by the method I described in the previous post. But to apply that force, you cannot just add it using the impulse force mode in Unity. If there is a bug in the Unity \/ PhysX physics system, it is at this point.<\/p>\n\n\n\n<p>The corrected jump function is therefore:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#39404f;color:#c8d0e0\">JumpScript.cs<\/span><span role=\"button\" tabindex=\"0\" data-code=\"if (Input.GetButton(&quot;Jump&quot;))\n{\n\tfloat g = Physics.gravity.y;\n\tfloat dt = Time.fixedDeltaTime;\n\tfloat bodge = -0.5f * g * dt;\n\tfloat v = Mathf.Sqrt(-2.0f * g * height);\n\tfloat force = body.mass * (v + bodge);\n\tbody.AddForce(Vector3.up * force, ForceMode.Impulse);\n}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">Input<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">GetButton<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Jump<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #81A1C1\">float<\/span><span style=\"color: #D8DEE9FF\"> g <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Physics<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">gravity<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #81A1C1\">float<\/span><span style=\"color: #D8DEE9FF\"> dt <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Time<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">fixedDeltaTime<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #81A1C1\">float<\/span><span style=\"color: #D8DEE9FF\"> bodge <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #B48EAD\">0.5f<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">g<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">dt<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #81A1C1\">float<\/span><span style=\"color: #D8DEE9FF\"> v <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Mathf<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">Sqrt<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #B48EAD\">2.0f<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">g<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">height<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #81A1C1\">float<\/span><span style=\"color: #D8DEE9FF\"> force <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">body<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">mass<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">v<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bodge<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #D8DEE9\">body<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">AddForce<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">Vector3<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">up<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">force<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">ForceMode<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">Impulse<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Further investigation into the Unity jump height bug.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,6,5],"tags":[39,32,35],"class_list":["post-438","post","type-post","status-publish","format-standard","hentry","category-process","category-programming","category-video-games","tag-programming","tag-unity","tag-video-games"],"_links":{"self":[{"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/posts\/438","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/comments?post=438"}],"version-history":[{"count":30,"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/posts\/438\/revisions"}],"predecessor-version":[{"id":488,"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/posts\/438\/revisions\/488"}],"wp:attachment":[{"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/media?parent=438"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/categories?post=438"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/tags?post=438"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}