private void InitializeAgentBrainAndBody(Agent newAgent, CritterGenome bodyGenome)        /// Configure newly-created Agent (brain + body) for the FIRST TIME!! to change settings on an existing agent, use a different method.
    {
        DebugBot.DebugFunctionCall("Population; InitializeAgentInstance(); ", debugFunctionCalls);
        // Figure out Agent Body HERE:
        newAgent.bodyGenome = bodyGenome;         // set as this agent's body Genome

        // BRAIN BELOW:
        // Initialize Brain:
        newAgent.brain = new BrainNEAT();

        GenomeNEAT brainGenome;

        Debug.Log("InitializeAgentBrainAndBody numInputNodes: " + numInputNodes.ToString() + ", NumHiddenNodes: " + initNumHiddenNodes.ToString() + ", numOutputNodes: " + numOutputNodes.ToString() + ", initConnectedness: " + initConnectedness.ToString() + ", initRandom: " + initRandom.ToString());
        // OLD // brainGenome = newAgent.brain.InitializeNewBrain(numInputNodes, initNumHiddenNodes, numOutputNodes, initConnectedness, initRandom);
        brainGenome = newAgent.brain.InitializeNewBrain(bodyGenome, initNumHiddenNodes, initConnectedness, initRandom);

        /*if(initRandom) {  // OLD
         *  brainGenome = newAgent.brain.InitializeRandomBrain(numInputNodes, numOutputNodes); // 'builds' the brain and spits out a Genome
         *      }
         *      else {
         *  brainGenome = newAgent.brain.InitializeBlankBrain(numInputNodes, numOutputNodes);
         *      }*/

        newAgent.brainGenome = brainGenome;
        newAgent.brain.BuildBrainNetwork();          // constructs the brain from its sourceGenome
        //AssignAgentToSpecies(newAgent);
        isFunctional = true;
    }
    public void InitializeMasterAgentArray(CritterGenome bodyGenome, bool useSpeciation)        // Creates a new population for the FIRST TIME!!!
    {
        DebugBot.DebugFunctionCall("Population; InitializeMasterAgentArray(CritterGenome); ", debugFunctionCalls);
        templateGenome = bodyGenome;

        // $$$$$$$$$$$$ TRY TO REMOVE THIS SOON!!!!!!!!!!!!!!!!  $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
        int[] critterData = templateGenome.CalculateNumberOfSegmentsInputsOutputs(); // just to check number of segments, inputs, and outputs
        int   numSegments = critterData[0];

        numInputNodes  = critterData[1];
        numOutputNodes = critterData[2];
        Debug.Log("Critter Stats [0]: " + numSegments.ToString() + ", [1]: " + numInputNodes.ToString() + ", [2]: " + numOutputNodes.ToString());
        // $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

        masterAgentArray = new Agent[populationMaxSize];
        for (int i = 0; i < populationMaxSize; i++)
        {
            Agent newAgent = new Agent();
            //newAgent.fitnessRank =
            InitializeAgentBrainAndBody(newAgent, bodyGenome);              // create Agent's brain as proper type, and copies over templateBrain's settings
            masterAgentArray[i] = newAgent;
            numAgents++;
        }

        InitializeSpeciesPoolsAndAgents(useSpeciation); // assigns agents to a species and populates the breeding pools
    }
    public override object Read(ES2Reader reader)
    {
        CritterGenome data = new CritterGenome();

        Read(reader, data);
        return(data);
    }
 public void InitializeCritterFromGenome(CritterGenome genome) {
     masterCritterGenome = genome;
     if (critterSegmentList == null) {
         critterSegmentList = new List<GameObject>(); // the 'official' record of this critters Segments
     }
     InitializeAddonLists();
     Debug.Log("InitializeCritterFromGenome(CritterGenome genome)  created SEGADDON LISTS!!!");
     
 }
示例#5
0
    public GenomeNEAT InitializeNewBrain(CritterGenome critterBodyGenome, int numHiddenNodes, float connectedness, bool randomWeights)
    {
        // OLD //sourceGenome = new GenomeNEAT(numInputNodes, numHiddenNodes, numOutputNodes); // create blank genome with no connections
        sourceGenome = new GenomeNEAT(critterBodyGenome, numHiddenNodes); // create blank genome with no connections
        sourceGenome.CreateInitialConnections(connectedness, randomWeights);

        //Debug.Log("InitializeBlankBrain #nodes: " + sourceGenome.nodeNEATList.Count.ToString() + ", #links: " + sourceGenome.linkNEATList.Count.ToString());

        return(sourceGenome);
    }
