# Blog

## Last Fate Postmortem

What Went Right

Game Concept

The class at Academy of Art University that was responsible for the inception of Last Fate was actually a technology research class. It’s purpose was to have students experiment and develop prototypes using emerging technology. Last Fate was initially going to be a proof of concept game demonstrating the use of mixed reality, utilizing Leap Motion, Oculus Rift and the Unity game engine.

This was a good combination because the immersion of the Oculus combined with the tactile feeling of having your hands interact with the virtual space made for an extremely compelling and new experience. The result from play testers were reactions of surprise, excitement and genuine captivation.

Prototyping

Unity was a powerful tool for quick prototyping. This was crucial to the development of Last Fate because experimentation with new tech meant many game play design failures before we achieved a satisfactory result.

Additionally, our team experience with Unity meant a smoother reiteration process. We could design, create and test within a reasonable amount of time considering the actual in class time with the professor was only three and a half hours a week. It also meant we could get students outside the project to play test frequently and get instant feedback.

Integration of New Tech

This was a double edged sword. The initial integration of Leap Motion was smooth, and learning the Leap API was a fun task. However, as is with any new tech, Leap Motion’s growing pains resulted in our growing pains as well. Leap Motion software updates were frequent, which was good because we knew the developers were dedicated to supporting their product and that hopefully our project would continue to be relevant for years to come, but it also resulted in our build breaking every time we updated. We would need to investigate each time as to what changed and fix it, which was every other week. Additionally, Unity 5 was just emerging and we were anxious to update there as well, but of course that also lead to compatibility issues between Unity and the VR tech.

Despite these setbacks, which took a lot of time away from focusing on designing the game play, we were able to provide a working prototype week after week.

What Went Wrong

Communication Breakdown

The first semester working on Last Fate was a intimate experience in a very small team. This made communication easy. The second semester the Last Fate team grew much larger. We had individual leads for each section of the game, and despite lead meetings and weekly three and a half hour classes, there were communication issues and misunderstandings which lead to a severely incomplete product.

My initiative to bridge the communication between the programmers and the level designers was a success, however still resulted in a lack of understanding. Parts of the team were waiting on information from others, which halted production in certain areas and resulted in last minute scrambling to put levels together. The first three main sections were completed just in time which was enough for about six to seven minutes of game play. Fortunately this was enough to portray a clear demonstration of emerging technology in gaming.

Perforce

Many students who took part in Last Fate had little to no experience with Perforce. There were many hold ups and mistakes that had to do with Perforce, for example certain files would be corrupted every time a new submission was pushed. In our case it was a water shader. Other times students would check out more files than necessary, holding up operations from other areas. Sometimes files that we needed would be accidentally deleted.

We were able to recover from all these mistakes, however there was so much time spent on fixing Perforce mistakes that the game suffered from it. Sometimes simply adding a quick animation to an object and pushing it to the build would break other things, or the animation would be lost somehow. This would happen in times when we needed a new version because we were about to have a play test session in the next 10 minutes. There was inevitably much improvisation, which resulted in backpedaling and more work than there needed to be.

Conclusion

There was a lot of personal growth for everyone on the team including myself. Communication is extremely important, and asking questions is just as important as informing others of your own status or information. It’s also important to have a solid understanding of version control software, because mishandling could result in not only your own setbacks but other as well.

Technical and communication set backs held Last Fate from becoming a full game experience. Overall, Last Fate was a successful project that met its goal of providing a new exciting experience to the gaming world. Since then I have never played a game like it, at least not with out more hardware than Last Fate used, like dual hand controllers of the HTC Vive.

Here is a short video of a student play testing Last Fate

## Bezier curves for flight paths in Unity C#

For my mobile game I needed enemy space ships that would fly to random points in space within a specific area. When they reached the designated point, they would choose a new point and the process would repeat. First I tried the easiest solution: transform.LookAt(), which worked, but the space ships had a specific turn radius and under some circumstances would circle the destination point indefinitely. I could increase the distance that was required for the ship to “reach” the checkpoint but I wanted to guarantee consistency.

Bezier curves would allow me to have consistent flight patterns without having to fine tune parameters in order to avoid unintended behaviors.

using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour
{
[SerializeField]
private float dist; //the distance of the current curve on a scale of 0 to 1
[SerializeField]
private Vector3[] points; // an array of Vector3 points to calculate the curve. You can adjust the formula to use your desired amount of points.
[SerializeField]
private float min; //the minimum distance at which to place a points[]
[SerializeField]
private float max; //the maximum distance at which to place a points[]
[SerializeField]
private float speed; //the speed modifier for moving the ship along the curve

void Awake()
{
CalcInitPoints();
}

Vector3 CalculateBezierPoint(float t,
Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) // returns the vector3 of the desired point along the curve. this vector3 will be the transform.position of the ship
{
float u = 1f - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;

Vector3 p = uu * p0;
p += 2 * u * t * p1;
p += tt * p2;

return p;
}

void Update ()
{
MoveBezier(); //for the purpose of demonstration, the flight is continuously calculated on Update().
}

private void CalcInitPoints() //create the initial points for the curve
{
for (int i = 0; i <= 4; i++)
{
points[i] = new Vector3(Random.Range(min, max), Random.Range(min, max), Random.Range(min, max));
}
}

private void NewPoints() //NewPoints is used only after there are points already existing
{

points[0] = points[2]; //re-use the third point
points[1] = (points[2] + (-0.5f * (points[1] - points[2]))); //the second point becomes the new tangent calculated using the third and second point
points[2] = new Vector3(Random.Range(min, max), Random.Range(min, max), Random.Range(min, max));//the third point is the new random Vector3
}

private void MoveBezier() //updates every frame to move the ship along the curve using Time.deltaTime
{
Vector3 nextPoint = CalculateBezierPoint(dist, points[0], points[1], points[2], points[3]); //injects dist (0-1 which increases by deltaTime) into the bezier formula
transform.position = nextPoint; //translate the position of the ship
if (dist <= 1f) //check every frame to see if the end of the curve has been reached
{
dist += Time.deltaTime * speed;
transform.LookAt(CalculateBezierPoint(dist, points[0], points[1], points[2], points[3])); //keeps the ship facing in the direction that it is flying
}
else
{
NewPoints(); //when the end of the curve has been reached, create a new curve and then reset the dist to zero
dist = 0;
}
}
}



The length and point on the curve is measured between 0 and 1.  The position of the ship is set equal to a specific point on the curve which is being increased by Time.deltaTime. Once the distance has reached 1, a new point is made, a new curve is calculated, and the distance along the curve is set back to 0. Now we have random flight paths using bezier curves.

Some caveats; the curves would sometimes be very acute, which resulted in a space ship that turned very quickly, which I found undesirable. A solution to this would be use a 3rd point between the previous and the next point. An extra point would create a softer curve, as long as it is placed between the first and last points a shape close to an equilateral triangle.

Special thanks and credits to Herman Tulleken for being my source: http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/ His function CalculateBezierPoint does a great job of breaking down the cubic bezier formula:

[x,y]=(1t)3P0+3(1t)2tP1+3(1t)t2P2+t3P3