Flocking Tool Tutorial

This is a tutorial on how to use the 3D flocking tool I made for Unity.

Firstly, Drag the Flocking Manger Prefab on to the scene.

tut1.png

Next add whatever prefab you would like to represent your boids. Make sure to attach the boidController script onto your selected prefab as well.

tut2.png

Set how many boids you would like to have in the scene at once and set how big of a spawn area you would like, the spawn area also affects how much room the boids have to move in as well.

tut3.png

Now we set a target, tick the use target bool if you want to use a custom prefab as your target else leave unticked it will use random position within the spawn area.

tut4.png

Now moving onto the boid, add a set maximum speed in the “RandomnessSpeed” value and so the same for the “RandomnessRule” which will change how often the rules are applied to the boids every update.

tut5.png

Lastly choose a rotation speed on how fast the boids can rotate and set a neighbour distance on how close they can before they are pickup into a group and a seperation distance value on far each boid is to each other in the group.

tut6

Thanks for Reading 🙂

Tool – 3D Flocking System

This 3D flocking tool is designed to simulate complex movements with boids within a 3D space. It does thought the use of two different scripts:

  • Boid Controller which controls the behaviour of the boids
  • Flocking Controller which controls the space, how many boids there are and the target.

FS1

The flocking controller is the first part in making this system work. It controls the amount and stores every boid in the scene. Controls the area the boids move in and sets the target for the boids to move too. How this all works is that,

Firstly there needs to be some boids in the scene before anything can happen. How I did this was creating a public game object that stores the boid prefab, an int that controls the number of boids on the scene, an array that stores every boid in the scene and another int to store how big of an area the boids spawn and move in.

With this I cycle thought the array of boids and getting a random X,Y and Z position before instantiating the boid onto that position and pushing it back into the list.

Code:

void Start ()
{
 boids = new GameObject[numOfBoids];

 for (int i = 0; i <= numOfBoids; i++) //Random starting positions for each boid in the list within the spawn area.
 {
 Vector3 boidPos = new Vector3(Random.Range(-spawnSizeArea, spawnSizeArea), //X
 Random.Range(-spawnSizeArea, spawnSizeArea), //Y
 Random.Range(-spawnSizeArea, spawnSizeArea)); //Z

 boids[i] = Instantiate(boidPrefab, boidPos, Quaternion.identity) as GameObject; //Instantiating the boid onto the scene
 }
}

Result:
FS2

Next up is the target and I had set a bool to check if there is custom target the user wants to set else I just choose a random position to be the target at random times.

Code:

void Update ()
{
if (addTarget) //if there is a custom target that the boids should go after
{
targetGoal = targetPrefab.transform.position;
}
else
{
if (Random.Range(0, 5000) < 50) //Else get a random position that changes randomly as well to keep the boids moving
{
targetGoal = new Vector3(Random.Range(-spawnSizeArea, spawnSizeArea), //X
Random.Range(-spawnSizeArea, spawnSizeArea), //Y
Random.Range(-spawnSizeArea, spawnSizeArea)); //Z
}
}

}

Result:
FS6

Once the boids are in the scene I needed them to start moving around the scene, I did this by giving the boids a random speed when they spawned, and had to reference both the flocking manager and the flocking controller before I could apply the rules to the boids.

Code:

void Start ()
 {
 boidSpeed = Random.Range(1, RandomnessSpeed);
 FlockingManager = GameObject.Find("Flocking Manager");
 fc = FlockingManager.GetComponent&amp;lt;FlockingController&amp;gt;(); //Finally got the reference corret
 }

In terms of the rules for flocking, I need to keep in mind the Alignment of the group of boids, the cohesion of the group of boids and the separation of the group of boids. To do this I got the group the boids from the flocking controller and stored into another array inside the boid controller so every boid would have a list of every boids on them. With this I needed to figure out how close all the boids are to each other, This involved performing a distance check on every boid in update to see if any boids were close enough to be picked up. Boids that were close enough were called neighbours and were added to a group.