示例#6
0
    public GenomeNEAT(CritterGenome critterBodyGenome, int numHidden)
    {
        // Constructor
        nodeNEATList = critterBodyGenome.GetBlankBrainNodesFromBody();  // returns a list of nodeNEAT's based on bodyGenome

        int currentID = nodeNEATList.Count;

        // Add in hidden nodes:
        for (int h = 0; h < numHidden; h++)
        {
            Debug.Log("NO HIDDEN NODES CREATED!!! -- need a way to keep track of innovation#'s, have no access to crossoverManager");
            //GeneNodeNEAT newHiddenNode = new GeneNodeNEAT(currentID, GeneNodeNEAT.GeneNodeType.Hid, TransferFunctions.TransferFunction.RationalSigmoid, -1, 0, -1);
            //nodeNEATList.Add(newHiddenNode);
            //currentID++;
        }
        // do I need to save body-part&add-on information on the Brain NODES? or only on Neurons?
        linkNEATList = new List <GeneLinkNEAT>();

        string newGenomeNEATDisplay = "NEW GenomeNEAT! #nodes: " + nodeNEATList.Count.ToString() + "\n";

        for (int i = 0; i < nodeNEATList.Count; i++)
        {
            newGenomeNEATDisplay += "Node[" + i.ToString() + "] (" + nodeNEATList[i].id.ToString() + ", " + nodeNEATList[i].sourceAddonInno.ToString() + ", " + nodeNEATList[i].sourceAddonRecursionNum.ToString() + ", " + nodeNEATList[i].sourceAddonChannelNum.ToString() + ")\n";
        }
        Debug.Log(newGenomeNEATDisplay);

        /*if (numInputs < 1 || numOutputs < 1) {
         *  Debug.LogError("New NEAT Genome requires at least 1 input and output node!! [" + numInputs.ToString() + "," + numOutputs.ToString() + "]");
         * }
         * else {
         *  nodeNEATList = new List<GeneNodeNEAT>();
         *  int currentID = 0;
         *  for (int i = 0; i < numInputs; i++) {
         *      GeneNodeNEAT newInputNode = new GeneNodeNEAT(currentID, GeneNodeNEAT.GeneNodeType.In, TransferFunctions.TransferFunction.Linear);
         *      nodeNEATList.Add(newInputNode);
         *      currentID++;
         *  }
         *  for (int h = 0; h < numHidden; h++) {
         *      GeneNodeNEAT newHiddenNode = new GeneNodeNEAT(currentID, GeneNodeNEAT.GeneNodeType.Hid, TransferFunctions.TransferFunction.RationalSigmoid);
         *      nodeNEATList.Add(newHiddenNode);
         *      currentID++;
         *  }
         *  for (int o = 0; o < numOutputs; o++) {
         *      GeneNodeNEAT newOutputNode = new GeneNodeNEAT(currentID, GeneNodeNEAT.GeneNodeType.Out, TransferFunctions.TransferFunction.RationalSigmoid);
         *      nodeNEATList.Add(newOutputNode);
         *      currentID++;
         *  }
         *
         *  linkNEATList = new List<GeneLinkNEAT>();
         *  // Empty for now
         * }*/
    }
    public GenomeNEAT(CritterGenome critterBodyGenome, int numHidden) {
        // Constructor
        nodeNEATList = critterBodyGenome.GetBlankBrainNodesFromBody();  // returns a list of nodeNEAT's based on bodyGenome
        
        int currentID = nodeNEATList.Count;
        // Add in hidden nodes:        
        for (int h = 0; h < numHidden; h++) {
            Debug.Log("NO HIDDEN NODES CREATED!!! -- need a way to keep track of innovation#'s, have no access to crossoverManager");
            //GeneNodeNEAT newHiddenNode = new GeneNodeNEAT(currentID, GeneNodeNEAT.GeneNodeType.Hid, TransferFunctions.TransferFunction.RationalSigmoid, -1, 0, -1);
            //nodeNEATList.Add(newHiddenNode);
            //currentID++;
        }
        // do I need to save body-part&add-on information on the Brain NODES? or only on Neurons?
        linkNEATList = new List<GeneLinkNEAT>();

        string newGenomeNEATDisplay = "NEW GenomeNEAT! #nodes: " + nodeNEATList.Count.ToString() + "\n";
        for(int i = 0; i < nodeNEATList.Count; i++) {
            newGenomeNEATDisplay += "Node[" + i.ToString() + "] (" + nodeNEATList[i].id.ToString() + ", " + nodeNEATList[i].sourceAddonInno.ToString() + ", " + nodeNEATList[i].sourceAddonRecursionNum.ToString() + ", " + nodeNEATList[i].sourceAddonChannelNum.ToString() + ")\n";
        }
        Debug.Log(newGenomeNEATDisplay);

        /*if (numInputs < 1 || numOutputs < 1) {
            Debug.LogError("New NEAT Genome requires at least 1 input and output node!! [" + numInputs.ToString() + "," + numOutputs.ToString() + "]");
        }
        else {
            nodeNEATList = new List<GeneNodeNEAT>();
            int currentID = 0;
            for (int i = 0; i < numInputs; i++) {
                GeneNodeNEAT newInputNode = new GeneNodeNEAT(currentID, GeneNodeNEAT.GeneNodeType.In, TransferFunctions.TransferFunction.Linear);
                nodeNEATList.Add(newInputNode);
                currentID++;
            }
            for (int h = 0; h < numHidden; h++) {
                GeneNodeNEAT newHiddenNode = new GeneNodeNEAT(currentID, GeneNodeNEAT.GeneNodeType.Hid, TransferFunctions.TransferFunction.RationalSigmoid);
                nodeNEATList.Add(newHiddenNode);
                currentID++;
            }
            for (int o = 0; o < numOutputs; o++) {
                GeneNodeNEAT newOutputNode = new GeneNodeNEAT(currentID, GeneNodeNEAT.GeneNodeType.Out, TransferFunctions.TransferFunction.RationalSigmoid);
                nodeNEATList.Add(newOutputNode);
                currentID++;
            }

            linkNEATList = new List<GeneLinkNEAT>();
            // Empty for now
        }*/
    }
    public override void Read(ES2Reader reader, object c)
    {
        CritterGenome data = (CritterGenome)c;
        // Add your reader.Read calls here to read the data into the object.
        // Read the version number.
        int fileVersion = reader.Read <int>();

        // VERSION 0:
        if (fileVersion >= 0)
        {
            data.CritterNodeList    = reader.ReadList <CritterNode>();
            data.savedNextNodeInno  = reader.Read <int>();
            data.savedNextAddonInno = reader.Read <int>();

            data.addonPhysicalAttributesList = reader.ReadList <AddonPhysicalAttributes>();

            data.addonJointAngleSensorList = reader.ReadList <AddonJointAngleSensor>();
            data.addonContactSensorList    = reader.ReadList <AddonContactSensor>();
            data.addonRaycastSensorList    = reader.ReadList <AddonRaycastSensor>();
            data.addonCompassSensor1DList  = reader.ReadList <AddonCompassSensor1D>();
            data.addonCompassSensor3DList  = reader.ReadList <AddonCompassSensor3D>();
            data.addonPositionSensor1DList = reader.ReadList <AddonPositionSensor1D>();
            data.addonPositionSensor3DList = reader.ReadList <AddonPositionSensor3D>();
            data.addonRotationSensor1DList = reader.ReadList <AddonRotationSensor1D>();
            data.addonRotationSensor3DList = reader.ReadList <AddonRotationSensor3D>();
            data.addonVelocitySensor1DList = reader.ReadList <AddonVelocitySensor1D>();
            data.addonVelocitySensor3DList = reader.ReadList <AddonVelocitySensor3D>();
            data.addonAltimeterList        = reader.ReadList <AddonAltimeter>();
            data.addonEarBasicList         = reader.ReadList <AddonEarBasic>();
            data.addonGravitySensorList    = reader.ReadList <AddonGravitySensor>();
            data.addonOscillatorInputList  = reader.ReadList <AddonOscillatorInput>();
            data.addonValueInputList       = reader.ReadList <AddonValueInput>();
            data.addonTimerInputList       = reader.ReadList <AddonTimerInput>();

            data.addonJointMotorList         = reader.ReadList <AddonJointMotor>();
            data.addonThrusterEffector1DList = reader.ReadList <AddonThrusterEffector1D>();
            data.addonThrusterEffector3DList = reader.ReadList <AddonThrusterEffector3D>();
            data.addonTorqueEffector1DList   = reader.ReadList <AddonTorqueEffector1D>();
            data.addonTorqueEffector3DList   = reader.ReadList <AddonTorqueEffector3D>();
            data.addonMouthBasicList         = reader.ReadList <AddonMouthBasic>();
            data.addonNoiseMakerBasicList    = reader.ReadList <AddonNoiseMakerBasic>();
            data.addonStickyList             = reader.ReadList <AddonSticky>();
            data.addonWeaponBasicList        = reader.ReadList <AddonWeaponBasic>();
        }
    }
    public override void Write(object obj, ES2Writer writer)
    {
        CritterGenome data = (CritterGenome)obj;

        // Add your writer.Write calls here.
        writer.Write(0); // Version 0 is current version number
        // Make sure to edit Read() function to properly handle version control!
        // VERSION 0:
        writer.Write(data.CritterNodeList);
        writer.Write(data.savedNextNodeInno);
        writer.Write(data.savedNextAddonInno);

        writer.Write(data.addonPhysicalAttributesList);

        writer.Write(data.addonJointAngleSensorList);
        writer.Write(data.addonContactSensorList);
        writer.Write(data.addonRaycastSensorList);
        writer.Write(data.addonCompassSensor1DList);
        writer.Write(data.addonCompassSensor3DList);
        writer.Write(data.addonPositionSensor1DList);
        writer.Write(data.addonPositionSensor3DList);
        writer.Write(data.addonRotationSensor1DList);
        writer.Write(data.addonRotationSensor3DList);
        writer.Write(data.addonVelocitySensor1DList);
        writer.Write(data.addonVelocitySensor3DList);
        writer.Write(data.addonAltimeterList);
        writer.Write(data.addonEarBasicList);
        writer.Write(data.addonGravitySensorList);
        writer.Write(data.addonOscillatorInputList);
        writer.Write(data.addonValueInputList);
        writer.Write(data.addonTimerInputList);

        writer.Write(data.addonJointMotorList);
        writer.Write(data.addonThrusterEffector1DList);
        writer.Write(data.addonThrusterEffector3DList);
        writer.Write(data.addonTorqueEffector1DList);
        writer.Write(data.addonTorqueEffector3DList);
        writer.Write(data.addonMouthBasicList);
        writer.Write(data.addonNoiseMakerBasicList);
        writer.Write(data.addonStickyList);
        writer.Write(data.addonWeaponBasicList);
    }
    public void ClickCreateNewPopulation()
    {
        DebugBot.DebugFunctionCall("TNewPopUI; ClickCreateNewPopulation(); ", debugFunctionCalls);

        Trainer trainer = trainerModuleScript.gameController.masterTrainer; //  ?? why only set up reference here???

        if (trainer.PlayerList != null)                                     // if there is a valid PlayerList
        {
            int curPlayer = trainer.CurPlayer;
            if (trainer.PlayerList[curPlayer - 1] != null)             // If Current Player exists

            {
                populationRef = trainer.PlayerList[curPlayer - 1].masterPopulation;               // grab current player's population -- this might not be needed
                populationRef.SetMaxPopulationSize(pendingPopulationSize);
                if (toggleZeroedWeights.isOn)
                {
                    populationRef.initRandom = false;
                }
                else
                {
                    populationRef.initRandom = true;
                }
                populationRef.initNumHiddenNodes = pendingNumHiddenNodes;
                populationRef.initConnectedness  = pendingConnectedness;

                // CREATE AGENT ARRAY!!!!!!! :
                CritterGenome genomeToLoad = ES2.Load <CritterGenome>(pendingBodyTemplateFilename);
                CrossoverManager.nextNodeInnov  = genomeToLoad.savedNextNodeInno;
                CrossoverManager.nextAddonInnov = genomeToLoad.savedNextAddonInno;

                populationRef.InitializeMasterAgentArray(genomeToLoad, trainer.PlayerList[curPlayer - 1].masterCupid.useSpeciation);
                trainer.PlayerList[curPlayer - 1].hasValidPopulation = true;
            }
            else
            {
                DebugBot.DebugFunctionCall("TNewPopUI; ClickCreateNewPopulation(); Null Player Ref!", debugFunctionCalls);
            }
        }
        trainerModuleScript.ClickPopulation();         // switches to Population Panel -- might not be necessary?
        trainer.PlayerList[trainer.CurPlayer - 1].graphKing.BuildTexturesCurAgentPerAgent(trainer.PlayerList[trainer.CurPlayer - 1], 0);
        trainerModuleScript.SetAllPanelsFromTrainerData();
    }
	public void InitializeMasterAgentArray(CritterGenome bodyGenome, bool useSpeciation) {  // Creates a new population for the FIRST TIME!!!
		DebugBot.DebugFunctionCall("Population; InitializeMasterAgentArray(CritterGenome); ", debugFunctionCalls);
		templateGenome = bodyGenome;        

        // $$$$$$$$$$$$ TRY TO REMOVE THIS SOON!!!!!!!!!!!!!!!!  $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
        int[] critterData = templateGenome.CalculateNumberOfSegmentsInputsOutputs(); // just to check number of segments, inputs, and outputs
        int numSegments = critterData[0];
        numInputNodes = critterData[1];
        numOutputNodes = critterData[2];
        Debug.Log("Critter Stats [0]: " + numSegments.ToString() + ", [1]: " + numInputNodes.ToString() + ", [2]: " + numOutputNodes.ToString());
        // $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
                
        masterAgentArray = new Agent[populationMaxSize];
		for(int i = 0; i < populationMaxSize; i++) {
			Agent newAgent = new Agent();
            //newAgent.fitnessRank =
			InitializeAgentBrainAndBody(newAgent, bodyGenome);  // create Agent's brain as proper type, and copies over templateBrain's settings
			masterAgentArray[i] = newAgent;
			numAgents++;
		}

        InitializeSpeciesPoolsAndAgents(useSpeciation); // assigns agents to a species and populates the breeding pools    
    }
	private void InitializeAgentBrainAndBody(Agent newAgent, CritterGenome bodyGenome) {  /// Configure newly-created Agent (brain + body) for the FIRST TIME!! to change settings on an existing agent, use a different method.
		DebugBot.DebugFunctionCall("Population; InitializeAgentInstance(); ", debugFunctionCalls);
		// Figure out Agent Body HERE:		
		newAgent.bodyGenome = bodyGenome; // set as this agent's body Genome
        
        // BRAIN BELOW:
        // Initialize Brain:
		newAgent.brain = new BrainNEAT();        
		
        GenomeNEAT brainGenome;
        Debug.Log("InitializeAgentBrainAndBody numInputNodes: " + numInputNodes.ToString() + ", NumHiddenNodes: " + initNumHiddenNodes.ToString() + ", numOutputNodes: " + numOutputNodes.ToString() + ", initConnectedness: " + initConnectedness.ToString() + ", initRandom: " + initRandom.ToString());
        // OLD // brainGenome = newAgent.brain.InitializeNewBrain(numInputNodes, initNumHiddenNodes, numOutputNodes, initConnectedness, initRandom);
        brainGenome = newAgent.brain.InitializeNewBrain(bodyGenome, initNumHiddenNodes, initConnectedness, initRandom);
        /*if(initRandom) {  // OLD
            brainGenome = newAgent.brain.InitializeRandomBrain(numInputNodes, numOutputNodes); // 'builds' the brain and spits out a Genome
		}
		else {
            brainGenome = newAgent.brain.InitializeBlankBrain(numInputNodes, numOutputNodes);
		}*/

        newAgent.brainGenome = brainGenome;
		newAgent.brain.BuildBrainNetwork();  // constructs the brain from its sourceGenome
        //AssignAgentToSpecies(newAgent);
        isFunctional = true;        
	}
    public void BreedCritterAddons(ref CritterGenome childBodyGenome, ref CritterGenome sourceBodyGenomeMoreFit, ref CritterGenome sourceBodyGenomeLessFit) {

        // Iterate over the Addons of the more fit parent:
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonPhysicalAttributesList.Count; i++) {
            AddonPhysicalAttributes clonedAddon = sourceBodyGenomeMoreFit.addonPhysicalAttributesList[i].CloneThisAddon();
            childBodyGenome.addonPhysicalAttributesList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonPhysicalAttributesList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonPhysicalAttributesList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.bounciness[0] = sourceBodyGenomeLessFit.addonPhysicalAttributesList[a].bounciness[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.dynamicFriction[0] = sourceBodyGenomeLessFit.addonPhysicalAttributesList[a].dynamicFriction[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.staticFriction[0] = sourceBodyGenomeLessFit.addonPhysicalAttributesList[a].staticFriction[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.freezePositionX[0] = sourceBodyGenomeLessFit.addonPhysicalAttributesList[a].freezePositionX[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.freezePositionY[0] = sourceBodyGenomeLessFit.addonPhysicalAttributesList[a].freezePositionY[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.freezePositionZ[0] = sourceBodyGenomeLessFit.addonPhysicalAttributesList[a].freezePositionZ[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.freezeRotationX[0] = sourceBodyGenomeLessFit.addonPhysicalAttributesList[a].freezeRotationX[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.freezeRotationY[0] = sourceBodyGenomeLessFit.addonPhysicalAttributesList[a].freezeRotationY[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.freezeRotationZ[0] = sourceBodyGenomeLessFit.addonPhysicalAttributesList[a].freezeRotationZ[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonJointAngleSensorList.Count; i++) {
            AddonJointAngleSensor clonedAddon = sourceBodyGenomeMoreFit.addonJointAngleSensorList[i].CloneThisAddon();
            childBodyGenome.addonJointAngleSensorList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonJointAngleSensorList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonJointAngleSensorList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.sensitivity[0] = sourceBodyGenomeLessFit.addonJointAngleSensorList[a].sensitivity[0];
                        }
                        // #################  How to handle MEasureVel Checkbox?? It adds a Neuron!!!!!!!!!
                        // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonContactSensorList.Count; i++) {
            AddonContactSensor clonedAddon = sourceBodyGenomeMoreFit.addonContactSensorList[i].CloneThisAddon();
            childBodyGenome.addonContactSensorList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonContactSensorList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonContactSensorList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.contactSensitivity[0] = sourceBodyGenomeLessFit.addonContactSensorList[a].contactSensitivity[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonRaycastSensorList.Count; i++) {
            AddonRaycastSensor clonedAddon = sourceBodyGenomeMoreFit.addonRaycastSensorList[i].CloneThisAddon();
            childBodyGenome.addonRaycastSensorList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonRaycastSensorList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonRaycastSensorList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.forwardVector[0] = sourceBodyGenomeLessFit.addonRaycastSensorList[a].forwardVector[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.maxDistance[0] = sourceBodyGenomeLessFit.addonRaycastSensorList[a].maxDistance[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonCompassSensor1DList.Count; i++) {
            AddonCompassSensor1D clonedAddon = sourceBodyGenomeMoreFit.addonCompassSensor1DList[i].CloneThisAddon();
            childBodyGenome.addonCompassSensor1DList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonCompassSensor1DList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonCompassSensor1DList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.forwardVector[0] = sourceBodyGenomeLessFit.addonCompassSensor1DList[a].forwardVector[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonCompassSensor3DList.Count; i++) {
            AddonCompassSensor3D clonedAddon = sourceBodyGenomeMoreFit.addonCompassSensor3DList[i].CloneThisAddon();
            childBodyGenome.addonCompassSensor3DList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonCompassSensor3DList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonCompassSensor3DList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonPositionSensor1DList.Count; i++) {
            AddonPositionSensor1D clonedAddon = sourceBodyGenomeMoreFit.addonPositionSensor1DList[i].CloneThisAddon();
            childBodyGenome.addonPositionSensor1DList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonPositionSensor1DList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonPositionSensor1DList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.forwardVector[0] = sourceBodyGenomeLessFit.addonPositionSensor1DList[a].forwardVector[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.relative[0] = sourceBodyGenomeLessFit.addonPositionSensor1DList[a].relative[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.sensitivity[0] = sourceBodyGenomeLessFit.addonPositionSensor1DList[a].sensitivity[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonPositionSensor3DList.Count; i++) {
            AddonPositionSensor3D clonedAddon = sourceBodyGenomeMoreFit.addonPositionSensor3DList[i].CloneThisAddon();
            childBodyGenome.addonPositionSensor3DList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonPositionSensor3DList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonPositionSensor3DList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.sensitivity[0] = sourceBodyGenomeLessFit.addonPositionSensor3DList[a].sensitivity[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.relative[0] = sourceBodyGenomeLessFit.addonPositionSensor3DList[a].relative[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonRotationSensor1DList.Count; i++) {
            AddonRotationSensor1D clonedAddon = sourceBodyGenomeMoreFit.addonRotationSensor1DList[i].CloneThisAddon();
            childBodyGenome.addonRotationSensor1DList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonRotationSensor1DList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonRotationSensor1DList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.localAxis[0] = sourceBodyGenomeLessFit.addonRotationSensor1DList[a].localAxis[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.sensitivity[0] = sourceBodyGenomeLessFit.addonRotationSensor1DList[a].sensitivity[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonRotationSensor3DList.Count; i++) {
            AddonRotationSensor3D clonedAddon = sourceBodyGenomeMoreFit.addonRotationSensor3DList[i].CloneThisAddon();
            childBodyGenome.addonRotationSensor3DList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonRotationSensor3DList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonRotationSensor3DList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.sensitivity[0] = sourceBodyGenomeLessFit.addonRotationSensor3DList[a].sensitivity[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonVelocitySensor1DList.Count; i++) {
            AddonVelocitySensor1D clonedAddon = sourceBodyGenomeMoreFit.addonVelocitySensor1DList[i].CloneThisAddon();
            childBodyGenome.addonVelocitySensor1DList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonVelocitySensor1DList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonVelocitySensor1DList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.sensitivity[0] = sourceBodyGenomeLessFit.addonVelocitySensor1DList[a].sensitivity[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.forwardVector[0] = sourceBodyGenomeLessFit.addonVelocitySensor1DList[a].forwardVector[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.relative[0] = sourceBodyGenomeLessFit.addonVelocitySensor1DList[a].relative[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonVelocitySensor3DList.Count; i++) {
            AddonVelocitySensor3D clonedAddon = sourceBodyGenomeMoreFit.addonVelocitySensor3DList[i].CloneThisAddon();
            childBodyGenome.addonVelocitySensor3DList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonVelocitySensor3DList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonVelocitySensor3DList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.sensitivity[0] = sourceBodyGenomeLessFit.addonVelocitySensor3DList[a].sensitivity[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.relative[0] = sourceBodyGenomeLessFit.addonVelocitySensor3DList[a].relative[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonAltimeterList.Count; i++) {
            AddonAltimeter clonedAddon = sourceBodyGenomeMoreFit.addonAltimeterList[i].CloneThisAddon();
            childBodyGenome.addonAltimeterList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonAltimeterList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonAltimeterList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!                        
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonEarBasicList.Count; i++) {
            AddonEarBasic clonedAddon = sourceBodyGenomeMoreFit.addonEarBasicList[i].CloneThisAddon();
            childBodyGenome.addonEarBasicList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonEarBasicList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonEarBasicList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.sensitivity[0] = sourceBodyGenomeLessFit.addonEarBasicList[a].sensitivity[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonGravitySensorList.Count; i++) {
            AddonGravitySensor clonedAddon = sourceBodyGenomeMoreFit.addonGravitySensorList[i].CloneThisAddon();
            childBodyGenome.addonGravitySensorList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonGravitySensorList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonGravitySensorList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonOscillatorInputList.Count; i++) {
            AddonOscillatorInput clonedAddon = sourceBodyGenomeMoreFit.addonOscillatorInputList[i].CloneThisAddon();
            childBodyGenome.addonOscillatorInputList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonOscillatorInputList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonOscillatorInputList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.amplitude[0] = sourceBodyGenomeLessFit.addonOscillatorInputList[a].amplitude[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.frequency[0] = sourceBodyGenomeLessFit.addonOscillatorInputList[a].frequency[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.offset[0] = sourceBodyGenomeLessFit.addonOscillatorInputList[a].offset[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonValueInputList.Count; i++) {
            AddonValueInput clonedAddon = sourceBodyGenomeMoreFit.addonValueInputList[i].CloneThisAddon();
            childBodyGenome.addonValueInputList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonValueInputList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonValueInputList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.value[0] = sourceBodyGenomeLessFit.addonValueInputList[a].value[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonTimerInputList.Count; i++) {
            AddonTimerInput clonedAddon = sourceBodyGenomeMoreFit.addonTimerInputList[i].CloneThisAddon();
            childBodyGenome.addonTimerInputList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonTimerInputList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonTimerInputList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                    }
                }
            }
        }

        for (int i = 0; i < sourceBodyGenomeMoreFit.addonJointMotorList.Count; i++) {
            AddonJointMotor clonedAddon = sourceBodyGenomeMoreFit.addonJointMotorList[i].CloneThisAddon();
            childBodyGenome.addonJointMotorList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonJointMotorList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonJointMotorList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.motorForce[0] = sourceBodyGenomeLessFit.addonJointMotorList[a].motorForce[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.motorSpeed[0] = sourceBodyGenomeLessFit.addonJointMotorList[a].motorSpeed[0];
                        }
                    }
                }
            }
        }        
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonThrusterEffector1DList.Count; i++) {
            AddonThrusterEffector1D clonedAddon = sourceBodyGenomeMoreFit.addonThrusterEffector1DList[i].CloneThisAddon();
            childBodyGenome.addonThrusterEffector1DList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonThrusterEffector1DList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonThrusterEffector1DList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.forwardVector[0] = sourceBodyGenomeLessFit.addonThrusterEffector1DList[a].forwardVector[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.maxForce[0] = sourceBodyGenomeLessFit.addonThrusterEffector1DList[a].maxForce[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonThrusterEffector3DList.Count; i++) {
            AddonThrusterEffector3D clonedAddon = sourceBodyGenomeMoreFit.addonThrusterEffector3DList[i].CloneThisAddon();
            childBodyGenome.addonThrusterEffector3DList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonThrusterEffector3DList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonThrusterEffector3DList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.maxForce[0] = sourceBodyGenomeLessFit.addonThrusterEffector3DList[a].maxForce[0];
                        }
                    }
                }
            }
        }        
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonTorqueEffector1DList.Count; i++) {
            AddonTorqueEffector1D clonedAddon = sourceBodyGenomeMoreFit.addonTorqueEffector1DList[i].CloneThisAddon();
            childBodyGenome.addonTorqueEffector1DList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonTorqueEffector1DList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonTorqueEffector1DList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.maxTorque[0] = sourceBodyGenomeLessFit.addonTorqueEffector1DList[a].maxTorque[0];
                        }
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.axis[0] = sourceBodyGenomeLessFit.addonTorqueEffector1DList[a].axis[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonTorqueEffector3DList.Count; i++) {
            AddonTorqueEffector3D clonedAddon = sourceBodyGenomeMoreFit.addonTorqueEffector3DList[i].CloneThisAddon();
            childBodyGenome.addonTorqueEffector3DList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonTorqueEffector3DList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonTorqueEffector3DList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.maxTorque[0] = sourceBodyGenomeLessFit.addonTorqueEffector3DList[a].maxTorque[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonMouthBasicList.Count; i++) {
            AddonMouthBasic clonedAddon = sourceBodyGenomeMoreFit.addonMouthBasicList[i].CloneThisAddon();
            childBodyGenome.addonMouthBasicList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonMouthBasicList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonMouthBasicList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonNoiseMakerBasicList.Count; i++) {
            AddonNoiseMakerBasic clonedAddon = sourceBodyGenomeMoreFit.addonNoiseMakerBasicList[i].CloneThisAddon();
            childBodyGenome.addonNoiseMakerBasicList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonNoiseMakerBasicList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonNoiseMakerBasicList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.amplitude[0] = sourceBodyGenomeLessFit.addonNoiseMakerBasicList[a].amplitude[0];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonStickyList.Count; i++) {
            AddonSticky clonedAddon = sourceBodyGenomeMoreFit.addonStickyList[i].CloneThisAddon();
            childBodyGenome.addonStickyList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonStickyList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonStickyList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                    }
                }
            }
        }
        for (int i = 0; i < sourceBodyGenomeMoreFit.addonWeaponBasicList.Count; i++) {
            AddonWeaponBasic clonedAddon = sourceBodyGenomeMoreFit.addonWeaponBasicList[i].CloneThisAddon();
            childBodyGenome.addonWeaponBasicList.Add(clonedAddon);

            if (useCrossover) {
                int sourceInno = clonedAddon.innov;
                for (int a = 0; a < sourceBodyGenomeLessFit.addonWeaponBasicList.Count; a++) {
                    if (sourceBodyGenomeLessFit.addonWeaponBasicList[a].innov == sourceInno) {  // if the LESS-fit parent also has this Add-On:
                        // MIX SETTINGS HERE!!!
                        if (CheckForMutation(0.5f)) {
                            clonedAddon.strength[0] = sourceBodyGenomeLessFit.addonWeaponBasicList[a].strength[0];
                        }
                    }
                }
            }
        }
    }
    public void PerformBodyMutation(ref CritterGenome bodyGenome, ref GenomeNEAT brainGenome) {
        int numBodyMutations = 0;
        //float attachDirMutationMultiplier = 0.1f;
        //float restAngleDirMutationMultiplier = 0.1f;
        float jointAngleTypeMultiplier = 0.5f;
        List<int> nodesToDelete = new List<int>();        
        for (int i = 0; i < bodyGenome.CritterNodeList.Count; i++) {
            
            // Segment Proportions:
            if(CheckForMutation(segmentProportionChance * bodyMutationBlastModifier)) {  // X
                bodyGenome.CritterNodeList[i].dimensions.x = MutateBodyFloatMult(bodyGenome.CritterNodeList[i].dimensions.x);
                numBodyMutations++;
            }
            if (CheckForMutation(segmentProportionChance * bodyMutationBlastModifier)) {  // Y
                bodyGenome.CritterNodeList[i].dimensions.y = MutateBodyFloatMult(bodyGenome.CritterNodeList[i].dimensions.y);
                numBodyMutations++;
            }
            if (CheckForMutation(segmentProportionChance * bodyMutationBlastModifier)) {  // Z
                bodyGenome.CritterNodeList[i].dimensions.z = MutateBodyFloatMult(bodyGenome.CritterNodeList[i].dimensions.z);
                numBodyMutations++;
            }
            if(i > 0) {   // NOT THE ROOT SEGMENT!:
                // REMOVE SEGMENT!!!!
                if(CheckForMutation(removeSegmentChance * bodyMutationBlastModifier)) {  // Can't delete Root Segment
                    // Add this nodeID into queue for deletion at the end of mutation, to avoid shortening NodeList while traversing it:
                    nodesToDelete.Add(i);                    
                }
                else {
                    // Segment Attach Settings:
                    if (CheckForMutation(segmentAttachSettingsChance * bodyMutationBlastModifier)) {  // Position X
                        bodyGenome.CritterNodeList[i].jointLink.attachDir = MutateBodyVector3Normalized(bodyGenome.CritterNodeList[i].jointLink.attachDir);
                        numBodyMutations++;
                    }
                    if (CheckForMutation(segmentAttachSettingsChance * bodyMutationBlastModifier)) {  // Orientation X
                        bodyGenome.CritterNodeList[i].jointLink.restAngleDir = MutateBodyVector3Normalized(bodyGenome.CritterNodeList[i].jointLink.restAngleDir);
                        numBodyMutations++;
                    }

                    // Joint Settings:
                    if (CheckForMutation(jointSettingsChance * bodyMutationBlastModifier)) {
                        bodyGenome.CritterNodeList[i].jointLink.jointLimitPrimary = MutateBodyFloatMult(bodyGenome.CritterNodeList[i].jointLink.jointLimitPrimary);
                    }
                    if (CheckForMutation(jointSettingsChance * bodyMutationBlastModifier)) {
                        bodyGenome.CritterNodeList[i].jointLink.jointLimitSecondary = MutateBodyFloatMult(bodyGenome.CritterNodeList[i].jointLink.jointLimitSecondary);
                    }
                    if (CheckForMutation(jointSettingsChance * bodyMutationBlastModifier)) {
                        bodyGenome.CritterNodeList[i].jointLink.recursionScalingFactor = MutateBodyFloatMult(bodyGenome.CritterNodeList[i].jointLink.recursionScalingFactor);
                    }
                    // Joint Hinge TYPE!!!!  --- how to handle this???
                    if (CheckForMutation(jointSettingsChance * jointAngleTypeMultiplier * bodyMutationBlastModifier)) {
                        int jointTypeInt = Mathf.RoundToInt(UnityEngine.Random.Range(0f, 4f));
                        bodyGenome.CritterNodeList[i].jointLink.jointType = (CritterJointLink.JointType)jointTypeInt;
                        Debug.Log(i.ToString() + " Mutated to JointType: " + bodyGenome.CritterNodeList[i].jointLink.jointType);
                    }

                    // RECURSION:
                    if (CheckForMutation(recursionChance * bodyMutationBlastModifier)) {
                        int addRemove = Mathf.RoundToInt(UnityEngine.Random.Range(0f, 1f)) * 2 - 1;  // either -1 or 1
                                                                                                     //addRemove = 1; // TEMPORARY!!! testing add recursion
                        if (bodyGenome.CritterNodeList[i].jointLink.numberOfRecursions + addRemove < 0 || bodyGenome.CritterNodeList[i].jointLink.numberOfRecursions + addRemove > 3) {
                            // Do Nothing, tried to change numRecursions beyond the CAP
                        }
                        else {  // It's all good -- PROCEED:
                            bodyGenome.CritterNodeList[i].jointLink.numberOfRecursions += addRemove;
                            numBodyMutations++;

                            if (addRemove > 0) {  // Created an additional Recursion -- Need to ADD new BrainNodes:
                                                  //int numNodesBefore = brainGenome.nodeNEATList.Count;                            
                                                  //brainGenome.AdjustBrainAfterBodyChange(bodyGenome);
                                                  //int numNodesAfter = brainGenome.nodeNEATList.Count;
                                                  //Debug.Log("MUTATION RECURSION! b4#: " + numNodesBefore.ToString() + ", after#: " + numNodesAfter.ToString());
                            }
                            else {  // REMOVED a Recursion -- Need to REMOVE BrainNodes:
                                    //brainGenome.AdjustBrainRemovedRecursion(bodyGenome, i);
                            }
                            
                        }
                        // NEED TO FIX BRAIN!!! -- how to preserve existing wiring while adding new neurons that may re-order?
                        // Do I need to save a reference to segment/nodes within each input/output neuron?
                    }

                    // SYMMETRY
                    if (CheckForMutation(symmetryChance * bodyMutationBlastModifier)) {
                        int symmetryType = Mathf.RoundToInt(UnityEngine.Random.Range(0f, 2f));  // 0=none,1=x, or 2=y
                        Debug.Log("Mutated Symmetry! " + bodyGenome.CritterNodeList[i].jointLink.symmetryType.ToString() + " => " + ((CritterJointLink.SymmetryType)symmetryType).ToString());
                        bodyGenome.CritterNodeList[i].jointLink.symmetryType = (CritterJointLink.SymmetryType)symmetryType;                        
                    }
                    // EXTRA -- recursion forward, only attach to tail
                }

                // CREATE NEW ADD-ON!!  On this segment
                if (CheckForMutation(newAddonChance * bodyMutationBlastModifier)) {
                    // Which types can be created automatically??
                    // 
                    int randomAddon = Mathf.RoundToInt(UnityEngine.Random.Range(0f, 1f));
                    switch (randomAddon) {
                        case 0:
                            AddonOscillatorInput newOscillatorInput = new AddonOscillatorInput(i, GetNextAddonInnov());
                            bodyGenome.addonOscillatorInputList.Add(newOscillatorInput);
                            break;
                        case 1:
                            AddonValueInput newValueInput = new AddonValueInput(i, GetNextAddonInnov());
                            bodyGenome.addonValueInputList.Add(newValueInput);
                            break;
                        default:
                            break;
                    }
                    Debug.Log("NEW ADDON! " + randomAddon.ToString() + ", segmentNode: " + i.ToString());
                }
            }            
        }

        for(int i = 0; i < nodesToDelete.Count; i++) {
            Debug.Log("DELETE SEGMENT NODE! " + i.ToString());
            bodyGenome.DeleteNode(nodesToDelete[i]);
            bodyGenome.RenumberNodes();
        }
        List<int> nodesToAddTo = new List<int>(); // After Deleting nodes, check all remaining nodes for a chance to have a child segment added:
        for (int i = 0; i < bodyGenome.CritterNodeList.Count; i++) {
            if (CheckForMutation(newSegmentChance * bodyMutationBlastModifier)) {
                nodesToAddTo.Add(i);
            }
        }
        for (int i = 0; i < nodesToAddTo.Count; i++) {
            Vector3 attachDir = Vector3.Slerp(new Vector3(0f, 0f, 1f), UnityEngine.Random.onUnitSphere, UnityEngine.Random.Range(0f, 1f)); //ConvertWorldSpaceToAttachDir(selectedSegment, rightClickWorldPosition);
            int nextID = bodyGenome.CritterNodeList.Count;
            bodyGenome.AddNewNode(bodyGenome.CritterNodeList[nodesToAddTo[i]], attachDir, new Vector3(0f, 0f, 0f), nextID, GetNextNodeInnov());

            // Init joint type:
            bodyGenome.CritterNodeList[bodyGenome.CritterNodeList.Count - 1].jointLink.jointType = (CritterJointLink.JointType)Mathf.RoundToInt(UnityEngine.Random.Range(1, 4));

            // Auto-Add-ons: -- New Segment starts with a joint angle sensor and joint Motor by default:
            AddonJointAngleSensor newJointAngleSensor = new AddonJointAngleSensor(nextID, GetNextAddonInnov());
            bodyGenome.addonJointAngleSensorList.Add(newJointAngleSensor);
            // Motor:
            AddonJointMotor newJointMotor = new AddonJointMotor(nextID, GetNextAddonInnov());
            bodyGenome.addonJointMotorList.Add(newJointMotor);

            Debug.Log("New SEGMENT! : " + nodesToAddTo[i].ToString());
        }        

        // Addon Mutation:
        PerformAddonMutation(ref bodyGenome, ref brainGenome);
        //Debug.Log("NumBodyMutations: " + numBodyMutations.ToString());
    }
    public void PerformAddonMutation(ref CritterGenome bodyGenome, ref GenomeNEAT brainGenome) {
             
        // Chance to Remove an existing Add-on:
        // Chance to Mutate Add-On Settings:
        for (int i = bodyGenome.addonPhysicalAttributesList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonPhysicalAttributesList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonPhysicalAttributesList[i].bounciness[0] = MutateBodyFloatMult(bodyGenome.addonPhysicalAttributesList[i].bounciness[0], 0f, 1f);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonPhysicalAttributesList[i].dynamicFriction[0] = MutateBodyFloatMult(bodyGenome.addonPhysicalAttributesList[i].dynamicFriction[0], 0f, 1f);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonPhysicalAttributesList[i].staticFriction[0] = MutateBodyFloatMult(bodyGenome.addonPhysicalAttributesList[i].staticFriction[0], 0f, 1f);
                }
                /*if (CheckForMutation(addonSettingsChance)) {
                    bodyGenome.addonPhysicalAttributesList[i].freezePositionX[0] = MutateBodyBool(bodyGenome.addonPhysicalAttributesList[i].freezePositionX[0]);
                }
                if (CheckForMutation(addonSettingsChance)) {
                    bodyGenome.addonPhysicalAttributesList[i].freezePositionY[0] = MutateBodyBool(bodyGenome.addonPhysicalAttributesList[i].freezePositionY[0]);
                }
                if (CheckForMutation(addonSettingsChance)) {
                    bodyGenome.addonPhysicalAttributesList[i].freezePositionZ[0] = MutateBodyBool(bodyGenome.addonPhysicalAttributesList[i].freezePositionZ[0]);
                }
                if (CheckForMutation(addonSettingsChance)) {
                    bodyGenome.addonPhysicalAttributesList[i].freezeRotationX[0] = MutateBodyBool(bodyGenome.addonPhysicalAttributesList[i].freezeRotationX[0]);
                }
                if (CheckForMutation(addonSettingsChance)) {
                    bodyGenome.addonPhysicalAttributesList[i].freezeRotationY[0] = MutateBodyBool(bodyGenome.addonPhysicalAttributesList[i].freezeRotationY[0]);
                }
                if (CheckForMutation(addonSettingsChance)) {
                    bodyGenome.addonPhysicalAttributesList[i].freezeRotationZ[0] = MutateBodyBool(bodyGenome.addonPhysicalAttributesList[i].freezeRotationZ[0]);
                }*/
            }
        }
        for (int i = bodyGenome.addonJointAngleSensorList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonJointAngleSensorList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonJointAngleSensorList[i].sensitivity[0] = MutateBodyFloatMult(bodyGenome.addonJointAngleSensorList[i].sensitivity[0], 0.001f, 100f);
                }
                // #################  How to handle MEasureVel Checkbox?? It adds a Neuron!!!!!!!!!
                // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%   
            }
        }
        for (int i = bodyGenome.addonContactSensorList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonContactSensorList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonContactSensorList[i].contactSensitivity[0] = MutateBodyFloatMult(bodyGenome.addonContactSensorList[i].contactSensitivity[0], 0.01f, 10f);
                }
            }            
        }
        for (int i = bodyGenome.addonRaycastSensorList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonRaycastSensorList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonRaycastSensorList[i].forwardVector[0] = MutateBodyVector3Normalized(bodyGenome.addonRaycastSensorList[i].forwardVector[0]);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonRaycastSensorList[i].maxDistance[0] = MutateBodyFloatMult(bodyGenome.addonRaycastSensorList[i].maxDistance[0], 0.01f, 100f);
                }
            }            
        }
        for (int i = bodyGenome.addonCompassSensor1DList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonCompassSensor1DList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonCompassSensor1DList[i].forwardVector[0] = MutateBodyVector3Normalized(bodyGenome.addonCompassSensor1DList[i].forwardVector[0]);
                }
            }                               
        }
        for (int i = bodyGenome.addonCompassSensor3DList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonCompassSensor3DList.RemoveAt(i);
            }
            else {

            }

        }
        for (int i = bodyGenome.addonPositionSensor1DList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonPositionSensor1DList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonPositionSensor1DList[i].forwardVector[0] = MutateBodyVector3Normalized(bodyGenome.addonPositionSensor1DList[i].forwardVector[0]);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonPositionSensor1DList[i].relative[0] = MutateBodyBool(bodyGenome.addonPositionSensor1DList[i].relative[0]);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonPositionSensor1DList[i].sensitivity[0] = MutateBodyFloatMult(bodyGenome.addonPositionSensor1DList[i].sensitivity[0], 0.01f, 100f);
                }
            }            
        }
        for (int i = bodyGenome.addonPositionSensor3DList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonPositionSensor3DList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonPositionSensor3DList[i].sensitivity[0] = MutateBodyFloatMult(bodyGenome.addonPositionSensor3DList[i].sensitivity[0], 0.01f, 100f);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonPositionSensor3DList[i].relative[0] = MutateBodyBool(bodyGenome.addonPositionSensor3DList[i].relative[0]);
                }
            }            
        }
        for (int i = bodyGenome.addonRotationSensor1DList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonRotationSensor1DList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonRotationSensor1DList[i].localAxis[0] = MutateBodyVector3Normalized(bodyGenome.addonRotationSensor1DList[i].localAxis[0]);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonRotationSensor1DList[i].sensitivity[0] = MutateBodyFloatMult(bodyGenome.addonRotationSensor1DList[i].sensitivity[0], 0.01f, 100f);
                }
            }            
        }
        for (int i = bodyGenome.addonRotationSensor3DList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonRotationSensor3DList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonRotationSensor3DList[i].sensitivity[0] = MutateBodyFloatMult(bodyGenome.addonRotationSensor3DList[i].sensitivity[0], 0.01f, 100f);
                }
            }            
        }
        for (int i = bodyGenome.addonVelocitySensor1DList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonVelocitySensor1DList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonVelocitySensor1DList[i].sensitivity[0] = MutateBodyFloatMult(bodyGenome.addonVelocitySensor1DList[i].sensitivity[0], 0.01f, 100f);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonVelocitySensor1DList[i].forwardVector[0] = MutateBodyVector3Normalized(bodyGenome.addonVelocitySensor1DList[i].forwardVector[0]);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonVelocitySensor1DList[i].relative[0] = MutateBodyBool(bodyGenome.addonVelocitySensor1DList[i].relative[0]);
                }
            }            
        }
        for (int i = bodyGenome.addonVelocitySensor3DList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonVelocitySensor3DList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonVelocitySensor3DList[i].sensitivity[0] = MutateBodyFloatMult(bodyGenome.addonVelocitySensor3DList[i].sensitivity[0], 0.01f, 100f);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonVelocitySensor3DList[i].relative[0] = MutateBodyBool(bodyGenome.addonVelocitySensor3DList[i].relative[0]);
                }
            }            
        }
        for (int i = bodyGenome.addonAltimeterList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonAltimeterList.RemoveAt(i);
            }
            else {

            }
        }
        for (int i = bodyGenome.addonEarBasicList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonEarBasicList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonEarBasicList[i].sensitivity[0] = MutateBodyFloatMult(bodyGenome.addonEarBasicList[i].sensitivity[0], 0.01f, 100f);
                }
            }                              
        }
        for (int i = bodyGenome.addonGravitySensorList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonGravitySensorList.RemoveAt(i);
            }
            else {

            }
        }
        for (int i = bodyGenome.addonOscillatorInputList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonOscillatorInputList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonOscillatorInputList[i].amplitude[0] = MutateBodyFloatMult(bodyGenome.addonOscillatorInputList[i].amplitude[0], 0.01f, 100f);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonOscillatorInputList[i].frequency[0] = MutateBodyFloatMult(bodyGenome.addonOscillatorInputList[i].frequency[0], 0.01f, 50f);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonOscillatorInputList[i].offset[0] = MutateBodyFloatMult(bodyGenome.addonOscillatorInputList[i].offset[0], -50f, 50f);
                }
            }            
        }
        for (int i = bodyGenome.addonValueInputList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonValueInputList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonValueInputList[i].value[0] = MutateBodyFloatMult(bodyGenome.addonValueInputList[i].value[0], -100f, 100f);
                }
            }            
        }
        for (int i = bodyGenome.addonTimerInputList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonTimerInputList.RemoveAt(i);
            }
            else {

            }
        }
        //=======================  OUTPUTS ===================== OUTPUTS ======================= OUTPUTS =====================================================
        for (int i = bodyGenome.addonJointMotorList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonJointMotorList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonJointMotorList[i].motorForce[0] = MutateBodyFloatMult(bodyGenome.addonJointMotorList[i].motorForce[0], 0.01f, 200f);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonJointMotorList[i].motorSpeed[0] = MutateBodyFloatMult(bodyGenome.addonJointMotorList[i].motorSpeed[0], 0.01f, 200f);
                }
            }            
        }
        for (int i = bodyGenome.addonThrusterEffector1DList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonThrusterEffector1DList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonThrusterEffector1DList[i].forwardVector[0] = MutateBodyVector3Normalized(bodyGenome.addonThrusterEffector1DList[i].forwardVector[0]);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonThrusterEffector1DList[i].maxForce[0] = MutateBodyFloatMult(bodyGenome.addonThrusterEffector1DList[i].maxForce[0], 0.01f, 100f);
                }
            }            
        }
        for (int i = bodyGenome.addonThrusterEffector3DList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonThrusterEffector3DList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonThrusterEffector3DList[i].maxForce[0] = MutateBodyFloatMult(bodyGenome.addonThrusterEffector3DList[i].maxForce[0], 0.01f, 100f);
                }
            }            
        }        
        for (int i = bodyGenome.addonTorqueEffector1DList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonTorqueEffector1DList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonTorqueEffector1DList[i].maxTorque[0] = MutateBodyFloatMult(bodyGenome.addonTorqueEffector1DList[i].maxTorque[0], 0.01f, 100f);
                }
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonTorqueEffector1DList[i].axis[0] = MutateBodyVector3Normalized(bodyGenome.addonTorqueEffector1DList[i].axis[0]);
                }
            }            
        }
        for (int i = bodyGenome.addonTorqueEffector3DList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonTorqueEffector3DList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonTorqueEffector3DList[i].maxTorque[0] = MutateBodyFloatMult(bodyGenome.addonTorqueEffector3DList[i].maxTorque[0], 0.01f, 100f);
                }
            }            
        }
        for (int i = bodyGenome.addonMouthBasicList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonMouthBasicList.RemoveAt(i);
            }
            else {

            }
        }
        for (int i = bodyGenome.addonNoiseMakerBasicList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonNoiseMakerBasicList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonNoiseMakerBasicList[i].amplitude[0] = MutateBodyFloatMult(bodyGenome.addonNoiseMakerBasicList[i].amplitude[0], 0.01f, 100f);
                }
            }            
        }
        for (int i = bodyGenome.addonStickyList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonStickyList.RemoveAt(i);
            }
            else {

            }
        }
        for (int i = bodyGenome.addonWeaponBasicList.Count - 1; i >= 0; i--) {
            if (CheckForMutation(removeAddonChance * bodyMutationBlastModifier)) {
                // DELETE THIS ADD-ON!!!
                bodyGenome.addonWeaponBasicList.RemoveAt(i);
            }
            else {
                if (CheckForMutation(addonSettingsChance * bodyMutationBlastModifier)) {
                    bodyGenome.addonWeaponBasicList[i].strength[0] = MutateBodyFloatMult(bodyGenome.addonWeaponBasicList[i].strength[0], 0.01f, 100f);
                }
            }            
        }

        // UPDATE BRAIN/BODY:
        brainGenome.AdjustBrainAfterBodyChange(ref bodyGenome);
    }
    public Population BreedPopulation(ref Population sourcePopulation, int currentGeneration) {

        #region Pre-Crossover, Figuring out how many agents to breed etc.
        int LifetimeGeneration = currentGeneration + sourcePopulation.trainingGenerations;
        int totalNumWeightMutations = 0;
        //float totalWeightChangeValue = 0f;
        // go through species list and adjust fitness
        List<SpeciesBreedingPool> childSpeciesPoolsList = new List<SpeciesBreedingPool>(); // will hold agents in an internal list to facilitate crossover
        
        for (int s = 0; s < sourcePopulation.speciesBreedingPoolList.Count; s++) {            
            SpeciesBreedingPool newChildSpeciesPool = new SpeciesBreedingPool(sourcePopulation.speciesBreedingPoolList[s].templateGenome, sourcePopulation.speciesBreedingPoolList[s].speciesID);  // create Breeding Pools
            // copies the existing breeding pools but leaves their agentLists empty for future children
            childSpeciesPoolsList.Add(newChildSpeciesPool);            // Add to list of pools          
        }

        sourcePopulation.RankAgentArray(); // based on modified species fitness score, so compensated for species sizes
        
        Agent[] newAgentArray = new Agent[sourcePopulation.masterAgentArray.Length];

        // Calculate total fitness score:
        float totalScore = 0f;
        if (survivalByRaffle) {
            for (int a = 0; a < sourcePopulation.populationMaxSize; a++) { // iterate through all agents
                totalScore += sourcePopulation.masterAgentArray[a].fitnessScoreSpecies;
            }
        }

        // Figure out How many Agents survive
        int numSurvivors = Mathf.RoundToInt(survivalRate * (float)sourcePopulation.populationMaxSize);
        //Depending on method, one at a time, select an Agent to survive until the max Number is reached
        int newChildIndex = 0;
        // For ( num Agents ) {
        for (int i = 0; i < numSurvivors; i++) {
            // If survival is by fitness score ranking:
            if (survivalByRank) {
                // Pop should already be ranked, so just traverse from top (best) to bottom (worst)
                newAgentArray[newChildIndex] = sourcePopulation.masterAgentArray[newChildIndex];
                SpeciesBreedingPool survivingAgentBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, newAgentArray[newChildIndex].speciesID);
                survivingAgentBreedingPool.AddNewAgent(newAgentArray[newChildIndex]);
                //SortNewAgentIntoSpecies(newAgentArray[newChildIndex], childSpeciesList); // sorts this surviving agent into next generation's species'
                newChildIndex++;
            }
            // if survival is completely random, as a control:
            if (survivalStochastic) {
                int randomAgent = UnityEngine.Random.Range(0, numSurvivors - 1);
                // Set next newChild slot to a randomly-chosen agent within the survivor faction -- change to full random?
                newAgentArray[newChildIndex] = sourcePopulation.masterAgentArray[randomAgent];
                SpeciesBreedingPool survivingAgentBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, newAgentArray[newChildIndex].speciesID);
                survivingAgentBreedingPool.AddNewAgent(newAgentArray[newChildIndex]);
                //SortNewAgentIntoSpecies(newAgentArray[newChildIndex], childSpeciesList); // sorts this surviving agent into next generation's species'
                newChildIndex++;
            }
            // if survival is based on a fitness lottery:
            if (survivalByRaffle) {  // Try when Fitness is normalized from 0-1
                float randomSlicePosition = UnityEngine.Random.Range(0f, totalScore);
                float accumulatedFitness = 0f;
                for (int a = 0; a < sourcePopulation.populationMaxSize; a++) { // iterate through all agents
                    accumulatedFitness += sourcePopulation.masterAgentArray[a].fitnessScoreSpecies;
                    // if accum fitness is on slicePosition, copy this Agent
                    //Debug.Log("NumSurvivors: " + numSurvivors.ToString() + ", Surviving Agent " + a.ToString() + ": AccumFitness: " + accumulatedFitness.ToString() + ", RafflePos: " + randomSlicePosition.ToString() + ", TotalScore: " + totalScore.ToString() + ", newChildIndex: " + newChildIndex.ToString());
                    if (accumulatedFitness >= randomSlicePosition) {
                        newAgentArray[newChildIndex] = sourcePopulation.masterAgentArray[a]; // add to next gen's list of agents
                        SpeciesBreedingPool survivingAgentBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, newAgentArray[newChildIndex].speciesID);
                        survivingAgentBreedingPool.AddNewAgent(newAgentArray[newChildIndex]);
                        //SortNewAgentIntoSpecies(newAgentArray[newChildIndex], childSpeciesList); // sorts this surviving agent into next generation's species'
                        newChildIndex++;
                        break;
                    }
                }
            }
        }

        // Figure out how many new agents must be created to fill up the new population:
        int numNewChildAgents = sourcePopulation.populationMaxSize - numSurvivors;
        int numEligibleBreederAgents = Mathf.RoundToInt(breedingRate * (float)sourcePopulation.populationMaxSize);
        int currentRankIndex = 0;

        // Once the agents are ranked, trim the BreedingPools of agents that didn't make the cut for mating:
        if(useSpeciation) {
            for (int s = 0; s < sourcePopulation.speciesBreedingPoolList.Count; s++) {
                int index = 0;
                int failsafe = 0;
                int numAgents = sourcePopulation.speciesBreedingPoolList[s].agentList.Count;
                while (index < numAgents) {
                    if (index < sourcePopulation.speciesBreedingPoolList[s].agentList.Count) {
                        if (sourcePopulation.speciesBreedingPoolList[s].agentList[index].fitnessRank >= numEligibleBreederAgents) {
                            sourcePopulation.speciesBreedingPoolList[s].agentList.RemoveAt(index);
                        }
                        else {
                            index++;
                        }
                    }
                    else {
                        break;
                    }
                    failsafe++;
                    if (failsafe > 500) {
                        Debug.Log("INFINITE LOOP! hit failsafe 500 iters -- Trimming BreedingPools!");
                        break;
                    }
                }
                //Debug.Log("BreedPopulation -- TRIMSpeciesPool# " + s.ToString() + ", id: " + sourcePopulation.speciesBreedingPoolList[s].speciesID.ToString() + ", Count: " + sourcePopulation.speciesBreedingPoolList[s].agentList.Count.ToString());
                //
            }
        }        

        float totalScoreBreeders = 0f;
        if (breedingByRaffle) {  // calculate total fitness scores to determine lottery weights
            for (int a = 0; a < numEligibleBreederAgents; a++) { // iterate through all agents
                totalScoreBreeders += sourcePopulation.masterAgentArray[a].fitnessScoreSpecies;
            }
        }
        #endregion

        // Iterate over numAgentsToCreate :
        int newChildrenCreated = 0;
        while (newChildrenCreated < numNewChildAgents) {
            //		Find how many parents random number btw min/max:
            int numParentAgents = 2; // UnityEngine.Random.Range(minNumParents, maxNumParents);
            int numChildAgents = 1; // defaults to one child, but:
            if (numNewChildAgents - newChildrenCreated >= 2) {  // room for two more!
                numChildAgents = 2;                
            }

            Agent[] parentAgentsArray = new Agent[numParentAgents]; // assume 2 for now? yes, so far....
            
            List<GeneNodeNEAT>[] parentNodeListArray = new List<GeneNodeNEAT>[numParentAgents];
            List<GeneLinkNEAT>[] parentLinkListArray = new List<GeneLinkNEAT>[numParentAgents];

            Agent firstParentAgent = SelectAgentFromPopForBreeding(sourcePopulation, numEligibleBreederAgents, ref currentRankIndex);
            parentAgentsArray[0] = firstParentAgent;
            List<GeneNodeNEAT> firstParentNodeList = firstParentAgent.brainGenome.nodeNEATList;
            List<GeneLinkNEAT> firstParentLinkList = firstParentAgent.brainGenome.linkNEATList;
            //List<GeneNodeNEAT> firstParentNodeList = new List<GeneNodeNEAT>();
            //List<GeneLinkNEAT> firstParentLinkList = new List<GeneLinkNEAT>();
            //firstParentNodeList = firstParentAgent.brainGenome.nodeNEATList;
            //firstParentLinkList = firstParentAgent.brainGenome.linkNEATList;
            parentNodeListArray[0] = firstParentNodeList;
            parentLinkListArray[0] = firstParentLinkList;

            Agent secondParentAgent;
            SpeciesBreedingPool parentAgentBreedingPool = sourcePopulation.GetBreedingPoolByID(sourcePopulation.speciesBreedingPoolList, firstParentAgent.speciesID);
            if (useSpeciation) {
                //parentAgentBreedingPool
                float randBreedOutsideSpecies = UnityEngine.Random.Range(0f, 1f);
                if (randBreedOutsideSpecies < interspeciesBreedingRate) { // Attempts to Found a new species
                                                                          // allowed to breed outside its own species:
                    secondParentAgent = SelectAgentFromPopForBreeding(sourcePopulation, numEligibleBreederAgents, ref currentRankIndex);
                }
                else {
                    // Selects mate only from within its own species:
                    secondParentAgent = SelectAgentFromPoolForBreeding(parentAgentBreedingPool);
                }
            }
            else {
                secondParentAgent = SelectAgentFromPopForBreeding(sourcePopulation, numEligibleBreederAgents, ref currentRankIndex);
            }           
            
            parentAgentsArray[1] = secondParentAgent;
            List<GeneNodeNEAT> secondParentNodeList = secondParentAgent.brainGenome.nodeNEATList;
            List<GeneLinkNEAT> secondParentLinkList = secondParentAgent.brainGenome.linkNEATList;
            //List<GeneNodeNEAT> secondParentNodeList = new List<GeneNodeNEAT>();
            //List<GeneLinkNEAT> secondParentLinkList = new List<GeneLinkNEAT>();
            //secondParentNodeList = secondParentAgent.brainGenome.nodeNEATList;
            //secondParentLinkList = secondParentAgent.brainGenome.linkNEATList;
            parentNodeListArray[1] = secondParentNodeList;
            parentLinkListArray[1] = secondParentLinkList;
           
            //		Iterate over ChildArray.Length :  // how many newAgents created
            for (int c = 0; c < numChildAgents; c++) { // for number of child Agents in floatArray[][]:
                Agent newChildAgent = new Agent();
                
                List<GeneNodeNEAT> childNodeList = new List<GeneNodeNEAT>();
                List<GeneLinkNEAT> childLinkList = new List<GeneLinkNEAT>();
                
                GenomeNEAT childBrainGenome = new GenomeNEAT();
                childBrainGenome.nodeNEATList = childNodeList;
                childBrainGenome.linkNEATList = childLinkList;

                int numEnabledLinkGenes = 0;

                if (useCrossover) {                    
                    int nextLinkInnoA = 0;
                    int nextLinkInnoB = 0;
                    //int nextBodyNodeInno = 0;
                    //int nextBodyAddonInno = 0;

                    int failsafeMax = 500;
                    int failsafe = 0;
                    int parentListIndexA = 0;
                    int parentListIndexB = 0;
                    //int parentBodyNodeIndex = 0;
                    bool parentDoneA = false;
                    bool parentDoneB = false;
                    bool endReached = false;

                    int moreFitParent = 0;  // which parent is more Fit
                    if (parentAgentsArray[0].fitnessScoreSpecies < parentAgentsArray[1].fitnessScoreSpecies) {
                        moreFitParent = 1;
                    }
                    else if (parentAgentsArray[0].fitnessScoreSpecies == parentAgentsArray[1].fitnessScoreSpecies) {
                        moreFitParent = Mathf.RoundToInt(UnityEngine.Random.Range(0f, 1f));
                    }

                    //  MATCH UP Links between both agents, if they have a gene with matching Inno#, then mixing can occur                    
                    while (!endReached) {
                        failsafe++;
                        if(failsafe > failsafeMax) {
                            Debug.Log("failsafe reached!");
                            break;
                        }
                        // inno# of next links:
                        if(parentLinkListArray[0].Count > parentListIndexA) {
                            nextLinkInnoA = parentLinkListArray[0][parentListIndexA].innov;
                        }
                        else {
                            parentDoneA = true;
                        }
                        if (parentLinkListArray[1].Count > parentListIndexB) {
                            nextLinkInnoB = parentLinkListArray[1][parentListIndexB].innov;
                        }
                        else {
                            parentDoneB = true;
                        }

                        int innoDelta = nextLinkInnoA - nextLinkInnoB;  // 0=match, neg= Aextra, pos= Bextra
                        if (parentDoneA && !parentDoneB) {
                            innoDelta = 1;
                        }
                        if (parentDoneB && !parentDoneA) {
                            innoDelta = -1;
                        }
                        if (parentDoneA && parentDoneB) {  // reached end of both parent's linkLists
                            endReached = true;
                            break;
                        }

                        if (innoDelta < 0) {  // Parent A has an earlier link mutation
                            //Debug.Log("newChildIndex: " + newChildIndex.ToString() + ", IndexA: " + parentListIndexA.ToString() + ", IndexB: " + parentListIndexB.ToString() + ", innoDelta < 0 (" + innoDelta.ToString() + ") --  moreFitP: " + moreFitParent.ToString() + ", nextLinkInnoA: " + nextLinkInnoA.ToString() + ", nextLinkInnoB: " + nextLinkInnoB.ToString());
                            if (moreFitParent == 0) {  // Parent A is more fit:
                                GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[0][parentListIndexA].fromNodeID, parentLinkListArray[0][parentListIndexA].toNodeID, parentLinkListArray[0][parentListIndexA].weight, parentLinkListArray[0][parentListIndexA].enabled, parentLinkListArray[0][parentListIndexA].innov, parentLinkListArray[0][parentListIndexA].birthGen);
                                childLinkList.Add(newChildLink);
                                if (parentLinkListArray[0][parentListIndexA].enabled)
                                    numEnabledLinkGenes++;
                            }
                            else {
                                if(CheckForMutation(crossoverRandomLinkChance)) {  // was less fit parent, but still passed on a gene!:
                                    GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[0][parentListIndexA].fromNodeID, parentLinkListArray[0][parentListIndexA].toNodeID, parentLinkListArray[0][parentListIndexA].weight, parentLinkListArray[0][parentListIndexA].enabled, parentLinkListArray[0][parentListIndexA].innov, parentLinkListArray[0][parentListIndexA].birthGen);
                                    childLinkList.Add(newChildLink);
                                }
                            }
                            parentListIndexA++;
                        }
                        if (innoDelta > 0) {  // Parent B has an earlier link mutation
                            //Debug.Log("newChildIndex: " + newChildIndex.ToString() + ", IndexA: " + parentListIndexA.ToString() + ", IndexB: " + parentListIndexB.ToString() + ", innoDelta > 0 (" + innoDelta.ToString() + ") --  moreFitP: " + moreFitParent.ToString() + ", nextLinkInnoA: " + nextLinkInnoA.ToString() + ", nextLinkInnoB: " + nextLinkInnoB.ToString());
                            if (moreFitParent == 1) {  // Parent B is more fit:
                                GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[1][parentListIndexB].fromNodeID, parentLinkListArray[1][parentListIndexB].toNodeID, parentLinkListArray[1][parentListIndexB].weight, parentLinkListArray[1][parentListIndexB].enabled, parentLinkListArray[1][parentListIndexB].innov, parentLinkListArray[1][parentListIndexB].birthGen);
                                childLinkList.Add(newChildLink);
                                if (parentLinkListArray[1][parentListIndexB].enabled)
                                    numEnabledLinkGenes++;
                            }
                            else {
                                if (CheckForMutation(crossoverRandomLinkChance)) {  // was less fit parent, but still passed on a gene!:
                                    GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[1][parentListIndexB].fromNodeID, parentLinkListArray[1][parentListIndexB].toNodeID, parentLinkListArray[1][parentListIndexB].weight, parentLinkListArray[1][parentListIndexB].enabled, parentLinkListArray[1][parentListIndexB].innov, parentLinkListArray[1][parentListIndexB].birthGen);
                                    childLinkList.Add(newChildLink);
                                }
                            }
                            parentListIndexB++;
                        }
                        if (innoDelta == 0) {  // Match!
                            float randParentIndex = UnityEngine.Random.Range(0f, 1f);
                            float newWeightValue;
                            if (randParentIndex < 0.5) {
                                // ParentA wins:
                                newWeightValue = parentLinkListArray[0][parentListIndexA].weight;
                            }
                            else {  // ParentB wins:
                                newWeightValue = parentLinkListArray[1][parentListIndexB].weight;
                            }
                            //Debug.Log("newChildIndex: " + newChildIndex.ToString() + ", IndexA: " + parentListIndexA.ToString() + ", IndexB: " + parentListIndexB.ToString() + ", innoDelta == 0 (" + innoDelta.ToString() + ") --  moreFitP: " + moreFitParent.ToString() + ", nextLinkInnoA: " + nextLinkInnoA.ToString() + ", nextLinkInnoB: " + nextLinkInnoB.ToString() + ", randParent: " + randParentIndex.ToString() + ", weight: " + newWeightValue.ToString());
                            GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[0][parentListIndexA].fromNodeID, parentLinkListArray[0][parentListIndexA].toNodeID, newWeightValue, parentLinkListArray[0][parentListIndexA].enabled, parentLinkListArray[0][parentListIndexA].innov, parentLinkListArray[0][parentListIndexA].birthGen);
                            childLinkList.Add(newChildLink);
                            if (parentLinkListArray[0][parentListIndexA].enabled)
                                numEnabledLinkGenes++;

                            parentListIndexA++;
                            parentListIndexB++;
                        }

                    }
                    // once childLinkList is built -- use nodes of the moreFit parent:
                    for (int i = 0; i < parentNodeListArray[moreFitParent].Count; i++) { 
                        // iterate through all nodes in the parent List and copy them into fresh new geneNodes:
                        GeneNodeNEAT clonedNode = new GeneNodeNEAT(parentNodeListArray[moreFitParent][i].id, parentNodeListArray[moreFitParent][i].nodeType, parentNodeListArray[moreFitParent][i].activationFunction, parentNodeListArray[moreFitParent][i].sourceAddonInno, parentNodeListArray[moreFitParent][i].sourceAddonRecursionNum, false, parentNodeListArray[moreFitParent][i].sourceAddonChannelNum);
                        childNodeList.Add(clonedNode);
                    }

                    if (useMutation) {
                        // BODY MUTATION:
                        //PerformBodyMutation(ref childBodyGenome, ref childBrainGenome);
                        // NEED TO ADJUST BRAINS IF MUTATION CHANGES #NODES!!!!

                        // BRAIN MUTATION:
                        if (numEnabledLinkGenes < 1)
                            numEnabledLinkGenes = 1;
                        for (int k = 0; k < childLinkList.Count; k++) {
                            float mutateChance = mutationBlastModifier * masterMutationRate / (1f + (float)numEnabledLinkGenes * 0.15f);
                            if (LifetimeGeneration - childLinkList[k].birthGen < newLinkBonusDuration) {
                                float t = 1 - ((LifetimeGeneration - childLinkList[k].birthGen) / (float)newLinkBonusDuration);
                                // t=0 means age of gene is same as bonusDuration, t=1 means it is brand new
                                mutateChance = Mathf.Lerp(mutateChance, mutateChance * newLinkMutateBonus, t);
                            }
                            if (CheckForMutation(mutateChance)) {  // Weight Mutation!
                                //Debug.Log("Weight Mutation Link[" + k.ToString() + "] weight: " + childLinkList[k].weight.ToString() + ", mutate: " + MutateFloat(childLinkList[k].weight).ToString());
                                childLinkList[k].weight = MutateFloat(childLinkList[k].weight);
                                totalNumWeightMutations++;
                            }
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationRemoveLinkChance)) {
                            //Debug.Log("Remove Link Mutation Agent[" + newChildIndex.ToString() + "]");
                            childBrainGenome.RemoveRandomLink();
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationAddNodeChance)) {   // Adds a new node
                            //Debug.Log("Add Node Mutation Agent[" + newChildIndex.ToString() + "]");
                            childBrainGenome.AddNewRandomNode(LifetimeGeneration, GetNextAddonInnov());
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationRemoveNodeChance)) {   // Adds a new node
                            //Debug.Log("Add Node Mutation Agent[" + newChildIndex.ToString() + "]");
                            childBrainGenome.RemoveRandomNode();
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationAddLinkChance)) { // Adds new connection
                            //Debug.Log("Add Link Mutation Agent[" + newChildIndex.ToString() + "]");
                            if (CheckForMutation(existingNetworkBias)) {
                                childBrainGenome.AddNewExtraLink(existingFromNodeBias, LifetimeGeneration);
                            }
                            else {
                                childBrainGenome.AddNewRandomLink(LifetimeGeneration);
                            }
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationActivationFunctionChance)) {
                            TransferFunctions.TransferFunction newFunction;
                            int randIndex = Mathf.RoundToInt(UnityEngine.Random.Range(0f, childNodeList.Count - 1));
                            int randomTF = (int)UnityEngine.Random.Range(0f, 12f);

                            switch (randomTF) {
                                case 0:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                case 1:
                                    newFunction = TransferFunctions.TransferFunction.Linear;
                                    break;
                                case 2:
                                    newFunction = TransferFunctions.TransferFunction.Gaussian;
                                    break;
                                case 3:
                                    newFunction = TransferFunctions.TransferFunction.Abs;
                                    break;
                                case 4:
                                    newFunction = TransferFunctions.TransferFunction.Cos;
                                    break;
                                case 5:
                                    newFunction = TransferFunctions.TransferFunction.Sin;
                                    break;
                                case 6:
                                    newFunction = TransferFunctions.TransferFunction.Tan;
                                    break;
                                case 7:
                                    newFunction = TransferFunctions.TransferFunction.Square;
                                    break;
                                case 8:
                                    newFunction = TransferFunctions.TransferFunction.Threshold01;
                                    break;
                                case 9:
                                    newFunction = TransferFunctions.TransferFunction.ThresholdNegPos;
                                    break;
                                case 10:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                case 11:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                case 12:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                default:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                            }
                            if (childNodeList[randIndex].nodeType != GeneNodeNEAT.GeneNodeType.Out) {  // keep outputs -1 to 1 range
                                Debug.Log("ActivationFunction Mutation Node[" + randIndex.ToString() + "] prev: " + childNodeList[randIndex].activationFunction.ToString() + ", new: " + newFunction.ToString());
                                childNodeList[randIndex].activationFunction = newFunction;
                            }
                        }
                    }
                    else {
                        Debug.Log("Mutation Disabled!");
                    }

                    // THE BODY   ==========!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!======================================================================================
                    CritterGenome childBodyGenome = new CritterGenome();  // create new body genome for Child
                    // This creates the ROOT NODE!!!!
                    // Clone Nodes & Addons from more fit parent to create new child body genome
                    // crossover is on, so check for matching Nodes and Add-ons (based on Inno#'s) to determine when to mix Settings/Attributes:                    
                    // Iterate over the nodes of the more fit parent:
                    for (int i = 0; i < parentAgentsArray[moreFitParent].bodyGenome.CritterNodeList.Count; i++) {
                        int currentNodeInno = parentAgentsArray[moreFitParent].bodyGenome.CritterNodeList[i].innov;
                        if (i == 0) {  // if this is the ROOT NODE:
                            childBodyGenome.CritterNodeList[0].CopySettingsFromNode(parentAgentsArray[moreFitParent].bodyGenome.CritterNodeList[0]);
                            // The root node was already created during the Constructor method of the CritterGenome,
                            // ... so instead of creating a new one, just copy the settings
                        }
                        else {  // NOT the root node, proceed normally:
                                // Create new cloned node defaulted to the settings of the source( more-fit parent's) Node:
                            CritterNode clonedCritterNode = parentAgentsArray[moreFitParent].bodyGenome.CritterNodeList[i].CloneThisCritterNode();
                            
                            // Check other parent for same node:
                            for (int j = 0; j < parentAgentsArray[1 - moreFitParent].bodyGenome.CritterNodeList.Count; j++) {
                                if (parentAgentsArray[1 - moreFitParent].bodyGenome.CritterNodeList[j].innov == currentNodeInno) {
                                    // CROSSOVER NODE SETTINGS HERE!!!  ---- If random dice roll > 0.5, use less fit parent's settings, otherwise leave as default
                                    BodyCrossover(ref clonedCritterNode, parentAgentsArray[1 - moreFitParent].bodyGenome.CritterNodeList[j]);                                    
                                }
                            }
                            childBodyGenome.CritterNodeList.Add(clonedCritterNode);
                        }                        
                    }
                    // ADD-ONS!!!!!!!!!!!!!!!!!!!!!!
                    BreedCritterAddons(ref childBodyGenome, ref parentAgentsArray[moreFitParent].bodyGenome, ref parentAgentsArray[1 - moreFitParent].bodyGenome);
                    newChildAgent.bodyGenome = childBodyGenome;  // ?????
                    if (useMutation) {
                        // BODY MUTATION:
                        PerformBodyMutation(ref childBodyGenome, ref childBrainGenome);
                    }
                }
                else { // no crossover:                    
                    
                    //===============================================================================================
                    for (int i = 0; i < parentNodeListArray[0].Count; i++) {
                        // iterate through all nodes in the parent List and copy them into fresh new geneNodes:
                        GeneNodeNEAT clonedNode = new GeneNodeNEAT(parentNodeListArray[0][i].id, parentNodeListArray[0][i].nodeType, parentNodeListArray[0][i].activationFunction, parentNodeListArray[0][i].sourceAddonInno, parentNodeListArray[0][i].sourceAddonRecursionNum, false, parentNodeListArray[0][i].sourceAddonChannelNum);
                        childNodeList.Add(clonedNode);
                    }
                    for (int j = 0; j < parentLinkListArray[0].Count; j++) {
                        //same thing with connections
                        GeneLinkNEAT clonedLink = new GeneLinkNEAT(parentLinkListArray[0][j].fromNodeID, parentLinkListArray[0][j].toNodeID, parentLinkListArray[0][j].weight, parentLinkListArray[0][j].enabled, parentLinkListArray[0][j].innov, parentLinkListArray[0][j].birthGen);
                        childLinkList.Add(clonedLink);
                        if (parentLinkListArray[0][j].enabled)
                            numEnabledLinkGenes++;
                    }
                    // MUTATION:
                    if (useMutation) {
                        // BODY MUTATION:
                        //childBrainGenome.nodeNEATList = childNodeList
                        //PerformBodyMutation(ref childBodyGenome, ref childBrainGenome);

                        // BRAIN MUTATION:
                        if (numEnabledLinkGenes < 1)
                            numEnabledLinkGenes = 1;
                        for (int k = 0; k < childLinkList.Count; k++) {
                            float mutateChance = mutationBlastModifier * masterMutationRate / (1f + (float)numEnabledLinkGenes * 0.15f);
                            if (LifetimeGeneration - childLinkList[k].birthGen < newLinkBonusDuration) {
                                float t = 1 - ((LifetimeGeneration - childLinkList[k].birthGen) / (float)newLinkBonusDuration);
                                // t=0 means age of gene is same as bonusDuration, t=1 means it is brand new
                                mutateChance = Mathf.Lerp(mutateChance, mutateChance * newLinkMutateBonus, t);
                            }
                            if (CheckForMutation(mutateChance)) {  // Weight Mutation!
                                //Debug.Log("Weight Mutation Link[" + k.ToString() + "] weight: " + childLinkList[k].weight.ToString() + ", mutate: " + MutateFloat(childLinkList[k].weight).ToString());
                                childLinkList[k].weight = MutateFloat(childLinkList[k].weight);
                                totalNumWeightMutations++;
                            }
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationRemoveLinkChance)) {
                            //Debug.Log("Remove Link Mutation Agent[" + newChildIndex.ToString() + "]");
                            childBrainGenome.RemoveRandomLink();
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationAddNodeChance)) {   // Adds a new node
                            //Debug.Log("Add Node Mutation Agent[" + newChildIndex.ToString() + "]");
                            childBrainGenome.AddNewRandomNode(LifetimeGeneration, GetNextAddonInnov());
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationAddLinkChance)) { // Adds new connection
                            //Debug.Log("Add Link Mutation Agent[" + newChildIndex.ToString() + "]");
                            if(CheckForMutation(existingNetworkBias)) {
                                childBrainGenome.AddNewExtraLink(existingFromNodeBias, LifetimeGeneration);
                            }
                            else {
                                childBrainGenome.AddNewRandomLink(LifetimeGeneration);
                            }
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationActivationFunctionChance)) {
                            TransferFunctions.TransferFunction newFunction;
                            int randIndex = Mathf.RoundToInt(UnityEngine.Random.Range(0f, childNodeList.Count - 1));
                            int randomTF = (int)UnityEngine.Random.Range(0f, 12f);

                            switch (randomTF) {
                                case 0:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                case 1:
                                    newFunction = TransferFunctions.TransferFunction.Linear;
                                    break;
                                case 2:
                                    newFunction = TransferFunctions.TransferFunction.Gaussian;
                                    break;
                                case 3:
                                    newFunction = TransferFunctions.TransferFunction.Abs;
                                    break;
                                case 4:
                                    newFunction = TransferFunctions.TransferFunction.Cos;
                                    break;
                                case 5:
                                    newFunction = TransferFunctions.TransferFunction.Sin;
                                    break;
                                case 6:
                                    newFunction = TransferFunctions.TransferFunction.Tan;
                                    break;
                                case 7:
                                    newFunction = TransferFunctions.TransferFunction.Square;
                                    break;
                                case 8:
                                    newFunction = TransferFunctions.TransferFunction.Threshold01;
                                    break;
                                case 9:
                                    newFunction = TransferFunctions.TransferFunction.ThresholdNegPos;
                                    break;
                                case 10:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                case 11:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                case 12:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                default:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                            }
                            if (childNodeList[randIndex].nodeType != GeneNodeNEAT.GeneNodeType.Out) {  // keep outputs -1 to 1 range
                                Debug.Log("ActivationFunction Mutation Node[" + randIndex.ToString() + "] prev: " + childNodeList[randIndex].activationFunction.ToString() + ", new: " + newFunction.ToString());
                                childNodeList[randIndex].activationFunction = newFunction;
                            }
                        }
                        //for (int t = 0; t < childNodeList.Count; t++) {
                            
                        //}
                    }
                    else {
                        Debug.Log("Mutation Disabled!");
                    }

                    //   THE BODY!!!!! ++++++++++++++++++++++================+++++++++++++++++++===============+++++++++++++++++++===================+++++++++++++++++==============
                    CritterGenome childBodyGenome = new CritterGenome();  // create new body genome for Child                 
                    // Iterate over the nodes of the more fit parent:
                    for (int i = 0; i < parentAgentsArray[0].bodyGenome.CritterNodeList.Count; i++) {
                        int currentNodeInno = parentAgentsArray[0].bodyGenome.CritterNodeList[i].innov;
                        if (i == 0) {  // if this is the ROOT NODE:
                            childBodyGenome.CritterNodeList[0].CopySettingsFromNode(parentAgentsArray[0].bodyGenome.CritterNodeList[0]);
                            // The root node was already created during the Constructor method of the CritterGenome,
                            // ... so instead of creating a new one, just copy the settings
                        }
                        else {  // NOT the root node, proceed normally:
                                // Create new cloned node defaulted to the settings of the source( more-fit parent's) Node:
                            CritterNode clonedCritterNode = parentAgentsArray[0].bodyGenome.CritterNodeList[i].CloneThisCritterNode();
                            childBodyGenome.CritterNodeList.Add(clonedCritterNode);
                        }
                    }
                    // ADD-ONS!!!!!!!!!!!!!!!!!!!!!!
                    BreedCritterAddons(ref childBodyGenome, ref parentAgentsArray[0].bodyGenome, ref parentAgentsArray[0].bodyGenome);
                    newChildAgent.bodyGenome = childBodyGenome;
                    if (useMutation) {
                        // BODY MUTATION:
                        PerformBodyMutation(ref childBodyGenome, ref childBrainGenome);
                    }
                }
                
                newChildAgent.brainGenome = childBrainGenome;
                //newChildAgent.brainGenome.nodeNEATList = childNodeList;
                //newChildAgent.brainGenome.linkNEATList = childLinkList;
                BrainNEAT childBrain = new BrainNEAT(newChildAgent.brainGenome);
                childBrain.BuildBrainNetwork();
                newChildAgent.brain = childBrain;
                //Debug.Log("NEW CHILD numNodes: " + newChildAgent.brainGenome.nodeNEATList.Count.ToString() + ", #Neurons: " + newChildAgent.brain.neuronList.Count.ToString());
                //newChildAgent.bodyGenome.PreBuildCritter(0.8f);
                // Species:
                if (useSpeciation) {
                    float randAdoption = UnityEngine.Random.Range(0f, 1f);
                    if (randAdoption < adoptionRate) { // Attempts to Found a new species
                        bool speciesGenomeMatch = false;
                        for (int s = 0; s < childSpeciesPoolsList.Count; s++) {
                            float geneticDistance = GenomeNEAT.MeasureGeneticDistance(newChildAgent.brainGenome, childSpeciesPoolsList[s].templateGenome, neuronWeight, linkWeight, weightWeight, normalizeExcess, normalizeDisjoint, normalizeLinkWeight);

                            if (geneticDistance < speciesSimilarityThreshold) {
                                speciesGenomeMatch = true;
                                //agent.speciesID = speciesBreedingPoolList[s].speciesID; // this is done inside the AddNewAgent method below v v v 
                                childSpeciesPoolsList[s].AddNewAgent(newChildAgent);
                                //Debug.Log(" NEW CHILD (" + newChildIndex.ToString() + ") SortAgentIntoBreedingPool dist: " + geneticDistance.ToString() + ", speciesIDs: " + newChildAgent.speciesID.ToString() + ", " + childSpeciesPoolsList[s].speciesID.ToString() + ", speciesCount: " + childSpeciesPoolsList[s].agentList.Count.ToString());
                                break;
                            }
                        }
                        if (!speciesGenomeMatch) {

                            SpeciesBreedingPool newSpeciesBreedingPool = new SpeciesBreedingPool(newChildAgent.brainGenome, sourcePopulation.GetNextSpeciesID()); // creates new speciesPool modeled on this agent's genome

                            newSpeciesBreedingPool.AddNewAgent(newChildAgent);  // add this agent to breeding pool
                            childSpeciesPoolsList.Add(newSpeciesBreedingPool);  // add new speciesPool to the population's list of all active species

                            //Debug.Log(" NEW CHILD (" + newChildIndex.ToString() + ") SortAgentIntoBreedingPool NO MATCH!!! -- creating new BreedingPool " + newSpeciesBreedingPool.speciesID.ToString() + ", newChildAgentSpeciesID: " + newChildAgent.speciesID.ToString());
                        }
                    }
                    else {  // joins parent species automatically:
                        SpeciesBreedingPool newSpeciesBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, parentAgentBreedingPool.speciesID);
                        newSpeciesBreedingPool.AddNewAgent(newChildAgent);  // add this agent to breeding pool
                                                                            //Debug.Log(" NEW CHILD (" + newChildIndex.ToString() + ") NO ADOPTION SortAgentIntoBreedingPool speciesIDs: " + newChildAgent.speciesID.ToString() + ", " + newSpeciesBreedingPool.speciesID.ToString() + ", speciesCount: " + newSpeciesBreedingPool.agentList.Count.ToString());
                    }
                }
                else {  // joins parent species automatically:
                    SpeciesBreedingPool newSpeciesBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, parentAgentBreedingPool.speciesID);
                    newSpeciesBreedingPool.AddNewAgent(newChildAgent);  // add this agent to breeding pool                                                                        
                }

                newChildAgent.parentFitnessScoreA = sourcePopulation.masterAgentArray[newChildIndex].fitnessScore;
                newAgentArray[newChildIndex] = newChildAgent;

                newChildIndex++;  // new child created!
                newChildrenCreated++;
            }
        }

        /*Debug.Log("Finished Crossover! childSpeciesPoolsList:");
        for (int i = 0; i < sourcePopulation.speciesBreedingPoolList.Count; i++) {
            string poolString = " Child Species ID: " + sourcePopulation.speciesBreedingPoolList[i].speciesID.ToString();
            for (int j = 0; j < sourcePopulation.speciesBreedingPoolList[i].agentList.Count; j++) {
                poolString += ", member# " + j.ToString() + ", species: " + sourcePopulation.speciesBreedingPoolList[i].agentList[j].speciesID.ToString() + ", fitRank: " + sourcePopulation.speciesBreedingPoolList[i].agentList[j].fitnessRank.ToString();
            }
            Debug.Log(poolString);
        }*/

        // Clear out extinct species:
        int listIndex = 0;
        for (int s = 0; s < childSpeciesPoolsList.Count; s++) {
            if (listIndex >= childSpeciesPoolsList.Count) {
                Debug.Log("end childSpeciesPoolsList " + childSpeciesPoolsList.Count.ToString() + ", index= " + listIndex.ToString());
                break;
            }
            else {
                if (childSpeciesPoolsList[listIndex].agentList.Count == 0) {  // if empty:
                    //Debug.Log("Species " + childSpeciesPoolsList[listIndex].speciesID.ToString() + " WENT EXTINCT!!! --- childSpeciesPoolsList[" + listIndex.ToString() + "] old Count: " + childSpeciesPoolsList.Count.ToString() + ", s: " + s.ToString());
                    childSpeciesPoolsList.RemoveAt(listIndex);
                    //s--;  // see if this works                    
                }
                else {
                    listIndex++;
                }
            }
        }
        
        Debug.Log("Finished Crossover! totalNumWeightMutations: " + totalNumWeightMutations.ToString() + ", mutationBlastModifier: " + mutationBlastModifier.ToString() + ", bodyMutationBlastModifier: " + bodyMutationBlastModifier.ToString() + ", LifetimeGeneration: " + LifetimeGeneration.ToString() + ", currentGeneration: " + currentGeneration.ToString() + ", sourcePopulation.trainingGenerations: " + sourcePopulation.trainingGenerations.ToString());
        sourcePopulation.masterAgentArray = newAgentArray;
        sourcePopulation.speciesBreedingPoolList = childSpeciesPoolsList;

        /*Debug.Log("Finished Crossover! sourcePopulation.speciesBreedingPoolList:");
        for (int i = 0; i < sourcePopulation.speciesBreedingPoolList.Count; i++) {
            string poolString = "New Species ID: " + sourcePopulation.speciesBreedingPoolList[i].speciesID.ToString();
            for (int j = 0; j < sourcePopulation.speciesBreedingPoolList[i].agentList.Count; j++) {
                poolString += ", member# " + j.ToString() + ", species: " + sourcePopulation.speciesBreedingPoolList[i].agentList[j].speciesID.ToString() + ", fitRank: " + sourcePopulation.speciesBreedingPoolList[i].agentList[j].fitnessRank.ToString();
            }
            Debug.Log(poolString);
        }*/

        return sourcePopulation;
    }
    public void AdjustBrainAfterBodyChange(ref CritterGenome bodyGenome) {
        // Try to do it assuming this function only took a CritterNode as input, rather than full bodyGenome:
        //CritterNode sourceNode = bodyGenome.CritterNodeList[bodyNodeID];
        string beforeBrain = "AdjustBrain Before: \n";
        string afterBrain = "AdjustBrain After: \n";

        List<GeneNodeNEAT> newBrainNodeList = bodyGenome.GetBlankBrainNodesFromBody(); // doesn't include Hidden Nodes
        //List<GeneLinkNEAT> newBrainLinkList = new List<GeneLinkNEAT>();  // need to make a new copy so that the old link-list stays static while searching for matching from/toID's
        // Find number of Input+Output nodes in the old list:
        //int numOriginalInOutNodes = 0;
        //for (int i = 0; i < nodeNEATList.Count; i++) {
        //    if(nodeNEATList[i].nodeType != GeneNodeNEAT.GeneNodeType.Hid) {
        //        numOriginalInOutNodes++;
        //    }            
        //}
        // Compare this to the number of nodes in the new list (which doesn't contain any hidden nodes)
        //int netNewNodes = newBrainNodeList.Count - numOriginalInOutNodes;

        //Debug.Log("AdjustBrainAddedRecursion! numOriginalInOutNodes: " + numOriginalInOutNodes.ToString() + ", netNewNodes: " + netNewNodes.ToString() + ", bodyNodeID: " + bodyNodeID.ToString() + ", recursionNum: " + recursionNum.ToString());

        int nextNodeIndexID = newBrainNodeList.Count;  // where to start counting for hiddenNode ID's
        for (int i = 0; i < nodeNEATList.Count; i++) {
            beforeBrain += "Node " + nodeNEATList[i].id.ToString() + " (" + nodeNEATList[i].sourceAddonInno.ToString() + ", " + nodeNEATList[i].sourceAddonRecursionNum.ToString() + ", " + nodeNEATList[i].sourceAddonChannelNum.ToString() + ")\n";

            if (nodeNEATList[i].nodeType == GeneNodeNEAT.GeneNodeType.Hid) {
                //Debug.Log("AdjustBrainAfterBodyChange HID NODE: nextNodeIndexID: " + (nextNodeIndexID).ToString());
                GeneNodeNEAT clonedNode = new GeneNodeNEAT(nextNodeIndexID, nodeNEATList[i].nodeType, nodeNEATList[i].activationFunction, nodeNEATList[i].sourceAddonInno, nodeNEATList[i].sourceAddonRecursionNum, false, nodeNEATList[i].sourceAddonChannelNum);
                newBrainNodeList.Add(clonedNode);
                nextNodeIndexID++;
            }
        }        
        
        for (int i = 0; i < newBrainNodeList.Count; i++) {
            afterBrain += "Node " + newBrainNodeList[i].id.ToString() + " (" + newBrainNodeList[i].sourceAddonInno.ToString() + ", " + newBrainNodeList[i].sourceAddonRecursionNum.ToString() + ", " + newBrainNodeList[i].sourceAddonChannelNum.ToString() + ")\n";
        }
        // Once complete, replace oldNodeList with the new one:
        nodeNEATList = newBrainNodeList;
        //linkNEATList = newBrainLinkList;

        // Make sure that there aren't any links pointing to non-existent nodes:
        for (int i = 0; i < linkNEATList.Count; i++) {
            bool linkSevered = false;
            if (GetNodeIndexFromInt3(linkNEATList[i].fromNodeID) == -1) {
                linkSevered = true;
            }
            if (GetNodeIndexFromInt3(linkNEATList[i].toNodeID) == -1) {
                linkSevered = true;
            }

            if (linkSevered) {
                linkNEATList[i].enabled = false;
                //Debug.Log("LINK " + i.ToString() + " SEVERED!! " + linkNEATList[i].fromNodeID.ToString() + ", " + linkNEATList[i].toNodeID.ToString());
            }
        }

        //Debug.Log(beforeBrain);
        //Debug.Log(afterBrain + "\n deltaNodes: " + netNewNodes.ToString());
    }
    public void Prime(CritterGenome sourceGenome) {
        textHeader.text = sourceAddonType.ToString() + " [" + addonInno.ToString() + "]";

        if(sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.PhysicalAttributes) {
            AddonPhysicalAttributes physicalAttributes = sourceGenome.addonPhysicalAttributesList[sourceAddonIndex];

            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();            
            floatDisplay1.textFloatName.text = "Dynamic Friction:";            
            floatDisplay1.sliderFloat.minValue = 0f;
            floatDisplay1.sliderFloat.maxValue = 1f;            
            floatDisplay1.linkedFloatValue[0] = physicalAttributes.dynamicFriction[0];
            physicalAttributes.dynamicFriction = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = physicalAttributes.dynamicFriction[0];
            floatDisplay1.textFloatValue.text = physicalAttributes.dynamicFriction[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject floatDisplay2GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay2 = floatDisplay2GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay2.textFloatName.text = "Static Friction:";
            floatDisplay2.sliderFloat.minValue = 0f;
            floatDisplay2.sliderFloat.maxValue = 1f;
            floatDisplay2.linkedFloatValue[0] = physicalAttributes.staticFriction[0];
            physicalAttributes.staticFriction = floatDisplay2.linkedFloatValue;
            floatDisplay2.sliderFloat.value = physicalAttributes.staticFriction[0];
            floatDisplay2.textFloatValue.text = physicalAttributes.staticFriction[0].ToString();
            floatDisplay2GO.transform.SetParent(this.transform);

            GameObject floatDisplay3GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay3 = floatDisplay3GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay3.textFloatName.text = "Bounciness:";
            floatDisplay3.sliderFloat.minValue = 0f;
            floatDisplay3.sliderFloat.maxValue = 1f;
            floatDisplay3.linkedFloatValue[0] = physicalAttributes.bounciness[0];
            physicalAttributes.bounciness = floatDisplay3.linkedFloatValue;
            floatDisplay3.sliderFloat.value = physicalAttributes.bounciness[0];
            floatDisplay3.textFloatValue.text = physicalAttributes.bounciness[0].ToString();
            floatDisplay3GO.transform.SetParent(this.transform);

            GameObject boolDisplay1GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay1 = boolDisplay1GO.GetComponent<PanelAddonDisplayBool>();
            boolDisplay1.textBoolName.text = "Freeze Position X:";
            boolDisplay1.linkedBoolValue[0] = physicalAttributes.freezePositionX[0];
            physicalAttributes.freezePositionX = boolDisplay1.linkedBoolValue;
            boolDisplay1.toggleBool.isOn = physicalAttributes.freezePositionX[0];
            boolDisplay1GO.transform.SetParent(this.transform);

            GameObject boolDisplay2GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay2 = boolDisplay2GO.GetComponent<PanelAddonDisplayBool>();
            boolDisplay2.textBoolName.text = "Freeze Position Y:";
            boolDisplay2.linkedBoolValue[0] = physicalAttributes.freezePositionY[0];
            physicalAttributes.freezePositionY = boolDisplay2.linkedBoolValue;
            boolDisplay2.toggleBool.isOn = physicalAttributes.freezePositionY[0];
            boolDisplay2GO.transform.SetParent(this.transform);

            GameObject boolDisplay3GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay3 = boolDisplay3GO.GetComponent<PanelAddonDisplayBool>();
            boolDisplay3.textBoolName.text = "Freeze Position Z:";
            boolDisplay3.linkedBoolValue[0] = physicalAttributes.freezePositionZ[0];
            physicalAttributes.freezePositionZ = boolDisplay3.linkedBoolValue;
            boolDisplay3.toggleBool.isOn = physicalAttributes.freezePositionZ[0];
            boolDisplay3GO.transform.SetParent(this.transform);

            GameObject boolDisplay4GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay4 = boolDisplay4GO.GetComponent<PanelAddonDisplayBool>();
            boolDisplay4.textBoolName.text = "Freeze Rotation X:";
            boolDisplay4.linkedBoolValue[0] = physicalAttributes.freezeRotationX[0];
            physicalAttributes.freezeRotationX = boolDisplay4.linkedBoolValue;
            boolDisplay4.toggleBool.isOn = physicalAttributes.freezeRotationX[0];
            boolDisplay4GO.transform.SetParent(this.transform);

            GameObject boolDisplay5GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay5 = boolDisplay5GO.GetComponent<PanelAddonDisplayBool>();
            boolDisplay5.textBoolName.text = "Freeze Rotation Y:";
            boolDisplay5.linkedBoolValue[0] = physicalAttributes.freezeRotationY[0];
            physicalAttributes.freezeRotationY = boolDisplay5.linkedBoolValue;
            boolDisplay5.toggleBool.isOn = physicalAttributes.freezeRotationY[0];
            boolDisplay5GO.transform.SetParent(this.transform);

            GameObject boolDisplay6GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay6 = boolDisplay6GO.GetComponent<PanelAddonDisplayBool>();
            boolDisplay6.textBoolName.text = "Freeze Rotation Z:";
            boolDisplay6.linkedBoolValue[0] = physicalAttributes.freezeRotationZ[0];
            physicalAttributes.freezeRotationZ = boolDisplay6.linkedBoolValue;
            boolDisplay6.toggleBool.isOn = physicalAttributes.freezeRotationZ[0];
            boolDisplay6GO.transform.SetParent(this.transform);
        }

        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.JointAngleSensor) {
            AddonJointAngleSensor jointAngleSensor = sourceGenome.addonJointAngleSensorList[sourceAddonIndex];
            GameObject floatDisplayGO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay = floatDisplayGO.GetComponent<PanelAddonDisplayFloat>();

            floatDisplay.textFloatName.text = "Angle Sensitivity:";
            floatDisplay.sliderFloat.minValue = 0.01f;
            floatDisplay.sliderFloat.maxValue = 2f;
            floatDisplay.linkedFloatValue[0] = jointAngleSensor.sensitivity[0];
            jointAngleSensor.sensitivity = floatDisplay.linkedFloatValue;
            floatDisplay.sliderFloat.value = jointAngleSensor.sensitivity[0];
            floatDisplay.textFloatValue.text = jointAngleSensor.sensitivity[0].ToString();

            GameObject boolDisplay1GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay1 = boolDisplay1GO.GetComponent<PanelAddonDisplayBool>();
            boolDisplay1.textBoolName.text = "Measure Vel:";
            boolDisplay1.linkedBoolValue[0] = jointAngleSensor.measureVel[0];
            jointAngleSensor.measureVel = boolDisplay1.linkedBoolValue;
            boolDisplay1.toggleBool.isOn = jointAngleSensor.measureVel[0];
            boolDisplay1GO.transform.SetParent(this.transform);

            floatDisplayGO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.ContactSensor) {
            AddonContactSensor contactSensor = sourceGenome.addonContactSensorList[sourceAddonIndex];
            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.05f;
            floatDisplay1.sliderFloat.maxValue = 20f;
            floatDisplay1.linkedFloatValue[0] = contactSensor.contactSensitivity[0];
            contactSensor.contactSensitivity = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = contactSensor.contactSensitivity[0];
            floatDisplay1.textFloatValue.text = contactSensor.contactSensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.RaycastSensor) {
            AddonRaycastSensor raycastSensor = sourceGenome.addonRaycastSensorList[sourceAddonIndex];
            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Max Distance:";
            floatDisplay1.sliderFloat.minValue = 0.1f;
            floatDisplay1.sliderFloat.maxValue = 25f;
            floatDisplay1.linkedFloatValue[0] = raycastSensor.maxDistance[0];
            raycastSensor.maxDistance = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = raycastSensor.maxDistance[0];
            floatDisplay1.textFloatValue.text = raycastSensor.maxDistance[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject vector3DisplayGO = (GameObject)Instantiate(vector3DisplayPrefab);
            PanelAddonDisplayVector3 vector3Display = vector3DisplayGO.GetComponent<PanelAddonDisplayVector3>();
            vector3Display.textVector3Name.text = "Forward Vector:";
            vector3Display.sliderX.minValue = -1f;
            vector3Display.sliderX.maxValue = 1f;
            vector3Display.sliderX.value = raycastSensor.forwardVector[0].x;
            vector3Display.textXValue.text = raycastSensor.forwardVector[0].x.ToString();
            vector3Display.sliderY.minValue = -1f;
            vector3Display.sliderY.maxValue = 1f;
            vector3Display.sliderY.value = raycastSensor.forwardVector[0].y;
            vector3Display.textYValue.text = raycastSensor.forwardVector[0].y.ToString();
            vector3Display.sliderZ.minValue = -1f;
            vector3Display.sliderZ.maxValue = 1f;
            vector3Display.sliderZ.value = raycastSensor.forwardVector[0].z;
            vector3Display.textZValue.text = raycastSensor.forwardVector[0].z.ToString();
            vector3Display.linkedVector3Value[0] = raycastSensor.forwardVector[0];
            raycastSensor.forwardVector = vector3Display.linkedVector3Value;
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.CompassSensor1D) {
            AddonCompassSensor1D compassSensor1D = sourceGenome.addonCompassSensor1DList[sourceAddonIndex];

            GameObject vector3DisplayGO = (GameObject)Instantiate(vector3DisplayPrefab);
            PanelAddonDisplayVector3 vector3Display = vector3DisplayGO.GetComponent<PanelAddonDisplayVector3>();
            vector3Display.textVector3Name.text = "Forward Vector:";
            vector3Display.sliderX.minValue = -1f;
            vector3Display.sliderX.maxValue = 1f;
            vector3Display.sliderX.value = compassSensor1D.forwardVector[0].x;
            vector3Display.textXValue.text = compassSensor1D.forwardVector[0].x.ToString();
            vector3Display.sliderY.minValue = -1f;
            vector3Display.sliderY.maxValue = 1f;
            vector3Display.sliderY.value = compassSensor1D.forwardVector[0].y;
            vector3Display.textYValue.text = compassSensor1D.forwardVector[0].y.ToString();
            vector3Display.sliderZ.minValue = -1f;
            vector3Display.sliderZ.maxValue = 1f;
            vector3Display.sliderZ.value = compassSensor1D.forwardVector[0].z;
            vector3Display.textZValue.text = compassSensor1D.forwardVector[0].z.ToString();
            vector3Display.linkedVector3Value[0] = compassSensor1D.forwardVector[0];
            compassSensor1D.forwardVector = vector3Display.linkedVector3Value;

            vector3DisplayGO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.CompassSensor3D) {
            AddonCompassSensor3D compassSensor3D = sourceGenome.addonCompassSensor3DList[sourceAddonIndex];            
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.PositionSensor1D) {
            AddonPositionSensor1D positionSensor1D = sourceGenome.addonPositionSensor1DList[sourceAddonIndex];

            GameObject vector3DisplayGO = (GameObject)Instantiate(vector3DisplayPrefab);
            PanelAddonDisplayVector3 vector3Display = vector3DisplayGO.GetComponent<PanelAddonDisplayVector3>();
            vector3Display.textVector3Name.text = "Forward Vector:";
            vector3Display.sliderX.minValue = -1f;
            vector3Display.sliderX.maxValue = 1f;
            vector3Display.sliderX.value = positionSensor1D.forwardVector[0].x;
            vector3Display.textXValue.text = positionSensor1D.forwardVector[0].x.ToString();
            vector3Display.sliderY.minValue = -1f;
            vector3Display.sliderY.maxValue = 1f;
            vector3Display.sliderY.value = positionSensor1D.forwardVector[0].y;
            vector3Display.textYValue.text = positionSensor1D.forwardVector[0].y.ToString();
            vector3Display.sliderZ.minValue = -1f;
            vector3Display.sliderZ.maxValue = 1f;
            vector3Display.sliderZ.value = positionSensor1D.forwardVector[0].z;
            vector3Display.textZValue.text = positionSensor1D.forwardVector[0].z.ToString();
            vector3Display.linkedVector3Value[0] = positionSensor1D.forwardVector[0];
            positionSensor1D.forwardVector = vector3Display.linkedVector3Value;
            vector3DisplayGO.transform.SetParent(this.transform);

            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.01f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0] = positionSensor1D.sensitivity[0];
            positionSensor1D.sensitivity = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = positionSensor1D.sensitivity[0];
            floatDisplay1.textFloatValue.text = positionSensor1D.sensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject boolDisplay1GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay1 = boolDisplay1GO.GetComponent<PanelAddonDisplayBool>();
            boolDisplay1.textBoolName.text = "Relative:";
            boolDisplay1.linkedBoolValue[0] = positionSensor1D.relative[0];
            positionSensor1D.relative = boolDisplay1.linkedBoolValue;
            boolDisplay1.toggleBool.isOn = positionSensor1D.relative[0];
            boolDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.PositionSensor3D) {
            AddonPositionSensor3D positionSensor3D = sourceGenome.addonPositionSensor3DList[sourceAddonIndex];

            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.01f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0] = positionSensor3D.sensitivity[0];
            positionSensor3D.sensitivity = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = positionSensor3D.sensitivity[0];
            floatDisplay1.textFloatValue.text = positionSensor3D.sensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject boolDisplay1GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay1 = boolDisplay1GO.GetComponent<PanelAddonDisplayBool>();
            boolDisplay1.textBoolName.text = "Relative:";
            boolDisplay1.linkedBoolValue[0] = positionSensor3D.relative[0];
            positionSensor3D.relative = boolDisplay1.linkedBoolValue;
            boolDisplay1.toggleBool.isOn = positionSensor3D.relative[0];
            boolDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.RotationSensor1D) {
            AddonRotationSensor1D rotationSensor1D = sourceGenome.addonRotationSensor1DList[sourceAddonIndex];

            GameObject vector3DisplayGO = (GameObject)Instantiate(vector3DisplayPrefab);
            PanelAddonDisplayVector3 vector3Display = vector3DisplayGO.GetComponent<PanelAddonDisplayVector3>();
            vector3Display.textVector3Name.text = "Local Axis:";
            vector3Display.sliderX.minValue = -1f;
            vector3Display.sliderX.maxValue = 1f;
            vector3Display.sliderX.value = rotationSensor1D.localAxis[0].x;
            vector3Display.textXValue.text = rotationSensor1D.localAxis[0].x.ToString();
            vector3Display.sliderY.minValue = -1f;
            vector3Display.sliderY.maxValue = 1f;
            vector3Display.sliderY.value = rotationSensor1D.localAxis[0].y;
            vector3Display.textYValue.text = rotationSensor1D.localAxis[0].y.ToString();
            vector3Display.sliderZ.minValue = -1f;
            vector3Display.sliderZ.maxValue = 1f;
            vector3Display.sliderZ.value = rotationSensor1D.localAxis[0].z;
            vector3Display.textZValue.text = rotationSensor1D.localAxis[0].z.ToString();
            vector3Display.linkedVector3Value[0] = rotationSensor1D.localAxis[0];
            rotationSensor1D.localAxis = vector3Display.linkedVector3Value;
            vector3DisplayGO.transform.SetParent(this.transform);

            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.01f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0] = rotationSensor1D.sensitivity[0];
            rotationSensor1D.sensitivity = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = rotationSensor1D.sensitivity[0];
            floatDisplay1.textFloatValue.text = rotationSensor1D.sensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.RotationSensor3D) {
            AddonRotationSensor3D rotationSensor3D = sourceGenome.addonRotationSensor3DList[sourceAddonIndex];

            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.01f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0] = rotationSensor3D.sensitivity[0];
            rotationSensor3D.sensitivity = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = rotationSensor3D.sensitivity[0];
            floatDisplay1.textFloatValue.text = rotationSensor3D.sensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.VelocitySensor1D) {
            AddonVelocitySensor1D velocitySensor1D = sourceGenome.addonVelocitySensor1DList[sourceAddonIndex];

            GameObject vector3DisplayGO = (GameObject)Instantiate(vector3DisplayPrefab);
            PanelAddonDisplayVector3 vector3Display = vector3DisplayGO.GetComponent<PanelAddonDisplayVector3>();
            vector3Display.textVector3Name.text = "Forward Vector:";
            vector3Display.sliderX.minValue = -1f;
            vector3Display.sliderX.maxValue = 1f;
            vector3Display.sliderX.value = velocitySensor1D.forwardVector[0].x;
            vector3Display.textXValue.text = velocitySensor1D.forwardVector[0].x.ToString();
            vector3Display.sliderY.minValue = -1f;
            vector3Display.sliderY.maxValue = 1f;
            vector3Display.sliderY.value = velocitySensor1D.forwardVector[0].y;
            vector3Display.textYValue.text = velocitySensor1D.forwardVector[0].y.ToString();
            vector3Display.sliderZ.minValue = -1f;
            vector3Display.sliderZ.maxValue = 1f;
            vector3Display.sliderZ.value = velocitySensor1D.forwardVector[0].z;
            vector3Display.textZValue.text = velocitySensor1D.forwardVector[0].z.ToString();
            vector3Display.linkedVector3Value[0] = velocitySensor1D.forwardVector[0];
            velocitySensor1D.forwardVector = vector3Display.linkedVector3Value;
            vector3DisplayGO.transform.SetParent(this.transform);

            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.01f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0] = velocitySensor1D.sensitivity[0];
            velocitySensor1D.sensitivity = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = velocitySensor1D.sensitivity[0];
            floatDisplay1.textFloatValue.text = velocitySensor1D.sensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject boolDisplay1GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay1 = boolDisplay1GO.GetComponent<PanelAddonDisplayBool>();
            boolDisplay1.textBoolName.text = "Relative:";
            boolDisplay1.linkedBoolValue[0] = velocitySensor1D.relative[0];
            velocitySensor1D.relative = boolDisplay1.linkedBoolValue;
            boolDisplay1.toggleBool.isOn = velocitySensor1D.relative[0];
            boolDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.VelocitySensor3D) {
            AddonVelocitySensor3D velocitySensor3D = sourceGenome.addonVelocitySensor3DList[sourceAddonIndex];

            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.01f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0] = velocitySensor3D.sensitivity[0];
            velocitySensor3D.sensitivity = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = velocitySensor3D.sensitivity[0];
            floatDisplay1.textFloatValue.text = velocitySensor3D.sensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject boolDisplay1GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay1 = boolDisplay1GO.GetComponent<PanelAddonDisplayBool>();
            boolDisplay1.textBoolName.text = "Relative:";
            boolDisplay1.linkedBoolValue[0] = velocitySensor3D.relative[0];
            velocitySensor3D.relative = boolDisplay1.linkedBoolValue;
            boolDisplay1.toggleBool.isOn = velocitySensor3D.relative[0];
            boolDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.Altimeter) {
            AddonAltimeter altimeter = sourceGenome.addonAltimeterList[sourceAddonIndex];
        }
        else if(sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.EarBasic) {
            AddonEarBasic earBasic = sourceGenome.addonEarBasicList[sourceAddonIndex];

            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.01f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0] = earBasic.sensitivity[0];
            earBasic.sensitivity = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = earBasic.sensitivity[0];
            floatDisplay1.textFloatValue.text = earBasic.sensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.Gravity) {
            AddonGravitySensor gravitySensor = sourceGenome.addonGravitySensorList[sourceAddonIndex];
        }

        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.JointMotor) {
            AddonJointMotor jointMotor = sourceGenome.addonJointMotorList[sourceAddonIndex];
            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Motor Force:";
            floatDisplay1.sliderFloat.minValue = 1f;
            floatDisplay1.sliderFloat.maxValue = 500f;
            floatDisplay1.linkedFloatValue[0] = jointMotor.motorForce[0];
            jointMotor.motorForce = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = jointMotor.motorForce[0];
            floatDisplay1.textFloatValue.text = jointMotor.motorForce[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject floatDisplay2GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay2 = floatDisplay2GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay2.textFloatName.text = "Motor Speed:";
            floatDisplay2.sliderFloat.minValue = 1f;
            floatDisplay2.sliderFloat.maxValue = 500f;
            floatDisplay2.linkedFloatValue[0] = jointMotor.motorSpeed[0];
            jointMotor.motorSpeed = floatDisplay2.linkedFloatValue;
            floatDisplay2.sliderFloat.value = jointMotor.motorSpeed[0];
            floatDisplay2.textFloatValue.text = jointMotor.motorSpeed[0].ToString();
            floatDisplay2GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.ThrusterEffector1D) {
            AddonThrusterEffector1D thrusterEffector1D = sourceGenome.addonThrusterEffector1DList[sourceAddonIndex];

            GameObject vector3DisplayGO = (GameObject)Instantiate(vector3DisplayPrefab);
            PanelAddonDisplayVector3 vector3Display = vector3DisplayGO.GetComponent<PanelAddonDisplayVector3>();
            vector3Display.textVector3Name.text = "Forward Vector:";
            vector3Display.sliderX.minValue = -1f;
            vector3Display.sliderX.maxValue = 1f;
            vector3Display.sliderX.value = thrusterEffector1D.forwardVector[0].x;
            vector3Display.textXValue.text = thrusterEffector1D.forwardVector[0].x.ToString();
            vector3Display.sliderY.minValue = -1f;
            vector3Display.sliderY.maxValue = 1f;
            vector3Display.sliderY.value = thrusterEffector1D.forwardVector[0].y;
            vector3Display.textYValue.text = thrusterEffector1D.forwardVector[0].y.ToString();
            vector3Display.sliderZ.minValue = -1f;
            vector3Display.sliderZ.maxValue = 1f;
            vector3Display.sliderZ.value = thrusterEffector1D.forwardVector[0].z;
            vector3Display.textZValue.text = thrusterEffector1D.forwardVector[0].z.ToString();
            vector3Display.linkedVector3Value[0] = thrusterEffector1D.forwardVector[0];
            thrusterEffector1D.forwardVector = vector3Display.linkedVector3Value;
            vector3DisplayGO.transform.SetParent(this.transform);

            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Max Force:";
            floatDisplay1.sliderFloat.minValue = 0.1f;
            floatDisplay1.sliderFloat.maxValue = 100f;
            floatDisplay1.linkedFloatValue[0] = thrusterEffector1D.maxForce[0];
            thrusterEffector1D.maxForce = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = thrusterEffector1D.maxForce[0];
            floatDisplay1.textFloatValue.text = thrusterEffector1D.maxForce[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.ThrusterEffector3D) {
            AddonThrusterEffector3D thrusterEffector3D = sourceGenome.addonThrusterEffector3DList[sourceAddonIndex];

            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Max Force:";
            floatDisplay1.sliderFloat.minValue = 0.1f;
            floatDisplay1.sliderFloat.maxValue = 100f;
            floatDisplay1.linkedFloatValue[0] = thrusterEffector3D.maxForce[0];
            thrusterEffector3D.maxForce = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = thrusterEffector3D.maxForce[0];
            floatDisplay1.textFloatValue.text = thrusterEffector3D.maxForce[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.TorqueEffector1D) {
            AddonTorqueEffector1D torqueEffector1D = sourceGenome.addonTorqueEffector1DList[sourceAddonIndex];

            GameObject vector3DisplayGO = (GameObject)Instantiate(vector3DisplayPrefab);
            PanelAddonDisplayVector3 vector3Display = vector3DisplayGO.GetComponent<PanelAddonDisplayVector3>();
            vector3Display.textVector3Name.text = "Axis:";
            vector3Display.sliderX.minValue = -1f;
            vector3Display.sliderX.maxValue = 1f;
            vector3Display.sliderX.value = torqueEffector1D.axis[0].x;
            vector3Display.textXValue.text = torqueEffector1D.axis[0].x.ToString();
            vector3Display.sliderY.minValue = -1f;
            vector3Display.sliderY.maxValue = 1f;
            vector3Display.sliderY.value = torqueEffector1D.axis[0].y;
            vector3Display.textYValue.text = torqueEffector1D.axis[0].y.ToString();
            vector3Display.sliderZ.minValue = -1f;
            vector3Display.sliderZ.maxValue = 1f;
            vector3Display.sliderZ.value = torqueEffector1D.axis[0].z;
            vector3Display.textZValue.text = torqueEffector1D.axis[0].z.ToString();
            vector3Display.linkedVector3Value[0] = torqueEffector1D.axis[0];
            torqueEffector1D.axis = vector3Display.linkedVector3Value;
            vector3DisplayGO.transform.SetParent(this.transform);

            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Max Torque:";
            floatDisplay1.sliderFloat.minValue = 0.1f;
            floatDisplay1.sliderFloat.maxValue = 100f;
            floatDisplay1.linkedFloatValue[0] = torqueEffector1D.maxTorque[0];
            torqueEffector1D.maxTorque = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = torqueEffector1D.maxTorque[0];
            floatDisplay1.textFloatValue.text = torqueEffector1D.maxTorque[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.TorqueEffector3D) {
            AddonTorqueEffector3D torqueEffector3D = sourceGenome.addonTorqueEffector3DList[sourceAddonIndex];

            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Max Torque:";
            floatDisplay1.sliderFloat.minValue = 0.1f;
            floatDisplay1.sliderFloat.maxValue = 100f;
            floatDisplay1.linkedFloatValue[0] = torqueEffector3D.maxTorque[0];
            torqueEffector3D.maxTorque = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = torqueEffector3D.maxTorque[0];
            floatDisplay1.textFloatValue.text = torqueEffector3D.maxTorque[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.MouthBasic) {
            AddonMouthBasic mouthBasic = sourceGenome.addonMouthBasicList[sourceAddonIndex];
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.NoiseMakerBasic) {
            AddonNoiseMakerBasic noiseMakerBasic = sourceGenome.addonNoiseMakerBasicList[sourceAddonIndex];

            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Amplitude:";
            floatDisplay1.sliderFloat.minValue = 0.1f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0] = noiseMakerBasic.amplitude[0];
            noiseMakerBasic.amplitude = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = noiseMakerBasic.amplitude[0];
            floatDisplay1.textFloatValue.text = noiseMakerBasic.amplitude[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.Sticky) {
            AddonSticky sticky = sourceGenome.addonStickyList[sourceAddonIndex];
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.WeaponBasic) {
            AddonWeaponBasic weaponBasic = sourceGenome.addonWeaponBasicList[sourceAddonIndex];

            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Strength:";
            floatDisplay1.sliderFloat.minValue = 0.1f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0] = weaponBasic.strength[0];
            weaponBasic.strength = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = weaponBasic.strength[0];
            floatDisplay1.textFloatValue.text = weaponBasic.strength[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }

        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.OscillatorInput) {
            AddonOscillatorInput oscillatorInput = sourceGenome.addonOscillatorInputList[sourceAddonIndex];
            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Frequency:";
            floatDisplay1.sliderFloat.minValue = 0.05f;
            floatDisplay1.sliderFloat.maxValue = 20f;
            floatDisplay1.linkedFloatValue[0] = oscillatorInput.frequency[0];
            oscillatorInput.frequency = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = oscillatorInput.frequency[0];
            floatDisplay1.textFloatValue.text = oscillatorInput.frequency[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject floatDisplay2GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay2 = floatDisplay2GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay2.textFloatName.text = "Amplitude:";
            floatDisplay2.sliderFloat.minValue = 0.05f;
            floatDisplay2.sliderFloat.maxValue = 20f;
            floatDisplay2.linkedFloatValue[0] = oscillatorInput.amplitude[0];
            oscillatorInput.amplitude = floatDisplay2.linkedFloatValue;
            floatDisplay2.sliderFloat.value = oscillatorInput.amplitude[0];
            floatDisplay2.textFloatValue.text = oscillatorInput.amplitude[0].ToString();
            floatDisplay2GO.transform.SetParent(this.transform);

            GameObject floatDisplay3GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay3 = floatDisplay3GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay3.textFloatName.text = "Offset:";
            floatDisplay3.sliderFloat.minValue = -20f;
            floatDisplay3.sliderFloat.maxValue = 20f;
            floatDisplay3.linkedFloatValue[0] = oscillatorInput.offset[0];
            oscillatorInput.offset = floatDisplay3.linkedFloatValue;
            floatDisplay3.sliderFloat.value = oscillatorInput.offset[0];
            floatDisplay3.textFloatValue.text = oscillatorInput.offset[0].ToString();
            floatDisplay3GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.ValueInput) {
            AddonValueInput valueInput = sourceGenome.addonValueInputList[sourceAddonIndex];
            GameObject floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1 = floatDisplay1GO.GetComponent<PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text = "Value:";
            floatDisplay1.sliderFloat.minValue = -5f;
            floatDisplay1.sliderFloat.maxValue = 5f;
            floatDisplay1.linkedFloatValue[0] = valueInput.value[0];
            valueInput.value = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value = valueInput.value[0];
            floatDisplay1.textFloatValue.text = valueInput.value[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.TimerInput) {
            AddonTimerInput timerInput = sourceGenome.addonTimerInputList[sourceAddonIndex];
        }

    }
示例#19
0
    public void RepopulateList(CritterGenome sourceGenome, int nodeID)
    {
        var children = new List <GameObject>();

        foreach (Transform child in this.gameObject.transform)
        {
            children.Add(child.gameObject);
        }
        children.ForEach(child => Destroy(child));

        int addonDisplayIndex = 0;

        // Go through all the Addon lists and check if there are any addons for the current NodeID:

        // Physical Attributes:
        for (int physicalAttributesIndex = 0; physicalAttributesIndex < sourceGenome.addonPhysicalAttributesList.Count; physicalAttributesIndex++)
        {
            if (sourceGenome.addonPhysicalAttributesList[physicalAttributesIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonPhysicalAttributesList[physicalAttributesIndex].innov;
                addonDisplayIndex++;
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.PhysicalAttributes;
                itemDisplay.sourceAddonIndex = physicalAttributesIndex;
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }

        // Joint Angle Sensors:
        for (int jointAngleSensorIndex = 0; jointAngleSensorIndex < sourceGenome.addonJointAngleSensorList.Count; jointAngleSensorIndex++)
        {
            //Debug.Log("jointAngleSensorIndex Addon# " + jointAngleSensorIndex.ToString() + ", ");
            // Check if this node contains a jointAngleSensor Add-on:
            if (sourceGenome.addonJointAngleSensorList[jointAngleSensorIndex].critterNodeID == nodeID)
            {
                //Debug.Log("FOUND JOINTAngleSensor! " + jointAngleSensorIndex.ToString() + ", nodeID: " + nodeID.ToString());
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonJointAngleSensorList[jointAngleSensorIndex].innov;
                addonDisplayIndex++;                                                                        // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.JointAngleSensor; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = jointAngleSensorIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Contact Sensors:
        for (int contactSensorIndex = 0; contactSensorIndex < sourceGenome.addonContactSensorList.Count; contactSensorIndex++)
        {
            if (sourceGenome.addonContactSensorList[contactSensorIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonContactSensorList[contactSensorIndex].innov;
                addonDisplayIndex++;                                                                     // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.ContactSensor; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = contactSensorIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Raycast Sensors:
        for (int raycastSensorIndex = 0; raycastSensorIndex < sourceGenome.addonRaycastSensorList.Count; raycastSensorIndex++)
        {
            if (sourceGenome.addonRaycastSensorList[raycastSensorIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonRaycastSensorList[raycastSensorIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.RaycastSensor;
                itemDisplay.sourceAddonIndex = raycastSensorIndex;
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Compass Sensor 1D's:
        for (int compassSensor1DIndex = 0; compassSensor1DIndex < sourceGenome.addonCompassSensor1DList.Count; compassSensor1DIndex++)
        {
            if (sourceGenome.addonCompassSensor1DList[compassSensor1DIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonCompassSensor1DList[compassSensor1DIndex].innov;
                addonDisplayIndex++;                                                                       // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.CompassSensor1D; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = compassSensor1DIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Compass Sensor 3D's:
        for (int compassSensor3DIndex = 0; compassSensor3DIndex < sourceGenome.addonCompassSensor3DList.Count; compassSensor3DIndex++)
        {
            //Debug.Log("CompassSensor3D Addon# " + compassSensor3DIndex.ToString() + ", ");
            // Check if this node contains a CompassSensor1D Add-on:
            if (sourceGenome.addonCompassSensor3DList[compassSensor3DIndex].critterNodeID == nodeID)
            {
                //Debug.Log("FOUND CompassSensor3D! " + compassSensor3DIndex.ToString() + ", nodeID: " + nodeID.ToString());
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonCompassSensor3DList[compassSensor3DIndex].innov;
                addonDisplayIndex++;                                                                       // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.CompassSensor3D; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = compassSensor3DIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Position Sensor 1D's:
        for (int positionSensor1DIndex = 0; positionSensor1DIndex < sourceGenome.addonPositionSensor1DList.Count; positionSensor1DIndex++)
        {
            if (sourceGenome.addonPositionSensor1DList[positionSensor1DIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonPositionSensor1DList[positionSensor1DIndex].innov;
                addonDisplayIndex++;                                                                        // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.PositionSensor1D; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = positionSensor1DIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Position Sensor 3D's:
        for (int positionSensor3DIndex = 0; positionSensor3DIndex < sourceGenome.addonPositionSensor3DList.Count; positionSensor3DIndex++)
        {
            if (sourceGenome.addonPositionSensor3DList[positionSensor3DIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonPositionSensor3DList[positionSensor3DIndex].innov;
                addonDisplayIndex++;                                                                        // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.PositionSensor3D; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = positionSensor3DIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Rotation Sensor 1D's:
        for (int rotationSensor1DIndex = 0; rotationSensor1DIndex < sourceGenome.addonRotationSensor1DList.Count; rotationSensor1DIndex++)
        {
            if (sourceGenome.addonRotationSensor1DList[rotationSensor1DIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonRotationSensor1DList[rotationSensor1DIndex].innov;
                addonDisplayIndex++;                                                                        // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.RotationSensor1D; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = rotationSensor1DIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Rotation Sensor 3D's:
        for (int rotationSensor3DIndex = 0; rotationSensor3DIndex < sourceGenome.addonRotationSensor3DList.Count; rotationSensor3DIndex++)
        {
            if (sourceGenome.addonRotationSensor3DList[rotationSensor3DIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonRotationSensor3DList[rotationSensor3DIndex].innov;
                addonDisplayIndex++;                                                                        // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.RotationSensor3D; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = rotationSensor3DIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Velocity Sensor 1D's:
        for (int velocitySensor1DIndex = 0; velocitySensor1DIndex < sourceGenome.addonVelocitySensor1DList.Count; velocitySensor1DIndex++)
        {
            if (sourceGenome.addonVelocitySensor1DList[velocitySensor1DIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonVelocitySensor1DList[velocitySensor1DIndex].innov;
                addonDisplayIndex++;                                                                        // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.VelocitySensor1D; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = velocitySensor1DIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Velocity Sensor 3D's:
        for (int velocitySensor3DIndex = 0; velocitySensor3DIndex < sourceGenome.addonVelocitySensor3DList.Count; velocitySensor3DIndex++)
        {
            if (sourceGenome.addonVelocitySensor3DList[velocitySensor3DIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonVelocitySensor3DList[velocitySensor3DIndex].innov;
                addonDisplayIndex++;                                                                        // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.VelocitySensor3D; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = velocitySensor3DIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Altimeters:
        for (int altimeterIndex = 0; altimeterIndex < sourceGenome.addonAltimeterList.Count; altimeterIndex++)
        {
            if (sourceGenome.addonAltimeterList[altimeterIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonAltimeterList[altimeterIndex].innov;
                addonDisplayIndex++;                                                                 // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.Altimeter; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = altimeterIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // EarBasic:
        for (int earBasicIndex = 0; earBasicIndex < sourceGenome.addonEarBasicList.Count; earBasicIndex++)
        {
            if (sourceGenome.addonEarBasicList[earBasicIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonEarBasicList[earBasicIndex].innov;
                addonDisplayIndex++;                                                                // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.EarBasic; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = earBasicIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // GravitySensor:
        for (int gravitySensorIndex = 0; gravitySensorIndex < sourceGenome.addonGravitySensorList.Count; gravitySensorIndex++)
        {
            if (sourceGenome.addonGravitySensorList[gravitySensorIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonGravitySensorList[gravitySensorIndex].innov;
                addonDisplayIndex++;                                                               // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.Gravity; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = gravitySensorIndex;                                 // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }

        // Joint Motors:
        for (int jointMotorIndex = 0; jointMotorIndex < sourceGenome.addonJointMotorList.Count; jointMotorIndex++)
        {
            //Debug.Log("jointMotor Addon# " + jointMotorIndex.ToString() + ", ");
            // Check if this node contains a jointMotor Add-on:
            if (sourceGenome.addonJointMotorList[jointMotorIndex].critterNodeID == nodeID)
            {
                //Debug.Log("FOUND JOINTMOTOR! " + jointMotorIndex.ToString() + ", nodeID: " + nodeID.ToString());
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonJointMotorList[jointMotorIndex].innov;
                addonDisplayIndex++;                                                                  // keeps track of position of this itemDisplay within the UI display addon List
                //itemDisplay.sourceAddon = sourceNode.addonsList[jointMotorIndex];
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.JointMotor; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = jointMotorIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.

                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Thruster Effector 1D's:
        for (int thrusterEffector1DIndex = 0; thrusterEffector1DIndex < sourceGenome.addonThrusterEffector1DList.Count; thrusterEffector1DIndex++)
        {
            if (sourceGenome.addonThrusterEffector1DList[thrusterEffector1DIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonThrusterEffector1DList[thrusterEffector1DIndex].innov;
                addonDisplayIndex++;
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.ThrusterEffector1D;
                itemDisplay.sourceAddonIndex = thrusterEffector1DIndex;
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Thruster Effector 3D's:
        for (int thrusterEffector3DIndex = 0; thrusterEffector3DIndex < sourceGenome.addonThrusterEffector3DList.Count; thrusterEffector3DIndex++)
        {
            if (sourceGenome.addonThrusterEffector3DList[thrusterEffector3DIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonThrusterEffector3DList[thrusterEffector3DIndex].innov;
                addonDisplayIndex++;
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.ThrusterEffector3D;
                itemDisplay.sourceAddonIndex = thrusterEffector3DIndex;
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Torque Effector 1D's:
        for (int torqueEffector1DIndex = 0; torqueEffector1DIndex < sourceGenome.addonTorqueEffector1DList.Count; torqueEffector1DIndex++)
        {
            if (sourceGenome.addonTorqueEffector1DList[torqueEffector1DIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonTorqueEffector1DList[torqueEffector1DIndex].innov;
                addonDisplayIndex++;
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.TorqueEffector1D;
                itemDisplay.sourceAddonIndex = torqueEffector1DIndex;
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Torque Effector 3D's:
        for (int torqueEffector3DIndex = 0; torqueEffector3DIndex < sourceGenome.addonTorqueEffector3DList.Count; torqueEffector3DIndex++)
        {
            if (sourceGenome.addonTorqueEffector3DList[torqueEffector3DIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonTorqueEffector3DList[torqueEffector3DIndex].innov;
                addonDisplayIndex++;
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.TorqueEffector3D;
                itemDisplay.sourceAddonIndex = torqueEffector3DIndex;
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // MouthBasic:
        for (int mouthBasicIndex = 0; mouthBasicIndex < sourceGenome.addonMouthBasicList.Count; mouthBasicIndex++)
        {
            if (sourceGenome.addonMouthBasicList[mouthBasicIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonMouthBasicList[mouthBasicIndex].innov;
                addonDisplayIndex++;                                                                  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.MouthBasic; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = mouthBasicIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // NoiseMakerBasic:
        for (int noiseMakerBasicIndex = 0; noiseMakerBasicIndex < sourceGenome.addonNoiseMakerBasicList.Count; noiseMakerBasicIndex++)
        {
            if (sourceGenome.addonNoiseMakerBasicList[noiseMakerBasicIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonNoiseMakerBasicList[noiseMakerBasicIndex].innov;
                addonDisplayIndex++;                                                                       // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.NoiseMakerBasic; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = noiseMakerBasicIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Sticky:
        for (int stickyIndex = 0; stickyIndex < sourceGenome.addonStickyList.Count; stickyIndex++)
        {
            if (sourceGenome.addonStickyList[stickyIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonStickyList[stickyIndex].innov;
                addonDisplayIndex++;                                                              // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.Sticky; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = stickyIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // WeaponBasic:
        for (int weaponBasicIndex = 0; weaponBasicIndex < sourceGenome.addonWeaponBasicList.Count; weaponBasicIndex++)
        {
            if (sourceGenome.addonWeaponBasicList[weaponBasicIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonWeaponBasicList[weaponBasicIndex].innov;
                addonDisplayIndex++;                                                                   // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.WeaponBasic; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = weaponBasicIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }

        // Oscillator Inputs:
        for (int oscillatorInputIndex = 0; oscillatorInputIndex < sourceGenome.addonOscillatorInputList.Count; oscillatorInputIndex++)
        {
            //Debug.Log("OscillatorInput Addon# " + oscillatorInputIndex.ToString() + ", ");
            // Check if this node contains a OscillatorInput Add-on:
            if (sourceGenome.addonOscillatorInputList[oscillatorInputIndex].critterNodeID == nodeID)
            {
                //Debug.Log("FOUND OscillatorInput! " + oscillatorInputIndex.ToString() + ", nodeID: " + nodeID.ToString());
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonOscillatorInputList[oscillatorInputIndex].innov;
                addonDisplayIndex++;                                                                       // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.OscillatorInput; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = oscillatorInputIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Value Inputs:
        for (int valueInputIndex = 0; valueInputIndex < sourceGenome.addonValueInputList.Count; valueInputIndex++)
        {
            if (sourceGenome.addonValueInputList[valueInputIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonValueInputList[valueInputIndex].innov;
                addonDisplayIndex++;                                                                  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.ValueInput; // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = valueInputIndex;                                       // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Timer Inputs:
        for (int timerInputIndex = 0; timerInputIndex < sourceGenome.addonTimerInputList.Count; timerInputIndex++)
        {
            if (sourceGenome.addonTimerInputList[timerInputIndex].critterNodeID == nodeID)
            {
                GameObject            itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay   = itemDisplayGO.GetComponent <PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index           = addonDisplayIndex;
                itemDisplay.addonInno       = sourceGenome.addonTimerInputList[timerInputIndex].innov;
                addonDisplayIndex++;
                itemDisplay.sourceAddonType  = CritterNodeAddonBase.CritterNodeAddonTypes.TimerInput;
                itemDisplay.sourceAddonIndex = timerInputIndex;
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
    }
示例#20
0
 public void LoadCritterGenome(CritterGenome newGenome) {
     Debug.Log("LoadCritterGenome!!");
     masterCritterGenome = newGenome;
     masterCritterGenome.ReconstructGenomeFromLoad();
     RebuildCritterFromGenomeRecursive(false, true, 0f, true);
 }
    public void RepopulateList(CritterGenome sourceGenome, int nodeID) {
        var children = new List<GameObject>();
        foreach (Transform child in this.gameObject.transform) children.Add(child.gameObject);
        children.ForEach(child => Destroy(child));

        int addonDisplayIndex = 0;
        // Go through all the Addon lists and check if there are any addons for the current NodeID:

        // Physical Attributes:
        for (int physicalAttributesIndex = 0; physicalAttributesIndex < sourceGenome.addonPhysicalAttributesList.Count; physicalAttributesIndex++) {
            if(sourceGenome.addonPhysicalAttributesList[physicalAttributesIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonPhysicalAttributesList[physicalAttributesIndex].innov;
                addonDisplayIndex++; 
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.PhysicalAttributes; 
                itemDisplay.sourceAddonIndex = physicalAttributesIndex; 
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }

        // Joint Angle Sensors:
        for (int jointAngleSensorIndex = 0; jointAngleSensorIndex < sourceGenome.addonJointAngleSensorList.Count; jointAngleSensorIndex++) {
            //Debug.Log("jointAngleSensorIndex Addon# " + jointAngleSensorIndex.ToString() + ", ");
            // Check if this node contains a jointAngleSensor Add-on:
            if (sourceGenome.addonJointAngleSensorList[jointAngleSensorIndex].critterNodeID == nodeID) {
                //Debug.Log("FOUND JOINTAngleSensor! " + jointAngleSensorIndex.ToString() + ", nodeID: " + nodeID.ToString());
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonJointAngleSensorList[jointAngleSensorIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.JointAngleSensor;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = jointAngleSensorIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Contact Sensors:
        for (int contactSensorIndex = 0; contactSensorIndex < sourceGenome.addonContactSensorList.Count; contactSensorIndex++) {
            if (sourceGenome.addonContactSensorList[contactSensorIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonContactSensorList[contactSensorIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.ContactSensor;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = contactSensorIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Raycast Sensors:
        for (int raycastSensorIndex = 0; raycastSensorIndex < sourceGenome.addonRaycastSensorList.Count; raycastSensorIndex++) {
            if (sourceGenome.addonRaycastSensorList[raycastSensorIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonRaycastSensorList[raycastSensorIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.RaycastSensor;
                itemDisplay.sourceAddonIndex = raycastSensorIndex;
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Compass Sensor 1D's:
        for (int compassSensor1DIndex = 0; compassSensor1DIndex < sourceGenome.addonCompassSensor1DList.Count; compassSensor1DIndex++) {
            if (sourceGenome.addonCompassSensor1DList[compassSensor1DIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonCompassSensor1DList[compassSensor1DIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.CompassSensor1D;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = compassSensor1DIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Compass Sensor 3D's:
        for (int compassSensor3DIndex = 0; compassSensor3DIndex < sourceGenome.addonCompassSensor3DList.Count; compassSensor3DIndex++) {
            //Debug.Log("CompassSensor3D Addon# " + compassSensor3DIndex.ToString() + ", ");
            // Check if this node contains a CompassSensor1D Add-on:
            if (sourceGenome.addonCompassSensor3DList[compassSensor3DIndex].critterNodeID == nodeID) {
                //Debug.Log("FOUND CompassSensor3D! " + compassSensor3DIndex.ToString() + ", nodeID: " + nodeID.ToString());
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonCompassSensor3DList[compassSensor3DIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.CompassSensor3D;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = compassSensor3DIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Position Sensor 1D's:
        for (int positionSensor1DIndex = 0; positionSensor1DIndex < sourceGenome.addonPositionSensor1DList.Count; positionSensor1DIndex++) {
            if (sourceGenome.addonPositionSensor1DList[positionSensor1DIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonPositionSensor1DList[positionSensor1DIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.PositionSensor1D;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = positionSensor1DIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Position Sensor 3D's:
        for (int positionSensor3DIndex = 0; positionSensor3DIndex < sourceGenome.addonPositionSensor3DList.Count; positionSensor3DIndex++) {
            if (sourceGenome.addonPositionSensor3DList[positionSensor3DIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonPositionSensor3DList[positionSensor3DIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.PositionSensor3D;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = positionSensor3DIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Rotation Sensor 1D's:
        for (int rotationSensor1DIndex = 0; rotationSensor1DIndex < sourceGenome.addonRotationSensor1DList.Count; rotationSensor1DIndex++) {
            if (sourceGenome.addonRotationSensor1DList[rotationSensor1DIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonRotationSensor1DList[rotationSensor1DIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.RotationSensor1D;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = rotationSensor1DIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Rotation Sensor 3D's:
        for (int rotationSensor3DIndex = 0; rotationSensor3DIndex < sourceGenome.addonRotationSensor3DList.Count; rotationSensor3DIndex++) {
            if (sourceGenome.addonRotationSensor3DList[rotationSensor3DIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonRotationSensor3DList[rotationSensor3DIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.RotationSensor3D;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = rotationSensor3DIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Velocity Sensor 1D's:
        for (int velocitySensor1DIndex = 0; velocitySensor1DIndex < sourceGenome.addonVelocitySensor1DList.Count; velocitySensor1DIndex++) {
            if (sourceGenome.addonVelocitySensor1DList[velocitySensor1DIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonVelocitySensor1DList[velocitySensor1DIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.VelocitySensor1D;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = velocitySensor1DIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Velocity Sensor 3D's:
        for (int velocitySensor3DIndex = 0; velocitySensor3DIndex < sourceGenome.addonVelocitySensor3DList.Count; velocitySensor3DIndex++) {
            if (sourceGenome.addonVelocitySensor3DList[velocitySensor3DIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonVelocitySensor3DList[velocitySensor3DIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.VelocitySensor3D;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = velocitySensor3DIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Altimeters:
        for (int altimeterIndex = 0; altimeterIndex < sourceGenome.addonAltimeterList.Count; altimeterIndex++) {
            if (sourceGenome.addonAltimeterList[altimeterIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonAltimeterList[altimeterIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.Altimeter;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = altimeterIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // EarBasic:
        for (int earBasicIndex = 0; earBasicIndex < sourceGenome.addonEarBasicList.Count; earBasicIndex++) {
            if (sourceGenome.addonEarBasicList[earBasicIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonEarBasicList[earBasicIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.EarBasic;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = earBasicIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // GravitySensor:
        for (int gravitySensorIndex = 0; gravitySensorIndex < sourceGenome.addonGravitySensorList.Count; gravitySensorIndex++) {
            if (sourceGenome.addonGravitySensorList[gravitySensorIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonGravitySensorList[gravitySensorIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.Gravity;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = gravitySensorIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }

        // Joint Motors:
        for (int jointMotorIndex = 0; jointMotorIndex < sourceGenome.addonJointMotorList.Count; jointMotorIndex++) {
            //Debug.Log("jointMotor Addon# " + jointMotorIndex.ToString() + ", ");
            // Check if this node contains a jointMotor Add-on:
            if (sourceGenome.addonJointMotorList[jointMotorIndex].critterNodeID == nodeID) {
                //Debug.Log("FOUND JOINTMOTOR! " + jointMotorIndex.ToString() + ", nodeID: " + nodeID.ToString());
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonJointMotorList[jointMotorIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                //itemDisplay.sourceAddon = sourceNode.addonsList[jointMotorIndex];
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.JointMotor;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = jointMotorIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.

                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Thruster Effector 1D's:
        for (int thrusterEffector1DIndex = 0; thrusterEffector1DIndex < sourceGenome.addonThrusterEffector1DList.Count; thrusterEffector1DIndex++) {
            if (sourceGenome.addonThrusterEffector1DList[thrusterEffector1DIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonThrusterEffector1DList[thrusterEffector1DIndex].innov;
                addonDisplayIndex++;
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.ThrusterEffector1D;
                itemDisplay.sourceAddonIndex = thrusterEffector1DIndex;
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Thruster Effector 3D's:
        for (int thrusterEffector3DIndex = 0; thrusterEffector3DIndex < sourceGenome.addonThrusterEffector3DList.Count; thrusterEffector3DIndex++) {
            if (sourceGenome.addonThrusterEffector3DList[thrusterEffector3DIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonThrusterEffector3DList[thrusterEffector3DIndex].innov;
                addonDisplayIndex++;
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.ThrusterEffector3D;
                itemDisplay.sourceAddonIndex = thrusterEffector3DIndex;
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Torque Effector 1D's:
        for (int torqueEffector1DIndex = 0; torqueEffector1DIndex < sourceGenome.addonTorqueEffector1DList.Count; torqueEffector1DIndex++) {
            if (sourceGenome.addonTorqueEffector1DList[torqueEffector1DIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonTorqueEffector1DList[torqueEffector1DIndex].innov;
                addonDisplayIndex++;
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.TorqueEffector1D;
                itemDisplay.sourceAddonIndex = torqueEffector1DIndex;
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Torque Effector 3D's:
        for (int torqueEffector3DIndex = 0; torqueEffector3DIndex < sourceGenome.addonTorqueEffector3DList.Count; torqueEffector3DIndex++) {
            if (sourceGenome.addonTorqueEffector3DList[torqueEffector3DIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonTorqueEffector3DList[torqueEffector3DIndex].innov;
                addonDisplayIndex++;
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.TorqueEffector3D;
                itemDisplay.sourceAddonIndex = torqueEffector3DIndex;
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // MouthBasic:
        for (int mouthBasicIndex = 0; mouthBasicIndex < sourceGenome.addonMouthBasicList.Count; mouthBasicIndex++) {
            if (sourceGenome.addonMouthBasicList[mouthBasicIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonMouthBasicList[mouthBasicIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.MouthBasic;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = mouthBasicIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // NoiseMakerBasic:
        for (int noiseMakerBasicIndex = 0; noiseMakerBasicIndex < sourceGenome.addonNoiseMakerBasicList.Count; noiseMakerBasicIndex++) {
            if (sourceGenome.addonNoiseMakerBasicList[noiseMakerBasicIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonNoiseMakerBasicList[noiseMakerBasicIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.NoiseMakerBasic;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = noiseMakerBasicIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Sticky:
        for (int stickyIndex = 0; stickyIndex < sourceGenome.addonStickyList.Count; stickyIndex++) {
            if (sourceGenome.addonStickyList[stickyIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonStickyList[stickyIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.Sticky;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = stickyIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // WeaponBasic:
        for (int weaponBasicIndex = 0; weaponBasicIndex < sourceGenome.addonWeaponBasicList.Count; weaponBasicIndex++) {
            if (sourceGenome.addonWeaponBasicList[weaponBasicIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonWeaponBasicList[weaponBasicIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.WeaponBasic;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = weaponBasicIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }

        // Oscillator Inputs:
        for (int oscillatorInputIndex = 0; oscillatorInputIndex < sourceGenome.addonOscillatorInputList.Count; oscillatorInputIndex++) {
            //Debug.Log("OscillatorInput Addon# " + oscillatorInputIndex.ToString() + ", ");
            // Check if this node contains a OscillatorInput Add-on:
            if (sourceGenome.addonOscillatorInputList[oscillatorInputIndex].critterNodeID == nodeID) {
                //Debug.Log("FOUND OscillatorInput! " + oscillatorInputIndex.ToString() + ", nodeID: " + nodeID.ToString());
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonOscillatorInputList[oscillatorInputIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.OscillatorInput;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = oscillatorInputIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Value Inputs:
        for (int valueInputIndex = 0; valueInputIndex < sourceGenome.addonValueInputList.Count; valueInputIndex++) {
            if (sourceGenome.addonValueInputList[valueInputIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonValueInputList[valueInputIndex].innov;
                addonDisplayIndex++;  // keeps track of position of this itemDisplay within the UI display addon List
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.ValueInput;  // tells this display to look in masterGenome.AddonJointMotorList[]
                itemDisplay.sourceAddonIndex = valueInputIndex;  // the index within masterGenome.AddonJointMotorList[] where the source Add-On is.
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
        // Timer Inputs:
        for (int timerInputIndex = 0; timerInputIndex < sourceGenome.addonTimerInputList.Count; timerInputIndex++) {
            if (sourceGenome.addonTimerInputList[timerInputIndex].critterNodeID == nodeID) {
                GameObject itemDisplayGO = (GameObject)Instantiate(addonDisplayPrefab);
                PanelAddonItemDisplay itemDisplay = itemDisplayGO.GetComponent<PanelAddonItemDisplay>();
                itemDisplay.panelAddonsList = this;
                itemDisplay.index = addonDisplayIndex;
                itemDisplay.addonInno = sourceGenome.addonTimerInputList[timerInputIndex].innov;
                addonDisplayIndex++; 
                itemDisplay.sourceAddonType = CritterNodeAddonBase.CritterNodeAddonTypes.TimerInput; 
                itemDisplay.sourceAddonIndex = timerInputIndex; 
                itemDisplayGO.transform.SetParent(this.transform);
                itemDisplay.Prime(sourceGenome);
            }
        }
    }
    public void SetMiniGameType(MiniGameManager.MiniGameType newGameType, MiniGameSettingsBase gameSettings)        // Change game type and re-instantiate miniGameInstance
    {
        DebugBot.DebugFunctionCall("Trial; SetMiniGameType(); " + gameType.ToString(), debugFunctionCalls);
        miniGameInstance = null;
        gameType         = newGameType;  // Update GameType to new Type!

        // CREATE mini-game instance!  !!!!!!!!!!!!! Come back to this for Improvement Later!!!!!!!
        if (newGameType == MiniGameType.None)
        {
            miniGameInstance = new MiniGameBase();
            //miniGameInstance = newGameInstance as MiniGame;
        }

        /*else if(newGameType == MiniGameType.MoveToTarget3D) {
         *      MiniGameMoveToTarget3D newGameInstance = new MiniGameMoveToTarget3D();
         *      miniGameInstance = newGameInstance;
         * }
         * else if(newGameType == MiniGameType.CreatureSwimBasic) {
         * // SHOULD the input/output Lists depend on the Agent's full Genome, or should the minigame have control over hookups?
         * // ... Maybe eventually the Agent's genome should dictate, but for now, to avoid a complete re-write, will leave the ability
         * // ... of miniGame's to choose which input/output neurons to hook up. Save that change for the big NEAT update where creature
         * // ... topologies can morph and differ within a population.
         * Debug.Log("BROKEN!! MiniGameManager public void SetMiniGameType(MiniGameManager.MiniGameType newGameType)");
         *      CritterGenome templateBody = playerRef.masterPopulation.templateGenome;
         *      //MiniGameCreatureSwimBasic newGameInstance = new MiniGameCreatureSwimBasic(templateBody);
         *      //miniGameInstance = newGameInstance;
         * }*/
        else if (newGameType == MiniGameType.CritterWalkBasic)
        {
            CritterGenome templateBody = playerRef.masterPopulation.templateGenome;
            //Debug.Log("playerRef.masterPopulation.templateBodyGenome: " + playerRef.masterPopulation.templateBodyGenome.creatureBodySegmentGenomeList[0].addOn1.ToString());
            //Debug.Log("templateBody: " + templateBody.creatureBodySegmentGenomeList[0].addOn1.ToString());
            MiniGameCritterWalkBasic newGameInstance = new MiniGameCritterWalkBasic(templateBody);
            newGameInstance.UseSettings((MiniGameCritterWalkBasicSettings)gameSettings);
            newGameInstance.InitializeGame();
            miniGameInstance = newGameInstance;
            Debug.Log("miniGameInstance.inputChannelsList.Count: " + miniGameInstance.inputChannelsList.Count.ToString() + "miniGameInstance.outputChannelsList.Count: " + miniGameInstance.outputChannelsList.Count.ToString());
        }

        /*else if(newGameType == MiniGameType.RobotArmSimple) {
         *      MiniGameRobotArm newGameInstance = new MiniGameRobotArm();
         *      miniGameInstance = newGameInstance;
         * }
         * else if(newGameType == MiniGameType.PhysXWorm) {
         *      MiniGamePhysXWorm newGameInstance = new MiniGamePhysXWorm();
         *      miniGameInstance = newGameInstance;
         * }
         * else if(newGameType == MiniGameType.BallCatch) {
         *      MiniGameBallCatch newGameInstance = new MiniGameBallCatch();
         *      miniGameInstance = newGameInstance;
         * }
         * else if(newGameType == MiniGameType.ObstacleNavigation) {
         *      MiniGameObstacleNavigation newGameInstance = new MiniGameObstacleNavigation();
         *      miniGameInstance = newGameInstance;
         * }
         * else if(newGameType == MiniGameType.PoleBalancing2D) {
         *      MiniGamePoleBalancing2D newGameInstance = new MiniGamePoleBalancing2D();
         *      miniGameInstance = newGameInstance;
         * }
         * else if(newGameType == MiniGameType.SpaceshipShooter) {
         *      MiniGameSpaceshipShooter newGameInstance = new MiniGameSpaceshipShooter();
         *      miniGameInstance = newGameInstance;
         * }*/

        SetInputOutputArrays();         // Haven't set input/output lists for the minigame yet....
    }
示例#23
0
    private void CreateBlankCritterGenome() {
        if(masterCritterGenome == null) {
            masterCritterGenome = new CritterGenome();
        }
        else {
            masterCritterGenome.ResetToBlankGenome();
        }

        RebuildCritterFromGenomeRecursive(false, true, 0f, true);
    }
示例#24
0
    public void AdjustBrainAfterBodyChange(ref CritterGenome bodyGenome)
    {
        // Try to do it assuming this function only took a CritterNode as input, rather than full bodyGenome:
        //CritterNode sourceNode = bodyGenome.CritterNodeList[bodyNodeID];
        string beforeBrain = "AdjustBrain Before: \n";
        string afterBrain  = "AdjustBrain After: \n";

        List <GeneNodeNEAT> newBrainNodeList = bodyGenome.GetBlankBrainNodesFromBody(); // doesn't include Hidden Nodes
        //List<GeneLinkNEAT> newBrainLinkList = new List<GeneLinkNEAT>();  // need to make a new copy so that the old link-list stays static while searching for matching from/toID's
        // Find number of Input+Output nodes in the old list:
        //int numOriginalInOutNodes = 0;
        //for (int i = 0; i < nodeNEATList.Count; i++) {
        //    if(nodeNEATList[i].nodeType != GeneNodeNEAT.GeneNodeType.Hid) {
        //        numOriginalInOutNodes++;
        //    }
        //}
        // Compare this to the number of nodes in the new list (which doesn't contain any hidden nodes)
        //int netNewNodes = newBrainNodeList.Count - numOriginalInOutNodes;

        //Debug.Log("AdjustBrainAddedRecursion! numOriginalInOutNodes: " + numOriginalInOutNodes.ToString() + ", netNewNodes: " + netNewNodes.ToString() + ", bodyNodeID: " + bodyNodeID.ToString() + ", recursionNum: " + recursionNum.ToString());

        int nextNodeIndexID = newBrainNodeList.Count;  // where to start counting for hiddenNode ID's

        for (int i = 0; i < nodeNEATList.Count; i++)
        {
            beforeBrain += "Node " + nodeNEATList[i].id.ToString() + " (" + nodeNEATList[i].sourceAddonInno.ToString() + ", " + nodeNEATList[i].sourceAddonRecursionNum.ToString() + ", " + nodeNEATList[i].sourceAddonChannelNum.ToString() + ")\n";

            if (nodeNEATList[i].nodeType == GeneNodeNEAT.GeneNodeType.Hid)
            {
                //Debug.Log("AdjustBrainAfterBodyChange HID NODE: nextNodeIndexID: " + (nextNodeIndexID).ToString());
                GeneNodeNEAT clonedNode = new GeneNodeNEAT(nextNodeIndexID, nodeNEATList[i].nodeType, nodeNEATList[i].activationFunction, nodeNEATList[i].sourceAddonInno, nodeNEATList[i].sourceAddonRecursionNum, false, nodeNEATList[i].sourceAddonChannelNum);
                newBrainNodeList.Add(clonedNode);
                nextNodeIndexID++;
            }
        }

        for (int i = 0; i < newBrainNodeList.Count; i++)
        {
            afterBrain += "Node " + newBrainNodeList[i].id.ToString() + " (" + newBrainNodeList[i].sourceAddonInno.ToString() + ", " + newBrainNodeList[i].sourceAddonRecursionNum.ToString() + ", " + newBrainNodeList[i].sourceAddonChannelNum.ToString() + ")\n";
        }
        // Once complete, replace oldNodeList with the new one:
        nodeNEATList = newBrainNodeList;
        //linkNEATList = newBrainLinkList;

        // Make sure that there aren't any links pointing to non-existent nodes:
        for (int i = 0; i < linkNEATList.Count; i++)
        {
            bool linkSevered = false;
            if (GetNodeIndexFromInt3(linkNEATList[i].fromNodeID) == -1)
            {
                linkSevered = true;
            }
            if (GetNodeIndexFromInt3(linkNEATList[i].toNodeID) == -1)
            {
                linkSevered = true;
            }

            if (linkSevered)
            {
                linkNEATList[i].enabled = false;
                //Debug.Log("LINK " + i.ToString() + " SEVERED!! " + linkNEATList[i].fromNodeID.ToString() + ", " + linkNEATList[i].toNodeID.ToString());
            }
        }

        //Debug.Log(beforeBrain);
        //Debug.Log(afterBrain + "\n deltaNodes: " + netNewNodes.ToString());
    }
示例#25
0
    public void Prime(CritterGenome sourceGenome)
    {
        textHeader.text = sourceAddonType.ToString() + " [" + addonInno.ToString() + "]";

        if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.PhysicalAttributes)
        {
            AddonPhysicalAttributes physicalAttributes = sourceGenome.addonPhysicalAttributesList[sourceAddonIndex];

            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Dynamic Friction:";
            floatDisplay1.sliderFloat.minValue = 0f;
            floatDisplay1.sliderFloat.maxValue = 1f;
            floatDisplay1.linkedFloatValue[0]  = physicalAttributes.dynamicFriction[0];
            physicalAttributes.dynamicFriction = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = physicalAttributes.dynamicFriction[0];
            floatDisplay1.textFloatValue.text  = physicalAttributes.dynamicFriction[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject             floatDisplay2GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay2   = floatDisplay2GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay2.textFloatName.text   = "Static Friction:";
            floatDisplay2.sliderFloat.minValue = 0f;
            floatDisplay2.sliderFloat.maxValue = 1f;
            floatDisplay2.linkedFloatValue[0]  = physicalAttributes.staticFriction[0];
            physicalAttributes.staticFriction  = floatDisplay2.linkedFloatValue;
            floatDisplay2.sliderFloat.value    = physicalAttributes.staticFriction[0];
            floatDisplay2.textFloatValue.text  = physicalAttributes.staticFriction[0].ToString();
            floatDisplay2GO.transform.SetParent(this.transform);

            GameObject             floatDisplay3GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay3   = floatDisplay3GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay3.textFloatName.text   = "Bounciness:";
            floatDisplay3.sliderFloat.minValue = 0f;
            floatDisplay3.sliderFloat.maxValue = 1f;
            floatDisplay3.linkedFloatValue[0]  = physicalAttributes.bounciness[0];
            physicalAttributes.bounciness      = floatDisplay3.linkedFloatValue;
            floatDisplay3.sliderFloat.value    = physicalAttributes.bounciness[0];
            floatDisplay3.textFloatValue.text  = physicalAttributes.bounciness[0].ToString();
            floatDisplay3GO.transform.SetParent(this.transform);

            GameObject            boolDisplay1GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay1   = boolDisplay1GO.GetComponent <PanelAddonDisplayBool>();
            boolDisplay1.textBoolName.text     = "Freeze Position X:";
            boolDisplay1.linkedBoolValue[0]    = physicalAttributes.freezePositionX[0];
            physicalAttributes.freezePositionX = boolDisplay1.linkedBoolValue;
            boolDisplay1.toggleBool.isOn       = physicalAttributes.freezePositionX[0];
            boolDisplay1GO.transform.SetParent(this.transform);

            GameObject            boolDisplay2GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay2   = boolDisplay2GO.GetComponent <PanelAddonDisplayBool>();
            boolDisplay2.textBoolName.text     = "Freeze Position Y:";
            boolDisplay2.linkedBoolValue[0]    = physicalAttributes.freezePositionY[0];
            physicalAttributes.freezePositionY = boolDisplay2.linkedBoolValue;
            boolDisplay2.toggleBool.isOn       = physicalAttributes.freezePositionY[0];
            boolDisplay2GO.transform.SetParent(this.transform);

            GameObject            boolDisplay3GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay3   = boolDisplay3GO.GetComponent <PanelAddonDisplayBool>();
            boolDisplay3.textBoolName.text     = "Freeze Position Z:";
            boolDisplay3.linkedBoolValue[0]    = physicalAttributes.freezePositionZ[0];
            physicalAttributes.freezePositionZ = boolDisplay3.linkedBoolValue;
            boolDisplay3.toggleBool.isOn       = physicalAttributes.freezePositionZ[0];
            boolDisplay3GO.transform.SetParent(this.transform);

            GameObject            boolDisplay4GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay4   = boolDisplay4GO.GetComponent <PanelAddonDisplayBool>();
            boolDisplay4.textBoolName.text     = "Freeze Rotation X:";
            boolDisplay4.linkedBoolValue[0]    = physicalAttributes.freezeRotationX[0];
            physicalAttributes.freezeRotationX = boolDisplay4.linkedBoolValue;
            boolDisplay4.toggleBool.isOn       = physicalAttributes.freezeRotationX[0];
            boolDisplay4GO.transform.SetParent(this.transform);

            GameObject            boolDisplay5GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay5   = boolDisplay5GO.GetComponent <PanelAddonDisplayBool>();
            boolDisplay5.textBoolName.text     = "Freeze Rotation Y:";
            boolDisplay5.linkedBoolValue[0]    = physicalAttributes.freezeRotationY[0];
            physicalAttributes.freezeRotationY = boolDisplay5.linkedBoolValue;
            boolDisplay5.toggleBool.isOn       = physicalAttributes.freezeRotationY[0];
            boolDisplay5GO.transform.SetParent(this.transform);

            GameObject            boolDisplay6GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay6   = boolDisplay6GO.GetComponent <PanelAddonDisplayBool>();
            boolDisplay6.textBoolName.text     = "Freeze Rotation Z:";
            boolDisplay6.linkedBoolValue[0]    = physicalAttributes.freezeRotationZ[0];
            physicalAttributes.freezeRotationZ = boolDisplay6.linkedBoolValue;
            boolDisplay6.toggleBool.isOn       = physicalAttributes.freezeRotationZ[0];
            boolDisplay6GO.transform.SetParent(this.transform);
        }

        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.JointAngleSensor)
        {
            AddonJointAngleSensor  jointAngleSensor = sourceGenome.addonJointAngleSensorList[sourceAddonIndex];
            GameObject             floatDisplayGO   = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay     = floatDisplayGO.GetComponent <PanelAddonDisplayFloat>();

            floatDisplay.textFloatName.text   = "Angle Sensitivity:";
            floatDisplay.sliderFloat.minValue = 0.01f;
            floatDisplay.sliderFloat.maxValue = 2f;
            floatDisplay.linkedFloatValue[0]  = jointAngleSensor.sensitivity[0];
            jointAngleSensor.sensitivity      = floatDisplay.linkedFloatValue;
            floatDisplay.sliderFloat.value    = jointAngleSensor.sensitivity[0];
            floatDisplay.textFloatValue.text  = jointAngleSensor.sensitivity[0].ToString();

            GameObject            boolDisplay1GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay1   = boolDisplay1GO.GetComponent <PanelAddonDisplayBool>();
            boolDisplay1.textBoolName.text  = "Measure Vel:";
            boolDisplay1.linkedBoolValue[0] = jointAngleSensor.measureVel[0];
            jointAngleSensor.measureVel     = boolDisplay1.linkedBoolValue;
            boolDisplay1.toggleBool.isOn    = jointAngleSensor.measureVel[0];
            boolDisplay1GO.transform.SetParent(this.transform);

            floatDisplayGO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.ContactSensor)
        {
            AddonContactSensor     contactSensor   = sourceGenome.addonContactSensorList[sourceAddonIndex];
            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.05f;
            floatDisplay1.sliderFloat.maxValue = 20f;
            floatDisplay1.linkedFloatValue[0]  = contactSensor.contactSensitivity[0];
            contactSensor.contactSensitivity   = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = contactSensor.contactSensitivity[0];
            floatDisplay1.textFloatValue.text  = contactSensor.contactSensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.RaycastSensor)
        {
            AddonRaycastSensor     raycastSensor   = sourceGenome.addonRaycastSensorList[sourceAddonIndex];
            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Max Distance:";
            floatDisplay1.sliderFloat.minValue = 0.1f;
            floatDisplay1.sliderFloat.maxValue = 25f;
            floatDisplay1.linkedFloatValue[0]  = raycastSensor.maxDistance[0];
            raycastSensor.maxDistance          = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = raycastSensor.maxDistance[0];
            floatDisplay1.textFloatValue.text  = raycastSensor.maxDistance[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject vector3DisplayGO             = (GameObject)Instantiate(vector3DisplayPrefab);
            PanelAddonDisplayVector3 vector3Display = vector3DisplayGO.GetComponent <PanelAddonDisplayVector3>();
            vector3Display.textVector3Name.text  = "Forward Vector:";
            vector3Display.sliderX.minValue      = -1f;
            vector3Display.sliderX.maxValue      = 1f;
            vector3Display.sliderX.value         = raycastSensor.forwardVector[0].x;
            vector3Display.textXValue.text       = raycastSensor.forwardVector[0].x.ToString();
            vector3Display.sliderY.minValue      = -1f;
            vector3Display.sliderY.maxValue      = 1f;
            vector3Display.sliderY.value         = raycastSensor.forwardVector[0].y;
            vector3Display.textYValue.text       = raycastSensor.forwardVector[0].y.ToString();
            vector3Display.sliderZ.minValue      = -1f;
            vector3Display.sliderZ.maxValue      = 1f;
            vector3Display.sliderZ.value         = raycastSensor.forwardVector[0].z;
            vector3Display.textZValue.text       = raycastSensor.forwardVector[0].z.ToString();
            vector3Display.linkedVector3Value[0] = raycastSensor.forwardVector[0];
            raycastSensor.forwardVector          = vector3Display.linkedVector3Value;
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.CompassSensor1D)
        {
            AddonCompassSensor1D compassSensor1D = sourceGenome.addonCompassSensor1DList[sourceAddonIndex];

            GameObject vector3DisplayGO             = (GameObject)Instantiate(vector3DisplayPrefab);
            PanelAddonDisplayVector3 vector3Display = vector3DisplayGO.GetComponent <PanelAddonDisplayVector3>();
            vector3Display.textVector3Name.text  = "Forward Vector:";
            vector3Display.sliderX.minValue      = -1f;
            vector3Display.sliderX.maxValue      = 1f;
            vector3Display.sliderX.value         = compassSensor1D.forwardVector[0].x;
            vector3Display.textXValue.text       = compassSensor1D.forwardVector[0].x.ToString();
            vector3Display.sliderY.minValue      = -1f;
            vector3Display.sliderY.maxValue      = 1f;
            vector3Display.sliderY.value         = compassSensor1D.forwardVector[0].y;
            vector3Display.textYValue.text       = compassSensor1D.forwardVector[0].y.ToString();
            vector3Display.sliderZ.minValue      = -1f;
            vector3Display.sliderZ.maxValue      = 1f;
            vector3Display.sliderZ.value         = compassSensor1D.forwardVector[0].z;
            vector3Display.textZValue.text       = compassSensor1D.forwardVector[0].z.ToString();
            vector3Display.linkedVector3Value[0] = compassSensor1D.forwardVector[0];
            compassSensor1D.forwardVector        = vector3Display.linkedVector3Value;

            vector3DisplayGO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.CompassSensor3D)
        {
            AddonCompassSensor3D compassSensor3D = sourceGenome.addonCompassSensor3DList[sourceAddonIndex];
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.PositionSensor1D)
        {
            AddonPositionSensor1D positionSensor1D = sourceGenome.addonPositionSensor1DList[sourceAddonIndex];

            GameObject vector3DisplayGO             = (GameObject)Instantiate(vector3DisplayPrefab);
            PanelAddonDisplayVector3 vector3Display = vector3DisplayGO.GetComponent <PanelAddonDisplayVector3>();
            vector3Display.textVector3Name.text  = "Forward Vector:";
            vector3Display.sliderX.minValue      = -1f;
            vector3Display.sliderX.maxValue      = 1f;
            vector3Display.sliderX.value         = positionSensor1D.forwardVector[0].x;
            vector3Display.textXValue.text       = positionSensor1D.forwardVector[0].x.ToString();
            vector3Display.sliderY.minValue      = -1f;
            vector3Display.sliderY.maxValue      = 1f;
            vector3Display.sliderY.value         = positionSensor1D.forwardVector[0].y;
            vector3Display.textYValue.text       = positionSensor1D.forwardVector[0].y.ToString();
            vector3Display.sliderZ.minValue      = -1f;
            vector3Display.sliderZ.maxValue      = 1f;
            vector3Display.sliderZ.value         = positionSensor1D.forwardVector[0].z;
            vector3Display.textZValue.text       = positionSensor1D.forwardVector[0].z.ToString();
            vector3Display.linkedVector3Value[0] = positionSensor1D.forwardVector[0];
            positionSensor1D.forwardVector       = vector3Display.linkedVector3Value;
            vector3DisplayGO.transform.SetParent(this.transform);

            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.01f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0]  = positionSensor1D.sensitivity[0];
            positionSensor1D.sensitivity       = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = positionSensor1D.sensitivity[0];
            floatDisplay1.textFloatValue.text  = positionSensor1D.sensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject            boolDisplay1GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay1   = boolDisplay1GO.GetComponent <PanelAddonDisplayBool>();
            boolDisplay1.textBoolName.text  = "Relative:";
            boolDisplay1.linkedBoolValue[0] = positionSensor1D.relative[0];
            positionSensor1D.relative       = boolDisplay1.linkedBoolValue;
            boolDisplay1.toggleBool.isOn    = positionSensor1D.relative[0];
            boolDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.PositionSensor3D)
        {
            AddonPositionSensor3D positionSensor3D = sourceGenome.addonPositionSensor3DList[sourceAddonIndex];

            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.01f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0]  = positionSensor3D.sensitivity[0];
            positionSensor3D.sensitivity       = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = positionSensor3D.sensitivity[0];
            floatDisplay1.textFloatValue.text  = positionSensor3D.sensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject            boolDisplay1GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay1   = boolDisplay1GO.GetComponent <PanelAddonDisplayBool>();
            boolDisplay1.textBoolName.text  = "Relative:";
            boolDisplay1.linkedBoolValue[0] = positionSensor3D.relative[0];
            positionSensor3D.relative       = boolDisplay1.linkedBoolValue;
            boolDisplay1.toggleBool.isOn    = positionSensor3D.relative[0];
            boolDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.RotationSensor1D)
        {
            AddonRotationSensor1D rotationSensor1D = sourceGenome.addonRotationSensor1DList[sourceAddonIndex];

            GameObject vector3DisplayGO             = (GameObject)Instantiate(vector3DisplayPrefab);
            PanelAddonDisplayVector3 vector3Display = vector3DisplayGO.GetComponent <PanelAddonDisplayVector3>();
            vector3Display.textVector3Name.text  = "Local Axis:";
            vector3Display.sliderX.minValue      = -1f;
            vector3Display.sliderX.maxValue      = 1f;
            vector3Display.sliderX.value         = rotationSensor1D.localAxis[0].x;
            vector3Display.textXValue.text       = rotationSensor1D.localAxis[0].x.ToString();
            vector3Display.sliderY.minValue      = -1f;
            vector3Display.sliderY.maxValue      = 1f;
            vector3Display.sliderY.value         = rotationSensor1D.localAxis[0].y;
            vector3Display.textYValue.text       = rotationSensor1D.localAxis[0].y.ToString();
            vector3Display.sliderZ.minValue      = -1f;
            vector3Display.sliderZ.maxValue      = 1f;
            vector3Display.sliderZ.value         = rotationSensor1D.localAxis[0].z;
            vector3Display.textZValue.text       = rotationSensor1D.localAxis[0].z.ToString();
            vector3Display.linkedVector3Value[0] = rotationSensor1D.localAxis[0];
            rotationSensor1D.localAxis           = vector3Display.linkedVector3Value;
            vector3DisplayGO.transform.SetParent(this.transform);

            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.01f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0]  = rotationSensor1D.sensitivity[0];
            rotationSensor1D.sensitivity       = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = rotationSensor1D.sensitivity[0];
            floatDisplay1.textFloatValue.text  = rotationSensor1D.sensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.RotationSensor3D)
        {
            AddonRotationSensor3D rotationSensor3D = sourceGenome.addonRotationSensor3DList[sourceAddonIndex];

            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.01f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0]  = rotationSensor3D.sensitivity[0];
            rotationSensor3D.sensitivity       = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = rotationSensor3D.sensitivity[0];
            floatDisplay1.textFloatValue.text  = rotationSensor3D.sensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.VelocitySensor1D)
        {
            AddonVelocitySensor1D velocitySensor1D = sourceGenome.addonVelocitySensor1DList[sourceAddonIndex];

            GameObject vector3DisplayGO             = (GameObject)Instantiate(vector3DisplayPrefab);
            PanelAddonDisplayVector3 vector3Display = vector3DisplayGO.GetComponent <PanelAddonDisplayVector3>();
            vector3Display.textVector3Name.text  = "Forward Vector:";
            vector3Display.sliderX.minValue      = -1f;
            vector3Display.sliderX.maxValue      = 1f;
            vector3Display.sliderX.value         = velocitySensor1D.forwardVector[0].x;
            vector3Display.textXValue.text       = velocitySensor1D.forwardVector[0].x.ToString();
            vector3Display.sliderY.minValue      = -1f;
            vector3Display.sliderY.maxValue      = 1f;
            vector3Display.sliderY.value         = velocitySensor1D.forwardVector[0].y;
            vector3Display.textYValue.text       = velocitySensor1D.forwardVector[0].y.ToString();
            vector3Display.sliderZ.minValue      = -1f;
            vector3Display.sliderZ.maxValue      = 1f;
            vector3Display.sliderZ.value         = velocitySensor1D.forwardVector[0].z;
            vector3Display.textZValue.text       = velocitySensor1D.forwardVector[0].z.ToString();
            vector3Display.linkedVector3Value[0] = velocitySensor1D.forwardVector[0];
            velocitySensor1D.forwardVector       = vector3Display.linkedVector3Value;
            vector3DisplayGO.transform.SetParent(this.transform);

            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.01f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0]  = velocitySensor1D.sensitivity[0];
            velocitySensor1D.sensitivity       = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = velocitySensor1D.sensitivity[0];
            floatDisplay1.textFloatValue.text  = velocitySensor1D.sensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject            boolDisplay1GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay1   = boolDisplay1GO.GetComponent <PanelAddonDisplayBool>();
            boolDisplay1.textBoolName.text  = "Relative:";
            boolDisplay1.linkedBoolValue[0] = velocitySensor1D.relative[0];
            velocitySensor1D.relative       = boolDisplay1.linkedBoolValue;
            boolDisplay1.toggleBool.isOn    = velocitySensor1D.relative[0];
            boolDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.VelocitySensor3D)
        {
            AddonVelocitySensor3D velocitySensor3D = sourceGenome.addonVelocitySensor3DList[sourceAddonIndex];

            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.01f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0]  = velocitySensor3D.sensitivity[0];
            velocitySensor3D.sensitivity       = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = velocitySensor3D.sensitivity[0];
            floatDisplay1.textFloatValue.text  = velocitySensor3D.sensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject            boolDisplay1GO = (GameObject)Instantiate(boolDisplayPrefab);
            PanelAddonDisplayBool boolDisplay1   = boolDisplay1GO.GetComponent <PanelAddonDisplayBool>();
            boolDisplay1.textBoolName.text  = "Relative:";
            boolDisplay1.linkedBoolValue[0] = velocitySensor3D.relative[0];
            velocitySensor3D.relative       = boolDisplay1.linkedBoolValue;
            boolDisplay1.toggleBool.isOn    = velocitySensor3D.relative[0];
            boolDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.Altimeter)
        {
            AddonAltimeter altimeter = sourceGenome.addonAltimeterList[sourceAddonIndex];
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.EarBasic)
        {
            AddonEarBasic earBasic = sourceGenome.addonEarBasicList[sourceAddonIndex];

            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Sensitivity:";
            floatDisplay1.sliderFloat.minValue = 0.01f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0]  = earBasic.sensitivity[0];
            earBasic.sensitivity              = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value   = earBasic.sensitivity[0];
            floatDisplay1.textFloatValue.text = earBasic.sensitivity[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.Gravity)
        {
            AddonGravitySensor gravitySensor = sourceGenome.addonGravitySensorList[sourceAddonIndex];
        }

        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.JointMotor)
        {
            AddonJointMotor        jointMotor      = sourceGenome.addonJointMotorList[sourceAddonIndex];
            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Motor Force:";
            floatDisplay1.sliderFloat.minValue = 1f;
            floatDisplay1.sliderFloat.maxValue = 500f;
            floatDisplay1.linkedFloatValue[0]  = jointMotor.motorForce[0];
            jointMotor.motorForce             = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value   = jointMotor.motorForce[0];
            floatDisplay1.textFloatValue.text = jointMotor.motorForce[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject             floatDisplay2GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay2   = floatDisplay2GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay2.textFloatName.text   = "Motor Speed:";
            floatDisplay2.sliderFloat.minValue = 1f;
            floatDisplay2.sliderFloat.maxValue = 500f;
            floatDisplay2.linkedFloatValue[0]  = jointMotor.motorSpeed[0];
            jointMotor.motorSpeed             = floatDisplay2.linkedFloatValue;
            floatDisplay2.sliderFloat.value   = jointMotor.motorSpeed[0];
            floatDisplay2.textFloatValue.text = jointMotor.motorSpeed[0].ToString();
            floatDisplay2GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.ThrusterEffector1D)
        {
            AddonThrusterEffector1D thrusterEffector1D = sourceGenome.addonThrusterEffector1DList[sourceAddonIndex];

            GameObject vector3DisplayGO             = (GameObject)Instantiate(vector3DisplayPrefab);
            PanelAddonDisplayVector3 vector3Display = vector3DisplayGO.GetComponent <PanelAddonDisplayVector3>();
            vector3Display.textVector3Name.text  = "Forward Vector:";
            vector3Display.sliderX.minValue      = -1f;
            vector3Display.sliderX.maxValue      = 1f;
            vector3Display.sliderX.value         = thrusterEffector1D.forwardVector[0].x;
            vector3Display.textXValue.text       = thrusterEffector1D.forwardVector[0].x.ToString();
            vector3Display.sliderY.minValue      = -1f;
            vector3Display.sliderY.maxValue      = 1f;
            vector3Display.sliderY.value         = thrusterEffector1D.forwardVector[0].y;
            vector3Display.textYValue.text       = thrusterEffector1D.forwardVector[0].y.ToString();
            vector3Display.sliderZ.minValue      = -1f;
            vector3Display.sliderZ.maxValue      = 1f;
            vector3Display.sliderZ.value         = thrusterEffector1D.forwardVector[0].z;
            vector3Display.textZValue.text       = thrusterEffector1D.forwardVector[0].z.ToString();
            vector3Display.linkedVector3Value[0] = thrusterEffector1D.forwardVector[0];
            thrusterEffector1D.forwardVector     = vector3Display.linkedVector3Value;
            vector3DisplayGO.transform.SetParent(this.transform);

            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Max Force:";
            floatDisplay1.sliderFloat.minValue = 0.1f;
            floatDisplay1.sliderFloat.maxValue = 100f;
            floatDisplay1.linkedFloatValue[0]  = thrusterEffector1D.maxForce[0];
            thrusterEffector1D.maxForce        = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = thrusterEffector1D.maxForce[0];
            floatDisplay1.textFloatValue.text  = thrusterEffector1D.maxForce[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.ThrusterEffector3D)
        {
            AddonThrusterEffector3D thrusterEffector3D = sourceGenome.addonThrusterEffector3DList[sourceAddonIndex];

            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Max Force:";
            floatDisplay1.sliderFloat.minValue = 0.1f;
            floatDisplay1.sliderFloat.maxValue = 100f;
            floatDisplay1.linkedFloatValue[0]  = thrusterEffector3D.maxForce[0];
            thrusterEffector3D.maxForce        = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = thrusterEffector3D.maxForce[0];
            floatDisplay1.textFloatValue.text  = thrusterEffector3D.maxForce[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.TorqueEffector1D)
        {
            AddonTorqueEffector1D torqueEffector1D = sourceGenome.addonTorqueEffector1DList[sourceAddonIndex];

            GameObject vector3DisplayGO             = (GameObject)Instantiate(vector3DisplayPrefab);
            PanelAddonDisplayVector3 vector3Display = vector3DisplayGO.GetComponent <PanelAddonDisplayVector3>();
            vector3Display.textVector3Name.text  = "Axis:";
            vector3Display.sliderX.minValue      = -1f;
            vector3Display.sliderX.maxValue      = 1f;
            vector3Display.sliderX.value         = torqueEffector1D.axis[0].x;
            vector3Display.textXValue.text       = torqueEffector1D.axis[0].x.ToString();
            vector3Display.sliderY.minValue      = -1f;
            vector3Display.sliderY.maxValue      = 1f;
            vector3Display.sliderY.value         = torqueEffector1D.axis[0].y;
            vector3Display.textYValue.text       = torqueEffector1D.axis[0].y.ToString();
            vector3Display.sliderZ.minValue      = -1f;
            vector3Display.sliderZ.maxValue      = 1f;
            vector3Display.sliderZ.value         = torqueEffector1D.axis[0].z;
            vector3Display.textZValue.text       = torqueEffector1D.axis[0].z.ToString();
            vector3Display.linkedVector3Value[0] = torqueEffector1D.axis[0];
            torqueEffector1D.axis = vector3Display.linkedVector3Value;
            vector3DisplayGO.transform.SetParent(this.transform);

            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Max Torque:";
            floatDisplay1.sliderFloat.minValue = 0.1f;
            floatDisplay1.sliderFloat.maxValue = 100f;
            floatDisplay1.linkedFloatValue[0]  = torqueEffector1D.maxTorque[0];
            torqueEffector1D.maxTorque         = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = torqueEffector1D.maxTorque[0];
            floatDisplay1.textFloatValue.text  = torqueEffector1D.maxTorque[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.TorqueEffector3D)
        {
            AddonTorqueEffector3D torqueEffector3D = sourceGenome.addonTorqueEffector3DList[sourceAddonIndex];

            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Max Torque:";
            floatDisplay1.sliderFloat.minValue = 0.1f;
            floatDisplay1.sliderFloat.maxValue = 100f;
            floatDisplay1.linkedFloatValue[0]  = torqueEffector3D.maxTorque[0];
            torqueEffector3D.maxTorque         = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = torqueEffector3D.maxTorque[0];
            floatDisplay1.textFloatValue.text  = torqueEffector3D.maxTorque[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.MouthBasic)
        {
            AddonMouthBasic mouthBasic = sourceGenome.addonMouthBasicList[sourceAddonIndex];
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.NoiseMakerBasic)
        {
            AddonNoiseMakerBasic noiseMakerBasic = sourceGenome.addonNoiseMakerBasicList[sourceAddonIndex];

            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Amplitude:";
            floatDisplay1.sliderFloat.minValue = 0.1f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0]  = noiseMakerBasic.amplitude[0];
            noiseMakerBasic.amplitude          = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = noiseMakerBasic.amplitude[0];
            floatDisplay1.textFloatValue.text  = noiseMakerBasic.amplitude[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.Sticky)
        {
            AddonSticky sticky = sourceGenome.addonStickyList[sourceAddonIndex];
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.WeaponBasic)
        {
            AddonWeaponBasic weaponBasic = sourceGenome.addonWeaponBasicList[sourceAddonIndex];

            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Strength:";
            floatDisplay1.sliderFloat.minValue = 0.1f;
            floatDisplay1.sliderFloat.maxValue = 10f;
            floatDisplay1.linkedFloatValue[0]  = weaponBasic.strength[0];
            weaponBasic.strength              = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value   = weaponBasic.strength[0];
            floatDisplay1.textFloatValue.text = weaponBasic.strength[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }

        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.OscillatorInput)
        {
            AddonOscillatorInput   oscillatorInput = sourceGenome.addonOscillatorInputList[sourceAddonIndex];
            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Frequency:";
            floatDisplay1.sliderFloat.minValue = 0.05f;
            floatDisplay1.sliderFloat.maxValue = 20f;
            floatDisplay1.linkedFloatValue[0]  = oscillatorInput.frequency[0];
            oscillatorInput.frequency          = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value    = oscillatorInput.frequency[0];
            floatDisplay1.textFloatValue.text  = oscillatorInput.frequency[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);

            GameObject             floatDisplay2GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay2   = floatDisplay2GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay2.textFloatName.text   = "Amplitude:";
            floatDisplay2.sliderFloat.minValue = 0.05f;
            floatDisplay2.sliderFloat.maxValue = 20f;
            floatDisplay2.linkedFloatValue[0]  = oscillatorInput.amplitude[0];
            oscillatorInput.amplitude          = floatDisplay2.linkedFloatValue;
            floatDisplay2.sliderFloat.value    = oscillatorInput.amplitude[0];
            floatDisplay2.textFloatValue.text  = oscillatorInput.amplitude[0].ToString();
            floatDisplay2GO.transform.SetParent(this.transform);

            GameObject             floatDisplay3GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay3   = floatDisplay3GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay3.textFloatName.text   = "Offset:";
            floatDisplay3.sliderFloat.minValue = -20f;
            floatDisplay3.sliderFloat.maxValue = 20f;
            floatDisplay3.linkedFloatValue[0]  = oscillatorInput.offset[0];
            oscillatorInput.offset             = floatDisplay3.linkedFloatValue;
            floatDisplay3.sliderFloat.value    = oscillatorInput.offset[0];
            floatDisplay3.textFloatValue.text  = oscillatorInput.offset[0].ToString();
            floatDisplay3GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.ValueInput)
        {
            AddonValueInput        valueInput      = sourceGenome.addonValueInputList[sourceAddonIndex];
            GameObject             floatDisplay1GO = (GameObject)Instantiate(floatDisplayPrefab);
            PanelAddonDisplayFloat floatDisplay1   = floatDisplay1GO.GetComponent <PanelAddonDisplayFloat>();
            floatDisplay1.textFloatName.text   = "Value:";
            floatDisplay1.sliderFloat.minValue = -5f;
            floatDisplay1.sliderFloat.maxValue = 5f;
            floatDisplay1.linkedFloatValue[0]  = valueInput.value[0];
            valueInput.value = floatDisplay1.linkedFloatValue;
            floatDisplay1.sliderFloat.value   = valueInput.value[0];
            floatDisplay1.textFloatValue.text = valueInput.value[0].ToString();
            floatDisplay1GO.transform.SetParent(this.transform);
        }
        else if (sourceAddonType == CritterNodeAddonBase.CritterNodeAddonTypes.TimerInput)
        {
            AddonTimerInput timerInput = sourceGenome.addonTimerInputList[sourceAddonIndex];
        }
    }
示例#26
0
    public void ClickSaveAgentBodyGenome()
    {
        DebugBot.DebugFunctionCall("SavePopulationUI; ClickSaveCurrentPopulation(); ", debugFunctionCalls);
        Player currentPlayer = trainerModuleScript.gameController.masterTrainer.PlayerList[trainerModuleScript.gameController.masterTrainer.CurPlayer - 1];

        populationRef = currentPlayer.masterPopulation;
        saveRootPath  = Application.dataPath + "/SaveFiles/CritterEditorGenomes/";

        string fileName = inputFieldFileSaveName.text + fileExt;

        Debug.Log(saveRootPath + fileName);

        if (populationRef != null)
        {
            //Population populationToSave = populationRef;  // Current player's population

            bool save = true;
            if (System.IO.File.Exists(saveRootPath + fileName) && !toggleOverwriteSaves.isOn)
            {
                Debug.Log("File Already Exists!");
                save = false;
            }
            if (fileName == "")
            {
                Debug.Log("No Filename Specified!");
                save = false;
            }

            if (save)     // SAVE:
            {
                Debug.Log("SAVE BodyGenome!!! filename: " + saveRootPath + fileName + ", pop size: " + populationRef.masterAgentArray.Length.ToString() + ", Agent# " + pendingAgentNumberN.ToString());

                // Create wrapper to hold all save info:
                CritterGenome genomeToSave = populationRef.masterAgentArray[pendingAgentNumberN].bodyGenome;
                genomeToSave.savedNextNodeInno  = CrossoverManager.nextNodeInnov;
                genomeToSave.savedNextAddonInno = CrossoverManager.nextAddonInnov;
                ES2.Save(genomeToSave, saveRootPath + fileName);

                /*TrainingSave trainingSave = new TrainingSave();
                 * populationToSave.nextAvailableGeneInno = GenomeNEAT.nextAvailableInnovationNumber;
                 * currentPlayer.masterCupid.savedNextNodeInnov = CrossoverManager.nextNodeInnov;
                 * currentPlayer.masterCupid.savedNextAddonInnov = CrossoverManager.nextAddonInnov; // Save status of Inno#'s!!!!
                 *
                 * trainingSave.savedPopulation = populationToSave;
                 * trainingSave.beginGeneration = populationToSave.trainingGenerations;
                 * trainingSave.endGeneration = trainingSave.beginGeneration + trainerModuleScript.gameController.masterTrainer.PlayingCurGeneration - 1; // Check if -1 is needed
                 * trainingSave.savedPopulation.trainingGenerations = trainingSave.endGeneration;  // update it so that when it is loaded it has the proper start gen#
                 *
                 * trainingSave.savedCrossoverManager = currentPlayer.masterCupid;
                 * trainingSave.savedFitnessComponentList = currentPlayer.masterTrialsList[0].fitnessManager.gameFitnessComponentList;
                 * trainingSave.savedMiniGameSettings = new MiniGameSettingsSaves();
                 * // Copy the settings from the minigame instance into the SaveWrapper:
                 * currentPlayer.masterTrialsList[0].miniGameManager.miniGameInstance.gameSettings.CopySettingsToSave(trainingSave.savedMiniGameSettings);
                 *
                 * trainingSave.savedTrainingModifierList = trainerModuleScript.gameController.masterTrainer.trainingModifierManager.activeTrainingModifierList;
                 *
                 * trainingSave.savedTrialDataBegin = currentPlayer.dataManager.generationDataList[0].trialDataArray[0];
                 * trainingSave.savedTrialDataEnd = currentPlayer.dataManager.generationDataList[trainerModuleScript.gameController.masterTrainer.PlayingCurGeneration - 1].trialDataArray[0];
                 *
                 * ES2.Save(trainingSave, saveRootPath + fileName);
                 */
            }
        }
        else
        {
            Debug.LogError("No Genome Exists!");
        }
    }
    public GenomeNEAT InitializeNewBrain(CritterGenome critterBodyGenome, int numHiddenNodes, float connectedness, bool randomWeights) {

        // OLD //sourceGenome = new GenomeNEAT(numInputNodes, numHiddenNodes, numOutputNodes); // create blank genome with no connections
        sourceGenome = new GenomeNEAT(critterBodyGenome, numHiddenNodes); // create blank genome with no connections
        sourceGenome.CreateInitialConnections(connectedness, randomWeights);

        //Debug.Log("InitializeBlankBrain #nodes: " + sourceGenome.nodeNEATList.Count.ToString() + ", #links: " + sourceGenome.linkNEATList.Count.ToString());

        return sourceGenome;
    }
	public override object Read(ES2Reader reader)
	{
		CritterGenome data = new CritterGenome();
		Read(reader, data);
		return data;
	}
    public MiniGameCritterWalkBasic(CritterGenome templateBodyGenome)
    {
        Debug.Log("MiniGameCritterWalkBasic(CritterGenome templateBodyGenome) CONSTRUCTOR!!!");
        piecesBuilt = false;  // This refers to if the pieces have all their components and are ready for Simulation, not simply instantiated empty GO's
        gameInitialized = false;  // Reset() is Initialization
        gameTicked = false;  // Has the game been ticked on its current TimeStep
        gameUpdatedFromPhysX = false;  // Did the game just get updated from PhysX Simulation?
        gameCurrentTimeStep = 0;  // Should only be able to increment this if the above are true (which means it went through gameLoop for this timeStep)
        preWarm = true;

        // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        //agentBodyBeingTested = templateBodyGenome;
        if (critterBeingTestedGO == null) {
            critterBeingTestedGO = new GameObject("critterGO");
            critterBeingTestedGO.transform.SetParent(ArenaGroup.arenaGroupStatic.gameObject.transform);
            critterBeingTested = critterBeingTestedGO.AddComponent<Critter>();
            critterBeingTested.InitializeCritterFromGenome(templateBodyGenome); // creates segmentList List<> and sets genome            
        }
        // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                
        targetSphereMat.SetFloat("_Mode", 3.0f);
        //Debug.Log(targetSphereMat.GetFloat("_Mode"));
        targetSphereMat.color = new Color(0.1f, 1f, 0.3f, 0.4f);
        groundPlaneMat.color = new Color(0.75f, 0.75f, 0.75f);
        headToTargetVecMat.color = new Color(1f, 1f, 0.25f);
        headToTargetVecHorMat.color = new Color(0.75f, 0f, 0f);
        headToTargetVecVerMat.color = new Color(0f, 0.75f, 0f);
        headFacingVecMat.color = new Color(0f, 0f, 0.75f);
        wormCenterOfMassMat.color = new Color(0f, 0f, 0f);

        // GAME OPTIONS INIT:
        //gameSettings = new MiniGameCritterWalkBasicSettings();
        //gameSettings.InitGameOptionsList();        
        //InitializeGame();        
    }