Thread: I want to do a little optimization of the car scripts, because I haven't done any so far, only been focusing on functionality. So, why not share the process. This may fail, but hopefully it won't :D To start I made a perf test scene with 600 cars #madewithunity #gamedev
First, I'm using classic MonoBehaviours, PhysX and Unity's WheelCollider, so no DOTS this time. First, open the profiler and maximize it so there are no scene or game views to add to the rendering cost. Here is one frame: #madewithunity #gamedev #YugoTrip
^ Ok, so the orange on the left is the WheelCollider processing, and there's nothing much we can do about that.. Except reduce timestep, but I won't do that. The big blue thing on the right are the scripts and what I can optimize. The little green thing on the right is rendering
Lets zoom in! Now we see individual car scripts running.. #madewithunity
Ok, so here's each thing in detail:
- CarAI.Update processes paths and sends steering and acceleration commands to CarController
- WheelTransform.Update sets the position and rotation of the graphical wheel model
- CarController takes inputs and applies forces to wheels...
- There are 3 raycasts, the narrow orange stripes, they are used for obstacle detection and avoidance
-And a.. GameObject.Deactivate, strange.. Ah yes, that's the brake and reverse lights that I just turn on and off! 😅
Hey... I wrote this on a game jam, this was fastest to code
Btw.. I wrote this on GGJ, so simplicity and speed of getting things done was crucial, give me some slack 😂 Anyway, note that Deactivate is actually just 0.25ms in total, compared to the rest that takes 15ms. So, I'll deal with it later... First and always first, THE BIG STUFF!
Ok, so first, WheelTransform can only be set while you are looking into it, there's no need to set it for all 600 cars. In this frame, total is 3ms. Here's the code. I heard SetPositionAndRotation is faster so lets try that. Also new C# out variables make it nicer. #madewithunity
Ok, that reduced from 3-3.2ms to 2.6-2.7ms, saved a tiny bit but it was fast to do. Ok, lemme now try to call all WheelTransforms together instead of using Update(), as @craigperko also suggested. I put wheels in a static list and call from new WheelTransformManager Update()
@craigperko ..Well, WheelTransforms are now combined, but they still take around 2.8ms in total, so there is not much difference between having 600 updates and running them manually in a loop
@craigperko Had to double check, reverted, and yes, it seems to not have much difference, it varies around 2.7-2.8 in both cases
@craigperko I thought of another micro :D Save the count so you don't query it each time in for loop, but yeah the benefit is so miniscule it's overhyped, I don't notice any change... Aaaanyway.......
@craigperko Ok, I've moved things around, now the CarController references wheel transforms, because I can use the entire car position instead of each wheel, to check if they're in view. Since the game is top down I use a simple rectangular extents value to compare to the camera position:
@craigperko This now reduces the time to like 0.7ms when I'm between the cars, and if I'm far away there's basically no cost, so that's great compared to 3.2 I started with
@craigperko Remember that thing with SetActive lights? Halved time by just calling SetActive on a state switch. It looks a bit less elegant tho
@craigperko Another nice thing about lights is that, just like wheel transforms, they're only graphical, so we can update them only when they're close to the player. Added car.UpdateLights()
@craigperko Just tested turning off obstacle avoidance with raycasting completely, it almost doubles performance. I should optimize that next.
@craigperko Made only one ray cast per frame, but still keeping the hit distance value from that position cached, so only detection is less frequent but no impact on AI avoidance. That got update down to ~7ms. But why stop there? I think I should cast even less often.
@craigperko Got it down to ~5.5ms by casting every third frame (at random offset per car), I don't see any functional differences so far in the game. Not bad optimization day considering I started with 15ms
Share this Scrolly Tale with your friends.
A Scrolly Tale is a new way to read Twitter threads with a more visually immersive experience.
Discover more beautiful Scrolly Tales like this.