Code:


 float dist; //Distance

 int groupSize = 0;
 foreach(GameObject bo in bos ) //Calculating the group distance between boids to see if they are within range to become part of the group
 {
 if (bo != this.gameObject)
 {
 dist = Vector3.Distance(bo.transform.position, this.transform.position); //Getting the distance between each of the boids
 if (dist &amp;lt;= neighbourDistance) //if they are in range of their neighbours
 {
 vCenter += bo.transform.position; //Update the center of the group
 groupSize++;

 if (dist &lt; 2.0f) //if they are too close
 {
 vAvoid = vAvoid + (this.transform.position - bo.transform.position); //push them in the other direction
 }

 BoidController anotherBoid = bo.GetComponent&lt;BoidController&gt;(); //Getting the boid script off the neightbour and adding the group speeds together so we can get an average
 groupSpeed = groupSpeed + anotherBoid.boidSpeed;
 }
 }
 }

You can also see that there is another distance check at the end that checks if the boid is too close to one another and there fore move in the opposite direction to avoid hitting it. I also needed to add the speed of the new boids together in a group speed value so it can averaged out later on.

Result:

FS3

Now that there is a group of boid together, next rules need to be allied, cohesion and alignment. This involved getting the current center of the group and averaging out the speed of the group as well. I then needed to average out the direction the boids are looking and moving in based on the center of the group, their current position and the avoidance distance. If at any point the boids end up hitting the end direction or target then I perform a Quaternion.Slerp to rotate around the target instead.

Code:

if (groupSize > 0) //if there is a group
{
vCenter = vCenter / groupSize + (targetPos - this.transform.position); //getting the center of the group
boidSpeed = groupSpeed / groupSize; //averaging it

Vector3 direction = (vCenter + vAvoid) - transform.position; //direction the boid needs to move in
if (direction != Vector3.zero) //if not on the right direction
{
transform.rotation = Quaternion.Slerp(transform.rotation, //rotating the boid to go in the correct direction
Quaternion.LookRotation(direction),
boidRotationSpeed * Time.deltaTime);
}
}

Result:

FS4

 

FS5

This was the basic’s of flocking currently implemented into this system. I lastly added one extra feature that checks if the boids are out of bounds. As if the boids were to be seperated or not join in a group they would move forever and not find anything so another distance check was done if they have left the spawning area set in the flocking manager.

Code:

if (Vector3.Distance(transform.position, Vector3.zero) >= 20) //if the boids move out of bounds (size of the spawn area) then they turn around
{
turning = true;
}
else
{
turning = false;
}

if (turning) //A quaternion.Slerp to rotate the boids back towards the center of the spawn area and give more opertunities for the boids to become groups
{
Vector3 direction = Vector3.zero - transform.position;
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), boidRotationSpeed * Time.deltaTime);
boidSpeed = Random.Range(1, RandomnessSpeed); //Give the boid a new random speed if selected
}

This is current flocking system I have made, hopefully it all made sense.

Thanks for Readying 🙂

 

 

My Personal Postmortem

Thought out this trimester I have been trying to push myself harder in the amount of work I do and how fast I can finish it. Thought this I am glad to say that my performance in studio 2 is much better then my studio 1 and despite me leaving a couple of thing towards the last minute, I am still happy with my performance as a whole.

During the start of the trimester I focused mainly on work and trying to gather as many long term tasks I could that I could do over the tri. I was doing this to, again help push myself and, start preparing work I would use to get a higher mark then a pass, as I got a pass concede last time and didn’t what that again. The collection of tasks I had was actually quite good,

  • Maths Library
  • Animation Showcase, Where I was going to create various shaders that the animator can use.
  • Stencil Portal Side Project, Where I was going to try and emulate a portal though stencil shaders.

I felt and setted up a lot of things to do throughout my weeks to come. However, Once the main bulk of work started to come in with creating A* for path finding bots and my terrible c++ coding skills. I ended up focusing to much of my time trying to get the bot to work and not a lot went into designing a maths library. The animation showcase team ended up disbanding as the project was meant to only be for a single person and not an entire team so I lost that as well. This only left the portal side project which I did put some effort into, trying to create a seamless transition between two different coloured planes was fun and challenging to try and do. But with my new major project to work on I stop working on that project all together and focused my time completely on the main game.

In terms of the kill bots we had to make during the first half of the trimester, I undoubtedly had a number of issues when it came to writing in C++. As I think in a very C# manner, it was hard trying to make the conversion of thing and that made in some of the more basic stuff hard for me to do. The first half however was do able and I eventually figured out how to use the framework given to got some custom behaviours going however when it came to path finding, that is a whole other issue.

