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
• • •
Missing some Tweet in this thread? You can try to
force a refresh
For people thinking of writing their own engine in C/C++ after the Unity fiasco, here's a few things I learned in my own journey making #ShakedownGame in C++: 🧵👇 #gamedev #cpp
1. Making your engine is not "hard", individual steps are easy, but there's just many of them! Every magical checkbox in Unity is now a feature you have to implement. So you're better off chosing specific features for your game, if you want generalist use another engine..
2. C++ is a mess, it's almost 40 years old, and built upon C, which is 50, so it inherited a lot of issues, like terrible defaults and manual header file management. It has evolved and grew drastically over the years, and all this makes it a rocky road for any beginner to learn..
So, my life in the old year was very eventful and hectic with many ups, but unfortunately, I will remember 2022 as one in which I haven't published a single game! Real life stuff took so much energy from me.. ->
..& I haven't participated in jams. While my new social landscape has kept me satisfied, games have definitely taken a back seat & for the second half of the year I barely worked on or could focus on my own projects. Any free time I had I used on learning new not-games skills. ->
That said, 2023 will be different! In the new year, I am making plans which I want to stick to. 1st of which is that I am going to release the first version of #ShakedownGame on 18th of January! Yes, that's in just a bit more than 2 weeks, and a day before Monte Carlo Rally! ->
Kinda disappointed that anti-anti-art redirects to Stuckism
Stuckism was definitely the last "movement" we learned about in school. But seems like there's been a bunch new ones in the mean time that I've never even heard of. I guess to be an anti-anti it needs to be direct response to anti-art.
Good news it works on win10. But for some reason on my native resolution it crops part of the screen. On 4:3 seems it doesn't crop. Oh & I had to start the game a few times to test it, which was super annoying cuz it has the first sin of video games, an UNSKIPPABLE INTRO!!
Everything in this game uses like deltatime lerping:
> current = lerp(current, target, dt);
from menu highlights to mouselook, lol. It's painful.
So, I'm finally working on a "material" system in my engine. Until now there was no need for it since there was just one scene shader, with the only object-unique uniform being the texture. The framebuffer and debug lines were special cases that bind their own shaders (1/?)
So, each "object" (I called it Model) was just Mesh, texture, and the model matrix. This was actually the whole scene rendering logic, I did some checks to see if models in sequence have the same texture or mesh to reduce unnecessary binds: (2/?)
But now with adding materials, I actually have to refactor almost everything, and turn the Model into a bigger beast, that has a Transform, Mesh and Material. With the only addition being ability to switch shaders (3/?)