I’ve decided to keep a weekly progress report on the unity project (Making a game in Unity 3D) I mentioned previously to make sure I’m making a bit of progress on it every week. And I’m off to a great start with that clearly, combining two weeks into one post!
These posts will generally include a summary of the plan for the week and the progress I made, a list of new features I was able to implement and a list of challenges I came across for future reference. Here’s what I managed to accomplish in the first two weeks.
My plan for the first week was simply to get the unity assets I bought loaded in and working, but I ended up getting a lot further than that as it turned out to be much easier than expected. I managed to get to a stage where the character could move between waypoints by clicking when the camera was pointing in the right direction. However, things would not work reliably and there was a few recurrent bugs.
This week I was able to modify the packaged asset code to disable the traditional 3D platforming movement implemented (running and jumping using the keyboard) to mouse based movement which involves no direct control of the character. Instead, the player simply clicks when the camera is facing one of the available nearby waypoints (represented visually by basic spheres at the moment) to signal the character to automatically move to that point.
The most important element of implementing this was to change the character to use a NavMesh for movement. As objects using a NavMesh (NavMeshAgents) are moved using transforms by Unity rather than the physics system, I had to disable the effects of physics on the character. Without doing so, both the physics system and the NavMesh system would be fighting to move the character at the same time, leading to non-deterministic results. Thankfully this was fairly simply achieved by setting the Rigidbody component of the character to kinematic. This means the object is no longer affected by forces but can still enact forces on other non-kinematic Rigidbody objects.
The NavMesh, once baked, simply provides information to Unity about what possible routes an object can take through a level so that it navigates around objects with static colliders. This means that the only thing I needed to do is add a NavMeshAgent component to the character and then set the goal position of the character like this:
navMeshAgent.destination = waypoint.transform.position;
Of course, I only want to do that on frames where the player clicked the mouse button and the camera was facing another waypoint. I also wanted to have a list of adjacent waypoints stored in each waypoint to make sure the player did not take invalid paths between waypoints. The latter was achieved by adding a simple script to each waypoint that does nothing more than store a list of adjacent waypoints, and the first was achieved by checking that the angle between the current camera direction and each adjacent waypoint was less than a constant value.
- Driving the animation – when implementing the above, I needed to make sure that the running animation was driven using the NavMeshAgent velocity instead of the Rigidbody velocity.
- Juddery camera – when running the game I had an issue with the camera stuttering as the player moved. I found that this was because the player was being moved in Update() while the camera was being moved in FixedUpdate(). I fixed this for now by changing the camera script to use Update().
- Navmesh height – at first the player appeared to hover above the ground rather than run along it. I fixed this by including the Height Mesh when baking the NavMesh.
As I was still experiencing a number of bugs at this point, I realised that perhaps removing as much of the built-in asset code as possible might be the best course of action. I was able to make some progress with this, but I didn’t complete it due to lack of time this week. However, I did further convince myself that this was a good idea and had some ideas for how to structure the new code that I would build to drive the game.
As I mentioned previously, my initial motivation for deciding to remove the existing code for the downloaded assets and build my own from scratch was that I was experiencing a bunch of unreliable bugs and wanted to build it again from the ground up to do exactly what I want. However, it also occurred to me that this would be a good idea as it would enable me to properly decouple the code from the models and assets themselves. At the moment, it would be difficult to drop in different models/animations without rewriting a lot of the code. If I rewrite the code from scratch, I can write a class to abstract away details of the animation and model. This means that if I want to change the player character model/animation in the future, all I need to do is write a new abstraction class which interacts with the animation differently but maintains the same external interface to the rest of the code. The rest of the code is also fairly tightly coupled to things like the camera behaviour, so I should benefit a lot later down the line from building it myself.
Another idea for making my life easier later down the line is to make sure that levels can be built purely by dragging and dropping things into the scene editor. The code should not have to be changed based on the position of objects in the level (at least in the general case). I can do this by making sure that all code reads it’s data from the world itself (using the world as its model) rather than using some kind of internal representation.