I met Dr. Guy and viewed the lab and where we would be working. Afterwards, we talked about the process of making video games and how it entailed getting user input, making AI and simulations, Modeling, and rendering.
Then, we proceeded to converse about some applications for crowd simulation that Dr.Guy had mind such as figuring out if certain structures were safe to inhabit and if a certain number of people could evacuate certain buildings in time among other things.
Additionally, we talked about different game engines that could be used for the different parts of the game creation process such as Blender, Unity3d, and Mitsuba. Following that, Dr. Guy introduced us to the Unity3d game engine.
Later, we downloaded Unity 3d and watched the video tutorials that were shown to us with the download. After watching the video tutorials, Dr. Guy gave use a few Unity 3d Tutorials that he knew of to work on.
The rest of the week was spent working on the runner tutorial to get a basic understanding of the unity3d engine and it's functions.
After we were finished with the tutorials that Dr.Guy had given us, we started new project in an attempt to get cubes moving
randomly on the screen.
Eventually, we were able to get cubes moving on the screen using some of the features from the Runner tutorial and some of the posts on the Unity3d forum.
Moreover, we used the "MoveTowards" function, which was a part of the Vector 3 class, to move our cubes to certain points on the plane that we created. Additionally, we used the random number generator in Unity3d in order to give them random goals.
After this, I worked on instantiating a cube by itself on command in order to give each cube a unique random goal.
To do this, i eventually used the "Instantiate" function of Unity3d along with the concept of "prefabs" which I learned from the Runner Tutorial.
Dr. Guy introduced a new formula to us which updated each cubes position based off of it's velocity. Likewise, we calculated each cube's velocity based off of it's distance from the goal, and it's distance from the nearest cube. Hence, to implement this formula, i had to find a way to enable each cube of where every other cube on the plane was.
My solution for this problem was to put the cube prefabs in a global list that each cube would be able to access and perform computations with.
As such, i proceeded to instantiate each object in a global list when a certain key was pressed. Afterwards, i worked on enabling each instantiated object(prefab) to be able to access the global list and perform computations with the positions of the other cube.
I was able to successfully do this by utilizing one of the many methods that Unity3d has for accessing the scripts of objects which was called "GetComponent".
After i had successfully enabled each cube to access the global list, i had each cube's velocity be a vector pointing towards the goal with a magnitude of one, and a scalar that would change based on certain conditions. Additionally, i also made each cube change position when they reached an adequate distance to their goal as getting to the exact location in a good amount of time proved difficult when moving at a velocity that was too fast or too slow.
Following that, i added a component to each cubes velocity that was a vector that started from the position of the closest cube towards the cubes own position . This vector had a magnitude of one and also had a custom scalar that would change based on certain conditions.
This method proved to produce successful collision avoidance however, the motion that the cubes moved in was somewhat jerky and sudden and it was not a good representation of the way actual humans moved.
After discussing this with Dr. Guy, he suggested a formula that would have the objects anticipate collision.
The formula that Dr. Guy spoke of uses the quadratic formula , along with the object's current position, the object's velocity, the closest object's current position, the closest object's current velocity, and
the radii of both objects to determine the time in which a collision will occur(if a collision will occur).
The important conditions of this formula are if the time is negative, or if the determinant is negative. If either of these cases happen, no collision will occur.
However, if the times are positive, then the least amount of time is used in a formula to calculate the future point of collision.
Afterwards, the object partially moves away from the future point of collision and towards its goal at the same time.
This happens because a portion of the objects velocity is moving away from the future point of collision, and towards the goal as well.
On Monday, i attempted to implement the formula and I started troubleshooting to get it working.
At first, the cubes would move and appear to be anticipated collision. However, they were still not displaying the anticipated behaviour.
After more troubleshooting, the cubes would move in a jerky sudden motion away from the point of collision and consistently get stuck in place
After encountering these issues, I set up a known configuration to help me debug the situation so that i could figure out what exactly was happening and what exactly was going wrong.
In this configuration,(these, (x,y,z) are points in the plane) I had a still cube(non moving) at (5,0,0) with no velocity, and a moving cube that started at (0,0,0) with a velocity of (1,0,0) .
In addition, i turned off avoidance to assist in debugging the formula function.
After calculating what the collision times for the configuration should be by hand and running the configuration in Unity3d, i found out that the times were not correct.
Following that, i adjusted formula and managed to get the correct time. Then, i started working on getting the avoidance method to behave correctly.
Afterwards, I adjusted the avoidance formula to move away from the colliding position of the opposing object
towards the future position of self(object).
Eventually, the avoidance collision was working for the most part.
Later, i decided that i needed to tinker with the scaling of the avoidance force to see if a favorable setting can be found
in which, the avoidance would look natural.
Additionally, i also decided to set certain scaling amounts for certain cases which may arise.
This week, I decided to make the movement a function of time in hopes that this would sure up the collision avoidance formula. Within this function, the component of the velocity that is moving towards the goal gets smaller as the time towards collision gets smaller (it has a positive correlation with the time), and the component of the velocity that is moving away from the point of collision gets larger as the time gets smaller (it has a negative correlation with the time towards collision).
After this, I spoke with a coworker about my method as I was not getting the exact results that I wanted. During our discussion, he explained that he always had an additional force that moved away from the closest object regardless of whether a future collision was detected or not. After hearing this, I decided to implement a similar force whilst multiplying it by a scalar that was supposed to change the intensity of the force depending on how close an object was to the closest object.
To do this, I decided to change the return type of the get collision function from a Boolean to a float so that it would always return the time. Hence, if both of the times were negative, "-4" would be return from this function and my movement function would handle the time accordingly. Likewise, if the determinant is negative, "-5" would be returned from this function.
Additionally, if both of the times were not negative and the determinant was not negative, the lowest non negative time was returned.
Afterwards, in both cases that a negative time was returned, there was no avoidance force applied. However, there was always a force that moves the object away from the closest object as was done in a coworkers method. This force was inversely proportional to the distance between an object and the closest object to it.
Upon changing my movement function to behave as described, the objects were finally avoiding collision the way we wanted.
The next thing I did was contact Dr. Guy so that I could speak with him about the next step that I should take with the project. Being that we now had the collision avoidance working, he suggested that I try to get animated human models working and not just cubes.
With this new goal in mind, I started searching the internet for 3d models and I found some free models in the Unity asset store for free. When I downloaded a couple models from the asset store, I loaded them into my project as prefabs in order to use them.
After I utilized the prefabs, I now had the models moving and avoiding collision with each other. The only problem was that the models were stuck in a “T-position" and they wouldn't always face the direction that they were moving. To rectify this, I attempted to get animations and put them on the 3d models in the hope that the models would perform the animation. As such, I once again went to the Unity Asset Store, only this time I went in search of free animations.
While in the assets store, I found a few free animations and I downloaded them in order to use them. When I put the animations on the prefabs, they did not perform the intended animations.
Being that I was quite stuck at this point, I consulted some of my coworkers for advice of how to approach getting animations on my 3d models. During our conversation, they suggested that I post on the Unity Forums for help with my dilemma. As such, I made a thread about my problem in the Unity scripting forums and I also posted a question about it in the Unity questions section.
On Monday, when I checked the Unity forums, I saw that the thread that I posted had not received any replies however; the question that I posted had received one answer. As such, I proceeded to look at the answer that had been posted to my question.
In response to my question of how to animate these characters in the specific way that I wanted, this individual suggested that I watch the Mechanim animation tutorial as it covered a lot of material.
After reading this, I proceeded to watch the Mechanim animation tutorial as suggested. In the Mechanim tutorial, I learn a plethora of things about the animation system and how many things functioned.
A few things that I learned were about to rig an Avatar, how to create animator controllers, how to develop conditions for animations, to edit animation clips, and many other things. Additionally, while I was watching the tutorial, I also followed along and did everything as the instructor did so as to gain a good understanding of the material.
After watching this tutorial, I added the animations to the assets of my own project in order to use them.
Following that, I created my own animator control and I added the "walk forward" animation from my assets folder to it, as the base animation. Then, I simply dragged the animator onto the 3d model, and de selected "apply root motion" to make sure that the animation would not move the character. When I did this, I finally had animations the working the way I wanted! Only a small problem remained and that was making sure that the models faced the direction that they were walking in. I rectified this by using the "LookRotation" method of the "Quarteon" class of unity in order to make the models face their goal during every frame.
At this point, I finally had walking people who avoided collision avoidance properly. As such, I talked to Dr. Guy again to discuss what I should do next in the project. When we talked, Dr. Guy suggested the idea that I enter an option in my code to be able to export and import data similarly to what a few coworkers of mine were doing. Moreover, Dr. Guy suggested that I work on exporting data to a file first, and Dr. Karamouzas also explained a couple of different formats that could be used. After this discussion, I started working on addition an opinion to export data to a file. Being that I was still learning the c# language, I simply read up to and past the chapter that concerned file input and output so that I would know how to use those functions.
For the file output, I posted the number of agents to be written, the number of time steps for which they would be written, and the x and z positions as well as the x and z velocities of each object during each time step.
To do this, I simply created a Boolean value in my script to signal if a file is to be exported or not and during each update frame, my manager script would write all of the positions to the file in the order specified above. After I accomplished this, I showed it to Dr. Guy and I then started working on reading from a file.
To accomplish the importing feature, I had to do a bit of brainstorming and I also consulted some of my coworkers. After a bit of brainstorming, and speaking with my coworkers, I decided to attempt to read the file starting at certain lines and then to go from there afterwards. I had a hard time figuring out how to do this in c# after searching on the internet. Instead, I was able to find alternative suggestions to questions that were similar to the one I was asking that were useful. The primary suggestion that I found was to read all of the files into an array of strings and then work with the array instead of the file. This seemed like the most plausible solution to my problem and hence, I started working on this.
After a while, I was successfully formulated an algorithm for reading the file and rendering the simulation based off the data in the file.
To do this, I read the entire file into a string in my manager string and used the first two lines to instantiate the required amount of agents, whilst setting a Boolean in each movement script for the agents to be true.
This specific Boolean signified that the objects movement would be based off of the file instead of from our previous random movement method. Following this, each script would read the same file into their own array and start at the line that corresponded to them.
Afterwards, they would read that line, move to the position that was specified on that line, and then read the next corresponding line the next time the update function was called. Moreover, this process would repeat for the total number of time steps.
The only issue with this was that the simulation played back somewhat fast and that the agents would not always face the way they were moving.
For me, the second problem was easier to formulate a solution for. As such, at every frame I decided to get the agent's future position and have them face that direction until the last update/time step and this was done for each agent. Thankfully, this solved the issue of the agents not facing the correct direction.
On Monday, Dr. Guy spoke with David and I about ideas for our final project and how to integrate it. Furthermore, Dr. Guy wanted us to combine our two methods of crowd simulation so that we could have an application that would let us choose between either method, and then allow us to choose to render a simulation from a file or to show collision avoidance, or to export data to a file. Moreover, the options within David's version would also be useable.
Furthermore, Dr. Guy wanted the final project to have a GUI that would enable the user to easily be able to choose the desired options. After we discussed this, I started doing research on how to make a GUI in unity so that I could implement it into my project for the final Project.
During my research, I looked at documentation on the GUI class in the scripting reference manual and tutorials on the Unity website. Being that the GUI system of Unity was a bit more complicated than that of .Net's (the .Net Framework), which is incredibly easy to understand, and that the documentation on the Unity website was not the best, I also looked up some tutorials on YouTube for different points of views on Unity's GUI system.
After watching a couple videos, I started to understand how the GUI system of unity worked, and how I would go about making my own GUI.
To start off, I made a new scene for my main menu and I made a menu object that would hold the script for my main menu. After this, I created a Window that had the text entitled "Main Menu" and two buttons that would lead to different menus.
One of the buttons allowed the user to choose the opinion to use the Predictive force method of collision avoidance that I had been working on this summer.
Afterwards, I created another scene for the menu of my Predictive force method and I linked the corresponding button from the main menu so that it would load the Predictive Force Menu upon button press.
From my Predictive Velocity menu, I had two more buttons that would lead to two different menu scenes. One was for rendering a simulation from a file, and the other was for simply simulating collision avoidance and/or exporting data to a file.
Following this, I made two menu scenes for each button and I linked the buttons to the corresponding menu scenes. Now, on both of these menus, I had a data object that would hold the settings that the user selected. These settings included file names, the choice to use capsules instead of people, and the number of agents and times steps that are desired to be exported, etc.
On both the Render and the Simulation menu, I took the user input and I showed error messages if the user had done something incorrectly. Furthermore, I did not allow the user to pass until these errors were rectified.
After successfully entering data, I transferred the data to my data object and then switched the scene to my collision avoidance scene. Moreover, I changed my collision avoidance scripts to take the input from the data object that had been passed over from the previous scene and to perform the desired operations.
At this point, I had the GUI my part of the project done, and the majority of the final project was done as well. Then, I gave my code to David so that he could start working on his part of the GUI over the weekend.
During the weekend, I helped David out understanding the GUI system and giving him suggestions when he needed it and I also added a few new options to my menu scenes.