Lately I was having alot of trouble with stuttering in my game. About a month ago I switched from a CharacterController to a Rigidbody controller but I have been encountering jitter/stutter eversince. At first I thought it had something to do with Cinemachine , but as of now I don’t think that’s the problem. The strange thing is when running my game (both in standalone as well as in editor) it runs perfectly fine in the beginning but after some time, this can be after 30 seconds or 2 minutes the background starts stuttering and eventually it will go away as well. This happens with both v-sync on and off, but with v-sync on it happens less often and you can sometimes play for 5 minutes untill the stutter starts happening.
My Cinemachine Brain has both the Update Method aswel as the Blend Update Method set to FixedUpdate and all my movement is happening in FixedUpdate aswel. For moving and rotating the Rigidbody I’m using _rb.MovePosition and _rb,MoveRotation
In my time settings I have set the Fixed Timestep to 0,01666667 (60fps) when using 0,02 (default) I get the background stutter all the time.
I have tried profiling my standalone game, but I can’t seem to find reasons for the stutter and my game generally maintains high fps (320fps with v-sync off). Below you can see a screenshot of the profiler, although I admit I’m not very experienced with deepprofiling.
I have tried working with interpolation on the rigidbody, but this doesn’t change anything. Same goes for changing various settings on the Cinemchine Brain. Besides that @Gregoryl explained what to use in different situations in one of his last comments in my previous topic .
Here you can see a recording of my game (Standalone) and you can see the stutter appearing at the 0:45 second mark.
I have also added both my movement code and a build of my game so you can see the stutter for yourself. It can be played with both keyboard and mouse as well as with an Xbox One or Ps4 controller.
So presumably you’ve discounted garbage collection before you focused on physics or Cinemachine? I see you have some prototype test project so hopefully if you get jitter there, there’s also no garbage to discount it from being the issue.
@MelvMay I’m not sure what you mean? As far as I can see Garbage collection is fine sometimes a spike to 17kb and than immediately after it returns to 5kb.
Edit: I’m also experimenting with incremantal GC, but this doesn’t change anything unfortunately.
Haha now I see what you mean, in the meantime I have created a simple script that does a Debug.Log in both Update and FixedUpdate to check if both Update and FixedUpdate get extremely out of sync. I also had a Debug.Log bind to a key press, so I could press that when the stuttering occurred.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FixedUpdateLogger : MonoBehaviour
{
void Update()
{
Debug.Log("Update");
if (InputManager.YButton())
{
Debug.Log("Jitter started");
}
}
void FixedUpdate()
{
Debug.Log("FixedUpdate");
}
}
Attached is a txt file to show how my loops are going, nothing strange there as far as I can tell.
One thing to note is that there’s a pretty terrible flaw in the interpolation of rigidbodies. What happens during the physics simulation (which is triggered via the fixed-update) is that before it performs the simulation step, it grabs the body poses. It use that for transform interpolation of bodies which use it. The simulation step then runs and then per-frame the transform is interpolated from the old body position to the current one.
That’s nothing new but one pain is that if two fixed-update happen then no interpolation will either. Or more specifically, it’ll do the above, then it’ll do it again. This means it’ll end up interpolating from the “old” position to the current one but the “old” position wasn’t the one during the first update but the second. This means you’ll effectively get non-interpolated jump for all but the last fixed-update.
I’m not saying this is what you’re seeing because you’re describing something happening on the order of minutes or 10s of seconds. It sucks and needs fixing.
Although it reduces determinism and sometimes stability you could run your physics per-frame manually, even if just for a test.
This and my previous post might be useful info but they also might be distracting from the real problem. Nevertheless, the more informed you are, the better position you are to figure out what’s going wrong.
Use Physics.Simulate passing in the frame time-delta. I woudn’t use it where you want consistent stacking behaviour or with complex joints unless you know the frame-rate is going to be fairly consistent and not too low. For a lot of game types though it doesn’t matter and makes things so much easier because there’s no disconnect between input/rendering and physics.
Also, you don’t need to interpolate because the Transform pose is always the same as the Rigidbody pose. In-fact, in doing the above, you should turn this option off for all 3D Rigidbody (for 2D you don’t need to do this as it’s done automatically).
I will give that shot, is it as simple as the following? And I’m not sure how to implement the “step” the docs are talking about.
void Update()
{
if (Physics.autoSimulation)
return; // do nothing if the automatic simulation is enabled
timer += Time.deltaTime;
// Catch up with the game time.
// Advance the physics simulation in portions of Time.fixedDeltaTime
// Note that generally, we don't want to pass variable delta to Simulate as that leads to unstable results.
while (timer >= Time.fixedDeltaTime)
{
timer -= Time.fixedDeltaTime;
Physics.Simulate(Time.fixedDeltaTime);
// My FixedUpdate logic come here?
}
// Here you can access the transforms state right after the simulation, if needed
}
Edit: And can my other logic still be in the same Update? Or do I need a new script?
void Update() {
// All of my input and other logic
Physics.Simulate(Time.deltaTime);
// The move function which was previously called in FixedUpdate
Move(inputDir, running);
}
You can do whatever you need to do before you simulate, then simulate, then do whatever you need to do after.
The script you know as FixedUpdate is called first, then the internal fixed-update is called which causes 2D/3D physics (and other stuff) to run. This means that you are typically doing stuff before the physics runs in your fixed-update.
If you do the above, you should do it in a dedicated script then set its execution order appropriately; most likely running it quite late.
It’s actually unclear to me how to simulate the physics with my current script (The one attachted to my initial post). Currently my script looks roughly like the following;
void Update() {
// Game logic and input
}
void FixedUpdate() {
Move(inputDir, running);
}
void Move (Vector3 inputDir, bool running) {
// My move logic
}
What I’m practically saying is that I’m not sure how to do this with my PlayerControllerRigidbody.cs script
Well you don’t perform the simulation here which should be obvious. You do that, as I said previously, in a dedicated script with its execution order set to later. You don’t use FixedUpdate in your script if you’re, well, not using fixed-update. Do everything in Update.
In short. Do everything in Update in all your scripts and don’t use FixedUpdate (because you’re doing everything per-frame). Then your other script will (later in the frame) run the simulation.
void Update() {
// Game logic and input
Move(inputDir, running);
}
void Move (Vector3 inputDir, bool running) {
// My move logic
}
I’m sorry for not completely understanding, but I think I’ve got it now;
In all of my scripts I don’t use FixedUpdate, I think this is clear (i.e. move my Move(inputDir, running); to Update) and then I create a new script with only the following;
And add it to the Execution order and set it to the bottom part i.e. 105?
Edit: On a side note, I had created a very simple CharacterController script to a capsule and a Cinemachine Brain with both Update Methods set to LateUpdate and was having no issues at all. This must mean it has something to do with FixedUpdate/Physics I think.
No need to apologise. My problem is trying to explain it without just repeating myself and not actually helping.
Also, wanted to ensure you were doing this as an experiment for fun and learning and not necessarily as a fix to your original problem as it’s not necessarily anything to do with fixed-update/update stuff.
I don’t think I’m necessarily fixing the problem by simulating physics, but see it more as a breakdown/experiment to what my problem actually is. I simply haven’t been able to create smooth player/camera movement with my Rigidbody Controller and am trying to find out how to get it as smooth as possible. Something that came to mind while debugging was Update and FixedUpdate being out of sync causing the stutter. Since you came with the experiment to try Simulating physics I started reading the documentation, which states; “Calling Physics.Simulate does not cause FixedUpdate to be called.” and your earlier comment stating;
The only problem is I’m not sure how to simulate the physics and actually try the experiment, I reckon my last comment is incorrect?
This is what the “Physics.Simulate” does so I’m not sure how else to answer. When Physics.AutoSimulate is on, Unity calls this for you during the fixed-update (it’s the same call). When that option is off, it doesn’t call it and you just call it yourself with whatever time-step you like.