How to build a Genetic Algorithm in Unity3D

Tutorial for beginners

Wael Dimassi
Jul 25, 2018 · 4 min read

With the right process in place, it will not be difficult to find state-of-the-art Genetic Algorithm for a given prediction task. Out of the three approaches — manual, machine-assisted, and algorithmic — this article will focus on ‘Gamification’ of AI since a huge number of Deep learning -specially Reinforcement learning- thesis and reaserches are oriented to games the apparition of OpenAI Five and Universe. The article will cover how I did it, get to the proof that the method works, and provide the understanding of why it works. The main principle is simplicity.

Let’s get started shall we ?

To begin properly we need to introduce some simple definitions :

  • Initial population : as its name refer to, a genetic algorithm is biomimicry of how genes and chromosomes evolve from generation to the next one. like Darwin said about the natural selection only keeps the best ,in our case, the most fitted genes. So short story long, the initial population is the set of individuals who are characterized by a set of parameters (variables) known as Genes. Genes are joined into a string to form a Chromosome (solution).
  • Fitness Function : shows how fit the individual is (the ability of an individual to compete with other individuals). It gives a fitness score calculated on his potential in that very environment. The probability that an individual will be selected for reproduction is based on its fitness score.
  • Selection : this phase consist on selectting the fittest individuals and let them pass their genes to the next generation. Two pairs of individuals (parents) are selected based on their fitness scores. Individuals with high fitness have more chance to be selected for reproduction.
  • Crossover : The main idea of the genetic algorithm. In this phase where happen the whole process of reproduction and creation of new generation based on the best fitted individuals of the previous population.
  • Mutation : If it happens in nature, it should happen in the algorithm. Thus, we need to introduce it with in low random probabilites to maintain diversity within the population and prevent premature convergence.

Sounds good but… I want an application!

Well ! we will translate all that into code to create a simple application about colors picking game : the main idea is to select colors so finally we have a popultaion with a dominant gene.

First Step : Create our initial population in a random way

for (int i = 0; i < populationSize; i++)
{
Vector3 pos = new Vector3(Random.Range(-9, 9), Random.Range(-4.5f, 4.5f), 0);
GameObject go = Instantiate(personPrefab, pos, Quaternion.identity);
go.GetComponent<DNA>().r = Random.Range(0.0f, 1.0f);
go.GetComponent<DNA>().g = Random.Range(0.0f, 1.0f);
go.GetComponent<DNA>().b = Random.Range(0.0f, 1.0f);
population.Add(go);
}

the life time of the current population will be set to 10 seconds , and at that time, we will be choosing our prefab with our chosen color.

After that amount of time we should breed the new generation from our chosen prefab of previous population.

void BreedNewPopulation()
{
List<GameObject> newPopulation = new List<GameObject>();
//get rid of unfit individuals
List<GameObject> sortedList = population.OrderByDescending(o => o.GetComponent<DNA>().timeToDie).ToList();

population.Clear();
//breed upper half of sorted list
for (int i = (int)(sortedList.Count / 2.0f) - 1; i < sortedList.Count - 1; i++)
{
population.Add(Breed(sortedList[i], sortedList[i + 1]));
population.Add(Breed(sortedList[i + 1], sortedList[i]));
}

//destroy all parents and previous population
for (int i = 0; i < sortedList.Count; i++)
{
Destroy(sortedList[i]);
}
generation++;
}

The breed function will be set as this :

GameObject Breed(GameObject parent1, GameObject parent2)
{
Vector3 pos = new Vector3(Random.Range(-9, 9), Random.Range(-4.5f, 4.5f), 0);
GameObject offspring = Instantiate(personPrefab, pos, Quaternion.identity);
DNA dna1 = parent1.GetComponent<DNA>();
DNA dna2 = parent2.GetComponent<DNA>();
//swap parent dna
if (Random.Range(0, 10) < 5)
{
offspring.GetComponent<DNA>().r = Random.Range(0, 10) < 5 ? dna1.r : dna2.r;
offspring.GetComponent<DNA>().g = Random.Range(0, 10) < 5 ? dna1.g : dna2.g;
offspring.GetComponent<DNA>().b = Random.Range(0, 10) < 5 ? dna1.b : dna2.b;
}
else
{
offspring.GetComponent<DNA>().r = Random.Range(0.0f, 1.0f);
offspring.GetComponent<DNA>().g = Random.Range(0.0f, 1.0f);
offspring.GetComponent<DNA>().b = Random.Range(0.0f, 1.0f);
}
return offspring;
}

The convergence is impressive. After 25–35 generation, we can have a homogenous population with a dominant color.

Finally !

I hope this was fun and helpful, hands-on way to learn how to build your own GA. Try it for yourself and enjoy tweeking to get better results. Or go further and try to implement a GA on another problem set; see how you would change the breed functions to handle other types of chromosomes. We’re just scratching the surface here!

To enjoy this project please visit it on heroku : here!

Please comment what do you think about this project .
Any feedback or suggestions for improvement will be really appreciated!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade