- Home /
Update function unstable frame rate
Hi. i'm doing a simple translation of a 2D object using transform.Translate in Update function, but the movement is not occurring smoothly and i'm having little lags. I know that Update funciton is unstable with the frame rate update and i'm already using Time.deltaTime. The code part looks like this:
transform.Translate(speed * Time.deltaTime, 0, 0);
Someone know how to solve this and get a smooth movement?
Answer by Dray · Nov 28, 2017 at 06:59 PM
FixedUpdate() and Time.fixedDeltaTime is what you need for high accuracy:
void FixedUpdate() {
transform.Translate(speed * Time.fixedDeltaTime, 0, 0);
}
To explain this real quick; Unity runs two parallel update loops: one for the rendering that by its nature takes a random amount of time and one with a fixed timespan for the physical calculations in the game.
The reason Unity is doing that is simply that running the physical part of a game depending on that random "time"-value from the rendering step would produce unpredictable deviations in the small digits that lead to weird behaviours like what you are experiencing.
If you run the main loop of your game logic always with the same timestep, the results of physics interacting with each other in any way will always be the same with a probability of 100%, thats why unity provides the FixedUpdate function.
Still lagging man. $$anonymous$$y game object hasn't Rigidbody2D attached, i think i don't need FixedUpdate(). I've tried put the code in FixedUpdate() with transform.Translate(speed Time.fixedDeltaTime, 0, 0); and hasn't worked, I've tried only to use transform.Translate(speed Time.fixedDeltaTime, 0, 0); on Update() and hasn't worked too.
Have you an opinion about this?
Thanks anyway!
This is my script:
public class ScrollRoad : $$anonymous$$onoBehaviour {
public float speed;
void Update () {
transform.Translate (speed * Time.fixedDeltaTime, 0, 0);
}
}
Oh, don't use fixedDeltaTime in the normal Update loop, it's Time.deltaTime for the normal Update and Time.fixedDeltaTime for the FixedUpdate, sry if that wasn't clear but I guess that's not the issue since you had that problem allready when you added that :/ The only other Idea I got would be checking if other scripts influence the same object as @JonPQ suggested
First check your FPS.... enable "stats" window. is your FPS stable ? If your FPS is fast and stable, * TimeDelta should be good enough.
If your FPS is choppy, lots of things it could be.... make sure you are not logging a bunch of debug logs to the console... that can make things run slow and choppy. You can turn them off temporarily under PlayerSettings->other settings.
Also... is this the only thing going on in the scene ? are you rendering too much... or too many transparencies? or instantiating objects while the gameplay is happening? try opening Window->profiler and look out for big spikes.... if you have a lot of spikes, pause the game and see what they are.... scripts or rendering....
Another thought.... Watch the movement of your object in the scene view... is it smooth there ? I once thought something wasn't smooth when it was actually fine, it was the camera that was following the target object that wasn't smooth. So make sure that the camera position update, happens after the object position update (consistently) If object updates in fixed update, and camera moves in Update, then you will get hitches and discrepancies. If you have something setup like this... the easy way is to turn off camera Update() function... and call the function from the end of the character position update code.
Answer by pako · Dec 05, 2017 at 09:38 PM
Your movement method should present no problem with unstable FPS. It's fine as it is: transform.Translate(speed * Time.deltaTime, 0, 0);
If you use the Instantiate ()/Destroy()
methods too much, you are actually asking for unstable/low FPS. When you call Destroy()
the garbage collector will kick-in at some point, and that's not good. Also, Instantiate()
is rather heavy on performance. So, instead of Instantiate()/Destroy create a pool of objects and use GameObject.SetActive(true/false)
. You should really be using a Pool Manager for this, and there are even free ones in the Asset Store. Typically, Pool Managers use Spawn()/Unspawn()
methods that utilize GameObject.SetActive(true/false)
behind the scenes. https://assetstore.unity.com/search?q=pool&q=manager
I'm using pool already. I believe I'm doing nothing wrong. This is my pool scripts:
public class RoadInstanciator : $$anonymous$$onoBehaviour {
public float instanciationTime;
public float disableTime;
public static float disableTimeStatic;
public GameObject road;
public int pooledAmount;
List<GameObject> roads;
void Start(){
disableTimeStatic = disableTime;
roads = new List<GameObject> ();
for (int i = 0; i < pooledAmount; i++) {
GameObject obj = (GameObject) Instantiate (road);
obj.SetActive (false);
roads.Add (obj);
}
InvokeRepeating ("InstanciateRoad", instanciationTime, instanciationTime);
}
void InstanciateRoad(){
for(int i = 0; i < roads.Count; i++){
if (!roads [i].activeInHierarchy) {
roads [i].transform.position = transform.position;
roads [i].transform.rotation = transform.rotation;
roads [i].SetActive (true);
break;
}
}
}
}
public class RoadDisable : $$anonymous$$onoBehaviour {
void OnEnable(){
Invoke ("Disable", RoadInstanciator.disableTimeStatic);
}
void Disable(){
gameObject.SetActive (false);
}
void OnDisable(){
CancelInvoke ();
}
}
You might find the source of the problem with the Profiler. Start the Profiler (Window/Profiler), start Play mode, and check the Profiler for spikes. Play around with the Profiler's settings and see if you get any clues from there. BTW, I noticed from your previous comments that you don't have a Rigidbody2D attached. If you have any Collider2D on you GO, and no Rigidbody2D, Unity internally attaches the Collider2D to a single hidden Static Rigidbody 2D component. I don't know if this is the source of your problem, but it's something to keep in $$anonymous$$d. Check out "Body Type: Static" in https://docs.unity3d.com/$$anonymous$$anual/class-Rigidbody2D.html In any case, it would be better to attach a Rigidbody2D to your GO, and enable is$$anonymous$$inematic.