For me AI from a theory point of view is quite easy to understand. I can comprehend what the AI is doing and even plan out the steps. However when it comes to actually writing the code its another matter, I tend to over complicate a problem to the extent where solving it requires a super complicated solution and after I hit this faze start to take steps back and re look at the problem and come up with something easier. This is no exception for A* coding. I had many issues trying to pass in the different nodes around the bot and calculating the various F,G and H costs of each node using the lists I had made and by the time I started to get a easier picture it was a little too late. I did re-attempt A* in unity a little later as well to try and get it working but to no avail, this is something I would want to try again just to figure out.

In terms of the major game, I had a lot of fun making it with everyone in the team and had a few challenging moments in throughout it to help improve my skills. One such moment was creating the gravity swap mechanic where I had to learn more about Quaternions, Eular Angles and Yaw, Pitch and Roll to get it working to way we wanted it. Throughout out the development of Anti-Gravity I like to think that my communication with my team was good as I kept within reach whenever I was working in case people had questions and was apart of every meeting I was called too. In terms of my time management it can always be better but managed to keep mostly on track with only a few instances being pushed behind and needed external help in order to solve it.

I problem solving skills could have also been better as I normally just keep to the basics when coding to try and keep the code as simple to look and use as possible, but while working with a friend who codes at a more advance level, it helped jog my memory about inheritance and polymorphism and it became a big help to cut out some of the tedious coding I was doing. Like instead of creating a series of checks for buttons, A single virtual method for interacting with buttons was made and override to the button was used instead which made buttons much easier to deal with in a scene.

Overall I felt I had done better in managing my work and time throughout this trimester then last and that was the main goal in the first place. In terms of improvements, try to use more advance coding methods to make my jobs easier and slowly add more extra tasks to do over the course of the trimester and not just all at the start to manage them better.

Thanks for Reading 🙂

 

Anti-Gravity Postmortem

This post mortem will be reflecting mainly on all the work I have done for the project and therefore wont have much in terms of critical game design decisions but more the code and systems I wrote along with methods and issues that came up. There will also be talk about how my code affected the project and the other people working on it as well along with how I worked with them in general.

The Good:

Gravity Swap System – This was the most important task and system I had to make for this game and I am glad to say that it turned out great and accomplished its goal and our expectations. The gravity swap system had many iteration happen to it before I landed on the version we use today, I originally wanted to use raycasting and lerps to move the player between the points of where they are currently standing to the closed point on what ever bound the ray hit, thinking that it would be an easy way to get accurate transition between the floor and roof. However this did cause when it came to keeping the player on there new location and rotation. This then lead to a suggestion to use the gravity multiplier in the First Person Controller we were using to swap the gravity on the player and that would keep them on whatever side we wanted. Once this was in place and it worked, I realised that there wasn’t a need any more for the raycasting and left it completely to gravity.

Rotation on the other hand is a completely different story, this caused a lot of issues for me as I could never get the rotation of the player camera correct and make it roll correctly around the Z axis 180 degrees, for the most part. The system originally used a Quaternion.Slerp to perform this action however this caused a rotation issue where the player camera would move towards 0 as the transition happens before finishing and returning to the desired rotation. After a little help from my lecturer, and demonstrating Yaw, Pitch and Roll for me, I was able to use a second script that would take take the Yaw, Pitch and Roll values and return to Roll back into itself while performing the transition and what would cancel the main rotation issue.

Why the player cannot move during the transition is the solution to a fault in my grounded check for the player. I need to know when the player is on the ground and a use a Collider check to see if the player has hit the ground or not. Whoever if the player was running or moving while they pressed space, it might not register that the player has left and the transition wouldn’t happen. So the counter to this was stopping the player from moving during the transition. Other was stopping the players horizontal camera control during the transition and this is for a simpler reason as it would cause a jitter whenever the player landed as it was updating the cameras location after the transition was ended so to stop that I stopped X sensitivity to the camera during the transition.

The effect this system had was quite massive, not only did it allow for the great dynamic game play, but with a sped up rotation and made the transition less disorientating and made it more enjoyable to look at and use.

Communication – I felt my communication with my team was good throughout the development of this project. I keep myself within reach for most of the time I was working, staying in our slack channel if anyone needed to ask me something, and for most of the time being on time for various Skype meetings about our progress. However there was times outside of work or when I had other things to do that I didn’t tell the rest of my team mates and therefore didn’t know where I was or what I was working on which did have some minor issues when it came to deadlines.

