Comments and answers for "Gravity & Framerate"
http://answers.unity.com/questions/1433194/gravity-framerate.html
The latest comments and answers for the question "Gravity & Framerate"Answer by ColtPtrHun
http://answers.unity.com/answers/1711496/view.html
@Bunny83
I had the same problem, and the trapezoidal integrator solved it :)
Thank you very much!
I knew that the rectangular integrator won't be that punctial but it was the least suspecious part at least for me.
-PeterThu, 26 Mar 2020 14:56:06 GMTColtPtrHunComment by NMS_TomiBary on NMS_TomiBary's comment
http://answers.unity.com/comments/1433663/view.html
Ok, i think i dont understand it very well.
I made this code, but it don't work and idk what is wrong.
What should i change ?
using System.Collections.Generic;
using UnityEngine;
public class SaveRayFire : $$anonymous$$onoBehaviour
{
private Vector3 lastPos;
private Vector3 newPos;
private Vector3 velocityV;
private RaycastHit hit;
public GameObject pos1, pos2;
public float speed;
public float drop;
//Debugs
public bool showDebugs, showLineRenderer;
public List<DebugCoor> dc = new List<DebugCoor>();
//Show line
LineRenderer ln;
int i = 1;
void Start()
{
lastPos = transform.position;
velocityV = transform.forward;
newPos = lastPos;
ln = GetComponent<LineRenderer>();
ln.SetPosition(0, lastPos);
}
void Update()
{
//Destroy when is under ground
if (lastPos.y < -1f)
{
Destroy(this.gameObject);
}
//$$anonymous$$ake one step
if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.F))
{
//Vizualize where point is in scene
GameObject x1 = Instantiate(pos1, lastPos, transform.rotation);
newPos += 0.5f * velocityV * speed * Time.deltaTime;
velocityV += Physics.gravity * drop * Time.deltaTime;
newPos += 0.5f * velocityV * Time.deltaTime;
Vector3 dir = newPos - lastPos;
if (Physics.Raycast(lastPos, dir, out hit, dir.magnitude))
{
dir = hit.point - lastPos;
dc.Add(new DebugCoor(lastPos, dir, Color.red));
Debug.Log("RAY: " + hit.transform.name);
}
else
{
dc.Add(new DebugCoor(lastPos, dir, Color.green));
}
//Vizualize where point is in scene
GameObject x2 = Instantiate(pos2, newPos, transform.rotation);
lastPos = newPos;
}
//Destroy it
if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.X))
{
Debug.Log("Zničit");
Destroy(this.gameObject);
}
//Show lines
if (showLineRenderer) ShowLineRenderer();
if (showDebugs) { Ballistics$$anonymous$$ethods.ShowAllDebugLines(dc); }
}
private void ShowLineRenderer()
{
//Trajectory
if (i < ln.positionCount)
{
ln.SetPosition(i, lastPos);
}
i++;
}
}Mon, 20 Nov 2017 20:03:02 GMTNMS_TomiBaryComment by Eno-Khaon on Eno-Khaon's comment
http://answers.unity.com/comments/1433571/view.html
<b>pos</b> is the current position at the given timestep, and <b>vel</b> is the current velocity at that timestep.
<br><br>
Specifically, <b>pos</b> and <b>vel</b> would both be <b>Vector3</b> values in this case, using your script sample as a reference.
<br><br>
Furthermore, <b>acc</b>, as the acceleration per frame, would also be a <b>Vector3</b>. This would most likely be the gravity (i.e. <b>Physics.gravity</b>).Mon, 20 Nov 2017 09:00:43 GMTEno-KhaonComment by NMS_TomiBary on NMS_TomiBary's comment
http://answers.unity.com/comments/1433567/view.html
Thank you for your great answer.
I thought that solution is a little easier.
Could you help me little bit more ? (I never knew much about physics.)
pos += 0.5f * vel * Time.deltaTime;
vel += acc * Time.deltaTime;
pos += 0.5f * vel * Time.deltaTime;
What are pos and vel ?
**pos** is position with datatype Vector3 ?
**vel** is float number or Vector3 too?
and what is acc (acceleration?) and where i get it?
I think, that i understood how you calculated this:
Time | vel | pos | dt |oldPos + oldVel + newVel
//-----------------------------------------------
0 | 0 | 0 | - |
1 | 10 | 5 | 1 | 0 + 0 + 5 --> 5
1.5 | 15 | 11.25 | 0.5 | 5 + 2.5 + 3.75 --> 11.25
2 | 20 | 20 | 0.5 | 11.25 + 3.75 + 5 --> 20
2.5 | 25 | 31.25 | 0.5 | 20 + 5 + 6.25 --> 31.25
3 | 30 | 45 | 0.5 | 31.25 + 6.25 + 7.5 --> 45
4 | 40 | 80 | 1 | 45 + 15 + 20 --> 80
But idk where or how i can add Gravity vector?
If we imagine, that i have:
V3 pos;
float vel;
??? acc;
//and make function do something like this.
addG(){
pos += 0.5f * vel * Time.deltaTime;
vel += acc * Time.deltaTime;
pos += 0.5f * vel * Time.deltaTime;
}
So where i add that Gravity vector and why **pos** wont be so "far" like **vel**?
Thank you alot for your help.Mon, 20 Nov 2017 08:32:14 GMTNMS_TomiBaryComment by Bunny83 on Bunny83's comment
http://answers.unity.com/comments/1433214/view.html
Well there are other ways if you do the whole movement equation yourself. However the way you "process" your direction does not represent an actual projectile trajectory. Your vector will always have the length of "speed" (and a tiny bit from the gravity component but that's almost nothing due to dt²). So you only use gravity to slowly rotate your direction downward. Gravity however appies an acceleration to the velocity. So over time your velocity should get larger (if you shoot in an upward angle it would first becomes slower until it reaches the highest point). So you should preserve the actual velocity between each "step".
<br>
A common way of fixing a linearly accelerated movement is to apply the velocity in two steps ins$$anonymous$$d of one. Usually the straight forward implementation looks like this:
vel += acc * Time.deltaTime;
pos += vel * Time.deltaTime;
This will lead to exactly the problem you see with different deltaTime values. Just look at extreme situations where dt is simply "1" so 1 frame takes 1 second. If you have a constant acceleration of 10m/s² and just imagine you start with 0 velocity when you look at [uniform acceleration formulas][1] you will notice that after 1 second the velocity should be 10 m/s (which it is when using our formula) however the position should be "5" however we get a result of "10". This error becomes smaller and smaller the smaller the "dt" gets.
<br>
The solution is to apply half of the old velocity before your apply the acceleration and half of the new velocity after you applied your acceleration. So it becomes something like this:
pos += 0.5f * vel * Time.deltaTime;
vel += acc * Time.deltaTime;
pos += 0.5f * vel * Time.deltaTime;
This will yield much better position values. Here's an example of varying deltaTime:
Time | vel | pos | dt |oldPos + oldVel + newVel
//-----------------------------------------------
0 | 0 | 0 | - |
1 | 10 | 5 | 1 | 0 + 0 + 5 --> 5
1.5 | 15 | 11.25 | 0.5 | 5 + 2.5 + 3.75 --> 11.25
2 | 20 | 20 | 0.5 | 11.25 + 3.75 + 5 --> 20
2.5 | 25 | 31.25 | 0.5 | 20 + 5 + 6.25 --> 31.25
3 | 30 | 45 | 0.5 | 31.25 + 6.25 + 7.5 --> 45
4 | 40 | 80 | 1 | 45 + 15 + 20 --> 80
According to `s(t) = s0 + v0 * t + 0.5*a*t²` after 4 seconds you should get a position of "80" which we do even the delta time changes between frames.
[1]: https://en.wikipedia.org/wiki/Acceleration#Uniform_accelerationSat, 18 Nov 2017 16:00:52 GMTBunny83Comment by NMS_TomiBary on NMS_TomiBary's answer
http://answers.unity.com/comments/1433203/view.html
I know, that one way how to fix it is by using FixedFrameRate, so it is only one possible method how to fix it ?
I used FidexUpdate and Time.fixedDeltaTime and everything was O$$anonymous$$.
This method sets my dirVector which will be used in castingRay.
i give lastDirVector to this method, then i use speed (which makes my vector longer/shorter so "faster in one frame")
and result of it is my dirVector for RayCast.
So there isn't any mathematical equation how to fix it in normal Update() ?Sat, 18 Nov 2017 14:53:37 GMTNMS_TomiBaryAnswer by Bunny83
http://answers.unity.com/answers/1433198/view.html
Any accelerated movement (which is not a linear movement but a quadratic) can't simply be scaled linearly. DeltaTime works fine for any linear process. So for example a constant acceleration applied to a velocity will yield the correct velocity values after "t" time reliably. Applying a constant velocity to a position will yield the correct position after "t" time reliably. However you apply a linearly growing velocity to the position which will not yield the correct values. In general lower framerates will result in a quicker grows.
<br>
That's the reason why Unity's physics runs at a constant framerate (FixedUpdate). Have a look at [this article][1]. Unity's FixedUpdate roughly does what is described in th "Free the physics" section. I said roughly because Unity doesn't take the min between the set fixedDeltaTime and the current deltaTime but simply always uses the fixedDeltaTime. Unity however does not really implement what is described in "The final touch"
<br>
What exactly do you pass to your SetGravityDir method? Also where and how do you actually use the result?
[1]: https://gafferongames.com/post/fix_your_timestep/Sat, 18 Nov 2017 14:20:19 GMTBunny83