Sunday 11 December 2016

The A-Star Algorithm

A-Star Pathfinding

Individual unit requests

First of all, we need to tie the existing pathfinding algorithm to each unit so the player can move them individually. I've written this code in the unit manager class so that when the player right clicks, all highlighted/selected units are queued for pathfinding.
This runs the "startPath" function in each object's basic unit class. This function queues the unit for pathfinding with the unit's current position. When pathfinding is complete, the path manager class then runs the callback function, which in this case is "onPathFound".
The "onPathFound" function stops any current movement coroutines and starts a new movement coroutine if the pathfinding algorithm was successful. The movement coroutine moves the ai in the direction of the next waypoint until is has reached proximity with it, then continues to the next waypoints in the list. The velocity is normalised because otherwise, the ai would have a greater velocity for further waypoints.

Path request manager

The path request manager queues each unit one by one so that multiple states of the algorithm aren't running at once, reducing performance. It does this by creating a "struct" (as of Microsoft's documentation, a struct is a value type that encapsulates groups of related variables)1. The struct stores the start, end and callback variables. When a path is requested, a new struct is created with the unit's pathfinding information. It then queues this request and attempts to process the next request in the queue (if the queue's size is greater than zero and it is not currently processing, then it starts the process). Also, once a current process has finished, it also tries to process the next request and activates the callback with the success boolean and found path.

Turning the algorithm into a more efficient and accurate a-star algorithm

In order to transform the algorithm into an a-star algorithm, new variables must be added to the nodes. The gcost is the total cost of movement from the star node to the next node. The hcost is the total cost of movement from the next node to the end node. The fcost is the total cost of the node (gcost + hcost). The algorithm now checks whether the new gcost of the node is less than the current gcost or whether the open list does not contain the new node (If the node hasn't been checked already). It then applies the gcost and hcost of the new node so they can be read later. The next node is now the parent of the current node (This is stored in a new variable within the node class) and is added to the open list.
This new piece of code cycles through all available node in the open list and checks them to see if their fcost is lower than the current node. If so, that node now becomes the current node, is removed from the open list and is added to the closed list.

Once the pathfinding process has finished, it tells the path request manager after retracing the path, passing the waypoints. To retrace the path, the function simply gets the end node and finds its parent and so on. It then reverses the path so that the unit can follow it.
1. https://msdn.microsoft.com/en-us/library/ah19swz4.aspx

Sunday 4 December 2016

Camera Movement

Camera Movement

Keyboard controls

We'll be using common key-binds WASD to control the camera and pan it across the play area. To zoom, page up and page down can be used as to not conflict with possible future key-binds.
The input axis "horizontal" and "vertical" take into account both WASD keys and arrow keys to add force to the camera's container object which also has a rigid-body element. There isn't a equivalent axis for page up and down in Unity's inputs, requiring the creation of one manually. However, for efficiency I have simply coded the inputs. The downside of this, however is that the player can't adjust the key-bind. This shouldn't be a problem at the moment, though as a control menu hasn't been implemented.
The code is simple; if page down is pressed then the camera's container gets a downwards force added which means the whole rig is consistent and doesn't leave us with any bugs that we might have whilst not using a rigidbody element.

Mouse controls

The mouse controls will consist of two things:
Scrolling via the mouse wheel and panning by moving the mouse to the edge of the screen.
This requires a proximity check which can be achieved by comparing the mouse position with screen positions.
Here, the mouse minimum boundaries are simply 30 units, which I deemed a good number for responsiveness and it is not too big as to disrupt the flow of gameplay in the center of the screen. The maximum boundaries are the screen width and height subtracted by 30. If the mouse cursor crosses these coordinates, then the camera is panned in the corresponding direction.
Next, we need to zoom using the mouse wheel. Unlike page up and down, the scroll wheel has a dedicated input axis already implemented within Unity, so we'll be using that.
I added the code to an original addforce function, however I needed to invert the scroll wheel axis and multiply it by 35 in order to get a big enough movement that feels natural.
Currently there is no need to add a rotation control to the camera, however if obstructing buildings and objects are added then this will be implemented. A lot of RTS games such as Starcraft and League of Legends don't include a rotating camera because often it isn't needed and sometimes even disorientates the player due to the change of perspective.

Thursday 1 December 2016

Selection

Selection

Basic Unit Selection

In order to select units I created a new "Unit Manager" class in which I can store and manage all the unit's information. A unit is selected by ray-casting relative to the mouse position, then checking if the object hit was an AI unit. If so, then the unit's projector element is enabled to provide feedback of the player's action.
We need a way to select single units at once, however so to do this I created a list of units so that when a new unit is selected with the left mouse button then it loops through all currently selected units, disables them and then removes them from the list.
To select multiple units now, the player must hold down shift which disables the removing loop.
Finally, one of the most common features in an RTS that improves usability is a box select. A box select lets the player drag a box that selects any unit inside it, allowing for quick mass-selection compared to shift-clicking. This was achieved by checking if the mouse had been clicked and dragged a small distance which would then trigger the creation of the selection box. The selection box is created by storing the mouse's original position and creating a rectangle to the current mouse position. Visually, the box is made up of a 1px white image that is repeated. A lower opacity is used in the middle for clarity. The colour of the box can be changed in Unity's editor and can be transferred to in-game easily at anytime.
The only other features to add consist of combining the multiple ways to select units. Later on, when enemy ai are involved the function will have to be updated as to not select them.