In terms of what I would improve next time would be keeping my team more informed of what I was doing when I wasn’t going to work or if I had other things to do so it completely negate the minor deadline issues we had prior on when things would be finished.

The Bad:

Dialogue Trigger System – The dialogue trigger system was meant to be a designer friendly system that was meant to trigger audio whenever the player interacted with various objects. This however was a bit harder to make then I first thought. In the end the system did work however it took quite a bit of effort from not only me but other people in our team which caused them to stop working on their own projects to help with my issues and that’s why I fell this was bad.

How I wanted this system to work was a series of bools that were used to check what object the script was on. I did this as it was an easy method of showing and determining what object the designer was going to using. The script would then run a series of if checks, each taking the their respective bool into account first. I choose if statements to do this as they were the quickest to perform and less issues would happen as they were stored away in there own functions.

For collision I used OnTriggerEnter() to check if the player entered a certain trigger, this is for the same reason of its was the quickest to perform as we only needed to check if the player was there or not. For buttons I got a little help from another script that was used to setting off the reset mechanic by inheriting an interact function which checks for when the player interacts with the collider of a button. I did this as my previous solution could potentially trigger dialogue from the wrong button as it was just a check on if the player pressed something.

Picking up boxes was a similar deal with a check to the box itself and seeing if it is being picked up or not. This was the easiest solution as it was already there to be used. Lastly powering doors was done by checking a powered bool on the receiver to the door needed. This was the quickest to perform instead of checking for height ranges on the door itself.

Audio was a main feature with this system and was used, it just plays the audio file that was placed on the players location. This would mean you cannot have audio playing anywhere else but the players position nor could you have multiple audio files at once as I didn’t use an array to store them. This was because the only audio would be from the AI and it would only be speaking directly to you and wouldn’t say multiple things at the same time.

Later on text was also added as Audio did happen a little too late. This was just adding a canvas to the player and displaying instant text of what the AI was saying.

How I would make it better would be to add array’s for audio storage so it can be called more easily and you wouldn’t have to place each individual audio clip in at a time, saving time and making it easier to config.

My Own Performance:

As I mentioned before communication was one of the better aspects I felt I did throughout the development of this project, by keeping in contact with my team-mates nearly all the time while I worked but had some issues will I wasn’t. Time management is always a constant issue with this project being no exception, There were times that I was on point with the work I was doing keeping up to date and having everything work out but there was also a series of times where I slacked off the work a little and that caused me to fall a little behind and had to quickly catch back up.

In terms of my coding, it could have been better and defiantly quicker. I tend to overcomplicate a situation and spend a lot of time figuring out massive complex solutions to what is normally a simple problem. the gravity system is a great example as I spent far to long building big lerping system instead of just swapping the gravity, you would think with a game called Anti-Gravity I would pick up on that quickly.

In terms of improvements, structuring out more of my time better as it wasn’t the best throughout this project and reacting better to when life things occur as well as there was a couple of times unexpected things happened and I could work around it, pushing myself more and more behind. Lastly would be to take steps back and thing more calm about a situation so I stop wasting time when it comes to building solutions.

Thanks for Reading 🙂

 

Anti-Gravity : Idle Animation Asset

While working on my tasks to the Anti-Gravity prototype, I decided to make an idle animation for the floating AI in our game as whenever it stopped moving it would just stay still hovering in the air and it looked quite dull.

Task:

  • Make an idle animation that would play after the AI has stopped moving.
  • Make the animation seem appropriate to the AI as a character (Small metallic object, floating in the air).
  • Don’t over complicate the animation

So with this animation, I wanted it to be quite subtle with its movements, noting to large to make it look like the AI was going to move somewhere else but enough to make it look like an actual floating AI bot that is in the room. In terms of inspiration of the movement I was looking in to the movements of robots like the eye bots from fallout with how they bob up and down when flying though the air and that was that I want this bot to do as well.

With this initial idea of how the animation would look like, I began working in the Unity animator. Making the animation was quite easy, I setup the animation with ten key frames to make help speed up the animation a little because I felt it would move to slowly going down to four or three as those are the only key frames I really need. I animation starts by moving downwards for about half a unit, and then returns to the center and then moves up half a unit. This caused a bounce effect to happen in the middle of the animation when it was returning to the center and makes it look more like it generating thrust upwards and gives a nice look to the overall animation.

Untitled