- Home /
Updating at frameRate some fixedUpdated gameObject
I'm reading the position of a sphere from a json file. As I want it to move at a certain speed, regardless of the FPS, I put its postition update script in FixedUpdate.
FixedUpdate is at 30 Hz, but I want the sphere to be moving smoothly.
Is there a way to "interpolate" it's position as if it was written in the Update method?
PS every FixedUpdate I call this method on an already existing Sphere:
public void update_Sphere(Vector3 p, GameObject sfera){
sfera.transform.position = new Vector3((float)p.x, -(float)p.y, (float)p.z);
}
Answer by Bunny83 · Jul 29, 2019 at 01:44 PM
Just don't use FixedUpdate. You said you want to move at a certain speed but you haven't mentioned at which speed. In general you want to interpolate between two points of your data all the time.
Say your desired "speed" is 2 units per seconds. You get two points from your data, the current one and the next one. You calculate the distance between those points (Vector3.Distance). Now that you have the distance you can simply lerp between your current and your next point based on the time that has passed.
float t = 0;
void Update()
{
float distance = Vector3.Distance(currentPos, nextPos);
t += Time.deltaTime * speed / distance;
if (t > 1.0f)
{
t -= 1f;
currentPos = nextPos;
nextPos = (next point from data);
t *= distance / Vector3.Distance(currentPos, nextPos);
}
transform.position = Vector3.Lerp(currentPos, nextPos, t);
}
As you can see if t is greater than 1 that means we reached / passed by the nextPos. So we replace the current with our next pos and set nextPos to the next data point. Also notice that we do not set t back to 0 but instead we subtract 1. This will preserve the fractional amount that we have already overshoot our target so we can actually proceed at the correct position. Since the distance between the last two points and the new two points doesn't need to be equal, we adjust the fractional amount by converting the normalized value into an actual distance value in units and divide by the new distance of our new segment.
Note that this just assumes that your data points do not have any speed / time relation since you said you want to move at a certain speed. If the data is actually time based data (for example a recorded GPS track) the speed would not represent the speed in the recorded data but, as we defined, just a constant set speed..
If your data do contain speed information and all the data points have been recorded at a fix time interval you can use a similar approach but just take out all the distance calculations. Like that:
float t = 0;
void Update()
{
t += Time.deltaTime * speed;
if (t > 1.0f)
{
t -= 1f;
currentPos = nextPos;
nextPos = (next point from data);
}
transform.position = Vector3.Lerp(currentPos, nextPos, t);
}
This will preserve the relative speed that is encoded in the data. The "speed" in this case does not represent units per second but just a time scaling factor of the actual data. So for example if the data was recorded at one data point every 10 seconds you want to set speed to "0.1" to get realtime replay.
If the recorded data contains speed information for each data point or is not recoreded at a fix time interval but each data point is paird with a timestamp, it's another story and slightly more complicated. Though you said you want to move at a certain speed so I'm assuming this is all not relevant to you.
Your answer
Follow this Question
Related Questions
Interpolation with jumping - Acting Weird. 1 Answer
FixedUpdate limits: consistant 0.01 s on mobile devices? 1 Answer
Applying Forces, independent of Frame Rate? 1 Answer
Lerp stopping/not working? 1 Answer
How do I fix jitter? 1 Answer