0
\$\begingroup\$

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;
}
}
\$\endgroup\$
2
  • \$\begingroup\$ Are you using physics to simulate the motion of these bodies? If so, why are you manipulating transforms directly, and doing it outside of the FixedUpdate loop with yield return null instead of WaitForFixedUpdate? Are you counting on the physics simulation to be deterministic? Unity does not make such a guarantee. \$\endgroup\$
    – DMGregory
    Dec 17, 2019 at 14:59
  • \$\begingroup\$ Ok, I canged it to yield return waitforfixedupdate, but even then, the champion still don't always do the same thing \$\endgroup\$ Dec 17, 2019 at 21:53

0

You must log in to answer this question.

Browse other questions tagged .