Week 3 and 4: Basic Enemy AI and a different perspective

Published / by robsws

It’s been a busy couple of weeks, so I haven’t found an awful lot of time to work on the game. However, I did manage to complete a couple of bits and pieces that get me a little closer to having a very basic playable game.

Enemy AI

Since this is a puzzle game, I want my enemy AI to be predictable by the player but still interesting enough that some thought is required to solve the puzzle. Therefore, I thought a combination between a basic patrolling enemy (walking up and down a line) and an enemy that spots you and comes after you might be a good mix. I think some interesting puzzles could arise from luring enemies around.

To begin with, I simply implemented the patrolling enemy. They act as if blind, not reacting to the player’s presence in any way – they simply follow a path up and down or around in a circle. This will be enough I think to implement a few basic puzzles and get me to that first playable iteration of the game.

Camera perspective

After thinking about it, I have decided to scrap the camera that follows the player and allows navigation using mouse look. There are two main reasons for this. Firstly, I mentioned in a previous post that not having access to the full information for the puzzle might frustrate players, and I think that having a camera angle positioned above the world makes it easier for the player to make informed decisions. Secondly, although the camera may have provided a different feel for the game (more like an adventure than a puzzle game), I think that the aesthetic of mouse look counterbalances this. For me, the sharp movements of the camera when using the mouse break the immersion, and are probably only suited to games where high precision is necessary (such as FPS games).

To implement the new perspective seen in the image for this post, I had to make a few changes to how my movement code worked. The code now fires a ray from the camera to the point clicked by the mouse, and if it finds a waypoint that is adjacent to the current waypoint it will tell the character to move there.

Introducing the new perspective has highlighted a possible problem with my NavMesh-based approach. Even though I disable clicking on other waypoints until the character is nearby the waypoint he is heading to, clicking another seems to allow the character to get too much momentum and kind of spiral around the next waypoint. I think I can remedy this by making sure the character has stopped (or is at least very close) to the current destination waypoint before accepting new destinations.

Next week

As I have mentioned a couple of times in this post, I think it is important to aim for the most basic playable game I can first of all. I can then iterate on this and grow it into a full game. Although I need to fix the character movement slightly, I think I’m happy that the movement and AI is ready otherwise. I think there are a few things still to do before I can say the first iteration is complete:

  • Undo and restart functionality
  • Implement failure and success – the player should not be allowed to make further moves after collision with an enemy. Only undo should be available. Similarly, the game should detect when a puzzle is complete and move to the next puzzle.
  • Collectibles and unlocking – I want there to be some kind of collectible in the levels that the player must collect in order to finish the level or unlock more levels.
  • Design some puzzles – design 10-20 puzzles using only the basic mechanics implemented so far.
  • Implement puzzles – drag and drop assets into Unity to implement the puzzles.
  • Simple UI – both HUD elements and menu.

I think focusing on the puzzle design in the next week would be a good place to start as the puzzle design may make me realise I want to implement some of the mechanics slightly differently to make things more interesting.

Week 1 and 2: Waypoint movement and code restructuring

Published / by robsws

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.

Week 1

Plan

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.

Features

Waypoint Movement

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.

Issues

  • 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.

Week 2

Plan

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.

Code restructure

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.

Level building

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.