I've been trying to do my first evolution script. I want my population to learn to walk in 3d space. I am getting issues with the movements and the mutation. In my script, they evolve based on certain probabilities. However, if I put -1 in the mutation (which is suppose to be no mutation) they still change not based on a parent. Also, my best walker isn't supposed to change from one generation to an other, but he don't end at the same place at each generation. Is there any problem with my script ?
My walker gameobject are made of a body (child 0) and 2 rotating recatangles attached to 2 rotating rectangles attached to the body. I was trying to make it so none of the parts do a 360 degree spin on its pivot. What is wrong with my scripts ?
thats a script attached to each walker.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class bodyMan : MonoBehaviour
{
public bool fg = false;
public bool done = false;
public Transform leCu;
public Transform leJa;
public Transform riCu;
public Transform riJa;
public List<popManv2.Movements> move = new List<popManv2.Movements>();
int nbOfLoop = 3;
float[] speDir = new float[]{0.0f,0.0f,0.0f,0.0f};
public Vector3 spawnPt;
int ind = 0;
public GameObject test;
float[] flc;
float[] frc;
float[] flj;
float[] frj;
int movLoopLeng;
GameObject man;
void Start()
{
man = GameObject.Find("Manager");
movLoopLeng = man.GetComponent<popManv2>().numOfMovement;
spawnPt = transform.GetChild(0).transform.position;
}
IEnumerator Move()
{
for(int u = 0; u < nbOfLoop; u++)
{
for(int j = 0; j < movLoopLeng; j++)
{
for(int a = 0; a < speDir.Length; a++)
{
if(a==0){speDir[a] = Mathf.Round((Quaternion.Euler(move[j].rotationAndSpeed[0],0,0).x - leCu.localRotation.x)/(Mathf.Abs(Quaternion.Euler(move[j].rotationAndSpeed[0],0,0).x - leCu.localRotation.x)));}
if(a==1){speDir[a] = Mathf.Round((Quaternion.Euler(move[j].rotationAndSpeed[2],0,0).x - riCu.localRotation.x)/(Mathf.Abs(Quaternion.Euler(move[j].rotationAndSpeed[2],0,0).x - riCu.localRotation.x)));}
if(a==2){speDir[a] = Mathf.Round((Quaternion.Euler(move[j].rotationAndSpeed[4],0,0).x - leJa.localRotation.x)/(Mathf.Abs(Quaternion.Euler(move[j].rotationAndSpeed[4],0,0).x - leJa.localRotation.x)));}
if(a==3){speDir[a] = Mathf.Round((Quaternion.Euler(move[j].rotationAndSpeed[6],0,0).x - riJa.localRotation.x)/(Mathf.Abs(Quaternion.Euler(move[j].rotationAndSpeed[6],0,0).x - riJa.localRotation.x)));}
}
ind = j;
float lcn1 = flc.Min(); float lcn2 = flc.Max(); int _111 = flc.ToList().IndexOf(flc.Min()); int _112 = flc.ToList().IndexOf(flc.Max());
float rcn1 = frc.Min(); float rcn2 = frc.Max(); int _211 = frc.ToList().IndexOf(frc.Min()); int _212 = frc.ToList().IndexOf(frc.Max());
float ljn1 = flj.Min(); float ljn2 = flj.Max(); int _121 = flj.ToList().IndexOf(flj.Min()); int _122 = flj.ToList().IndexOf(flj.Max());
float rjn1 = frj.Min(); float rjn2 = frj.Max(); int _221 = frj.ToList().IndexOf(frj.Min()); int _222 = frj.ToList().IndexOf(frj.Max());
while(lcn1 <= lcn2 | rcn1 <= rcn2 | ljn1 <= ljn2 | rjn1 <= rjn2)
{
if(lcn1 <= lcn2)
{leCu.Rotate(new Vector3(1,0,0), move[j].rotationAndSpeed[1] * speDir[0] * Time.deltaTime);lcn1 = flc[_111];lcn2 = flc[_112];}
if(rcn1 <= rcn2)
{riCu.Rotate(new Vector3(1,0,0), move[j].rotationAndSpeed[3] * speDir[1] * Time.deltaTime);rcn1 = frc[_211];rcn2 = frc[_212];}
if(ljn1 <= ljn2)
{leJa.Rotate(new Vector3(1,0,0), move[j].rotationAndSpeed[5] * speDir[2] * Time.deltaTime);ljn1 = flj[_121];ljn2 = flj[_122];}
if(rjn1 <= rjn2)
{riJa.Rotate(new Vector3(1,0,0), move[j].rotationAndSpeed[7] * speDir[3] * Time.deltaTime);rjn1 = frj[_221]; rjn2 = frj[_222];}
yield return null;
}
}
}
done = true;
}
void FixedUpdate()
{
flc = new float[]{leCu.localRotation.x, Quaternion.Euler(move[ind].rotationAndSpeed[0],0,0).x};
frc = new float[]{riCu.localRotation.x, Quaternion.Euler(move[ind].rotationAndSpeed[2],0,0).x};
flj = new float[]{leJa.localRotation.x, Quaternion.Euler(move[ind].rotationAndSpeed[4],0,0).x};
frj = new float[]{riJa.localRotation.x, Quaternion.Euler(move[ind].rotationAndSpeed[6],0,0).x};
if(fg == false)
{
StartCoroutine(Move());
fg = true;
}
}
}
thats a script attached to a empty gameobject
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class popManv2 : MonoBehaviour
{
public float mutationRate;
public int spawnDist;
public int numOfWalkers;
public Material chamMat;
public List<List<Movements>> walkersMove = new List<List<Movements>>();
public List<List<Movements>> walkersMoveSto;
public int numOfMovement;
public GameObject walker;
List<Movements> champ;
int champInd;
List<float> fitness;
List<GameObject> walkers = new List<GameObject>();
float fitSum;
bool checkIfDone = true;
int championIndex;
public class Movements
{
public List<float> rotationAndSpeed;
}
void Start()
{
for(int i = 0; i < numOfWalkers; i++)
{
walkersMove.Add(new List<Movements>());
for(int u = 0; u < numOfMovement; u++)
{
walkersMove[i].Add(new Movements(){rotationAndSpeed = new
List<float>()});
}
for(int j = 0; j < numOfMovement; j++)
{
walkersMove[i]
[j].rotationAndSpeed.Add(Random.Range(-90.0f,90.0f));
walkersMove[i]
[j].rotationAndSpeed.Add(Random.Range(350.0f,500.0f));
walkersMove[i]
[j].rotationAndSpeed.Add(Random.Range(-90.0f,90.0f));
walkersMove[i]
[j].rotationAndSpeed.Add(Random.Range(350.0f,500.0f));
walkersMove[i]
[j].rotationAndSpeed.Add(Random.Range(-90.0f,20.0f));
walkersMove[i]
[j].rotationAndSpeed.Add(Random.Range(350.0f,500.0f));
walkersMove[i]
[j].rotationAndSpeed.Add(Random.Range(-90.0f,20.0f));
walkersMove[i]
[j].rotationAndSpeed.Add(Random.Range(350.0f,500.0f));
}
GameObject x = Instantiate(walker, new Vector3(0+(i*spawnDist),0,0),Quaternion.identity);
x.GetComponent<bodyMan>().move = walkersMove[i];
x.GetComponent<bodyMan>().enabled = false;
}
}
void FixedUpdate()
{
if(checkIfDone == true)
{
walkers = GameObject.FindGameObjectsWithTag("walker").ToList();
StartCoroutine(CheckIfDone());
}
if(Input.GetKeyDown("t"))
{
for(int i = 0; i < numOfWalkers; i++)
{
walkers[i].GetComponent<bodyMan>().enabled = true;
}
}
}
IEnumerator CheckIfDone()
{
bool done = false;
for(int i = 0; i < numOfWalkers; i++)
{
if(walkers[i].GetComponent<bodyMan>().done == false)
{
done = true;
}
}
if(done == false)
{
checkIfDone = false;
yield return new WaitForSeconds(0.3f);
walkersMoveSto = new List<List<Movements>>();
fitness = new List<float>();
CalculateFitness();
FindChampion();
ChoseParent();
Mutation();
StartNewGen();
}
}
void CalculateFitness()
{
fitSum = 0;
for(int i = 0; i < numOfWalkers; i++)
{
fitness.Add(Mathf.Pow((1/Mathf.Abs(walkers[i].transform.GetChild(0).transform.position.z+100))+1,100));
fitSum += fitness[i];
}
}
void FindChampion()
{
champ = walkersMove[fitness.IndexOf(fitness.Max())];
champInd = walkers.IndexOf(walkers[fitness.IndexOf(fitness.Max())]);
}
void ChoseParent()
{
for(int i = 0; i < numOfWalkers; i++)
{
float ranFit = Random.Range(0.0f, fitSum);
float fitRanSelect = 0.0f;
for(int j = 0; j < numOfWalkers; j++)
{
fitRanSelect += fitness[j];
if(i != champInd){
if(fitRanSelect >= ranFit)
{
walkersMoveSto.Add(walkersMove[j]);
break;
}}
if(i == champInd)
{
walkersMoveSto.Add(walkersMove[i]);
break;
}
}
}
}
void Mutation()
{
for(int i = 0; i < numOfWalkers; i++)
{
if(i != champInd)
{
for(int j = 0; j < numOfMovement; j++)
{
for(int k = 0; k < 7; k++)
{
float randMutate = Random.Range(0.0f, 100.0f);
if(randMutate < mutationRate)
{
Debug.Log("mutate");
if((k==0)|(k==2))
{
walkersMoveSto[i][j].rotationAndSpeed[k] = Random.Range(-90.0f,90.0f);
}
if((k==4)|(k==6))
{
walkersMoveSto[i][j].rotationAndSpeed[k] = Random.Range(-90.0f,20.0f);
}
if((k==1)|(k==3)|(k==5)|(k==7))
{
walkersMoveSto[i][j].rotationAndSpeed[k] = Random.Range(350.0f,500.0f);
}
}
}
}
}
}
}
void StartNewGen()
{
for(int i = 0; i < numOfWalkers; i++)
{
Destroy(walkers[i]);
}
walkersMove = walkersMoveSto;
for(int i = 0; i < numOfWalkers; i++)
{
GameObject x = Instantiate(walker, new Vector3(0+(i*spawnDist),0,0),Quaternion.identity);
x.GetComponent<bodyMan>().move = walkersMove[i];
if(i == champInd)
{
x.GetComponentInChildren<MeshRenderer>().material = chamMat;
}
}
checkIfDone = true;
}
}