This week, our spotlight post is a double feature: Driving and CPUs with Emil Balian and Angela Zhang! While both are Juniors, Emil is majoring in Computational Physics, and Angela in Computer Science. Throughout the semester, both students have been hard at work on our Code team, making sure our players can drive their buggies smoothly, and that they have CPU opponents to race against.
This blog post will be a bit longer than our previous entries. We will continue with our Q & A format, first interviewing each student individually, and then coming together at the end to discuss their shared work.
Emil Balian
Q: How did you approach creating our buggy driving mechanic?
A: “The main approach to the buggy driving mechanics was to maintain relatively simple arcade vehicle physics (i.e. not get bogged down in complex traction and/or real car simulation), and to design a driving system with parameters that can be extended and tweaked easily, vehicle by vehicle. Our system was built from scratch with no pre-made scripts or aids, just using Unity’s physics engine, which allows us to have close control of all physics of the buggy. “
Q: What different elements must you consider when creating the driving mechanic?
A: “Creating physics-based systems can often get complex just by virtue of the number of parameters one has at their disposal to tweak and change. Because of this, you have to consider which elements are most fundamental for the game at hand. Given the huge buggy roaster, driving mechanics and visuals may need to be adjusted buggy by buggy due to the variations in size and shape over the years, but the basic underlying system is the same for each.
Our buggy has two core independent components: a physics proxy to determine the driving and physics, and a visual component. Under the hood, each buggy is some variation of a basic rectangle shaped vehicle with differing size, speed, acceleration, traction, etc, which can be tweaked from a prefab. For the visuals of the buggy, a model is added over which scales appropriately with the size of the physics proxy and does things like placing the wheels in the appropriate position and orientation with information from the physics proxy.”
Angela Zhang
Q: How did you approach making CPU opponent buggies?
A: “There were a few guidelines in the original design of the CPU components that I used to shape how the current code was. From the very beginning the different requirements included:
- CPUs must be able to navigate a track
- CPUs must be able to use and be affected by items
- The CPU system should be easily adaptable for other tracks
The initial week of designing the CPUs were a lot of trial and testing of different AI systems in Unity. I spent some time working on both MLAgents, NavMesh Agents, and coding an AI system from scratch. After some feedback from the other programmers, we decided the NavMesh Agent was the best way to go – it was easily adaptable to newer tracks without requiring too much setup.”
Q: How do you train your CPUs, both to move and to use items?
A: “The moving portion of the AI is mostly handled by the NavMesh portion of each of the CPU buggies. The base library handles setting a destination and basic movement of an agent to that destination.
In the first iteration of the CPUs, we found that the movement needed to be tweaked to prevent the CPU buggies from just hugging the edge in an attempt to get to the final destination. We solved this by setting incrementation checkpoint destinations along the track to make driving look smoother.
Another aspect that needed to be adjusted was collisions with the CPU buggies; at the beginning, running into a buggy would be similar to running into a wall. There needed to be additional controls to ensure a sort of “bounce-off” effect would happen and make the collision seem more realistic.
For items, the current CPU code doesn’t do anything special; if an item is picked up, the CPU uses it instantly. I’ve been working on making the CPUs more intentional and having them use the items in a more competitive manner – coming soon!”
Emil and Angela
Q: What’s it like trying to find balance between too fast and too slow when adjusting speeds? How do you test difficulty as a player versus the AI?
Emil: “Mostly trial and error, changing specific parameters and running the game again in editor is pretty much the only way I have done it. Since the AI and driving system evolve week by week, my focus while doing the driving mechanics (during development) is to make sure that it is a speed similar to that of the AI buggies, but beyond that my focus was mostly on making the driving feel good itself. Given the system we have put in place, it will be very easy to tweak these values for difficulty later on in development (like around now-ish time wise) which was the plan, but earlier in development that was not necessarily the main focus since things change quite easily.”
Angela: “This has been tricky so far – the player code (and therefore the player buggy speeds) have been adjusted numerous times throughout the development of this game. For the most part, speeds for the CPUs have been set at random within a given range that would hopefully make them feel competitive, but not unfair.
There is also a rubber-banding system with the CPU buggies; depending on their relative positions with respect to the player, they will incrementally adjust their speed to either catch up to the player, or give the player a chance to take the lead.”
Q: How does your code rely on your teammate’s? What’s it like working with this codependency?
Emil: “This might be a question that Angela can answer better, since the player and AI systems have been not-so interdependent until recently.”
Angela: “There’s a lot of dependence between our two portions of code! Along with having to balance AI vs player speed, the general relationship between the player’s actions and those of the CPUs means there’s a lot of back-and-forth tweaking that needs to happen.
For instance, something that was an issue in a previous week was needing to balance how a speed boost and/or caffeine power-up affect the player versus a CPU. A CPU buggy was able to immediately change its speed, making it appear to be much more affected by the speed boosts than the player’s buggy, which would instead gradually accelerate. We ended up changing up how a player reacts to the boosts to be more similar to the CPU system.
It is a little tedious to perform all of these adjustments, but I think there’s also a large benefit in seeing how someone else approaches coding the same features for a different purpose, then figuring out how to make them work together.”
Q: What has it been like working in a team of fellow coders?
Emil: “Everybody working on the code team has been great and working on games with other people is loads of fun. We naturally have taken up our own areas to become the go-to person for so everybody knows their stuff and there is a lot to learn from one another.”
Angela: “It’s been a really fun experience! I’ve enjoyed seeing everything come together and the progress we make with each new week. This was my first time working on a driving game, and I’ve learned so much from working with others on this team. Through both seeing my teammates’ code in various components and discussing approaches to different problems, I think I’ve definitely grown as a programmer, and I’m super excited to see how our game turns out!”
Closing Remarks…
Teamwork is essential to our project’s development, and thanks to the hard work Emil and Angela put in, our game’s code is progressing nicely. In the upcoming weeks, we look forward to seeing how our driving and CPUs will evolve!