// Update is called once per frame private void Update() { DebugGUI.LogPersistent("fpsCounter", "FPS: " + (1 / Time.smoothDeltaTime).ToString("F2")); DebugGUI.LogPersistent("genCount", "Generation: " + genCount.ToString()); int activeCars = 0; foreach (GameObject item in cars) { if (!item.GetComponent <CarController>().IsFinished()) { activeCars++; } } DebugGUI.LogPersistent("activeCars", "Active Cars: " + activeCars.ToString()); for (int i = 0; i < populationSize; i++) { if (!cars[i].GetComponent <CarController>().IsFinished()) { if (cars[i].GetComponent <CarController>().output.Length != 0) { float speed = cars[i].GetComponent <CarController>().currentSpeed; DebugGUI.Graph("bestCarSpeed", speed); speedOMeter.text = speed.ToString("F0") + " MPH"; float throttleBrake = cars[i].GetComponent <CarController>().output[1]; //DebugGUI.Graph("throttle", Mathf.Clamp(cars[i].GetComponent<CarController>().output[1], 0f, 1f)); //DebugGUI.Graph("brake", Mathf.Clamp(cars[i].GetComponent<CarController>().output[2], 0f, 1f)); float engine = cars[i].GetComponent <CarController>().output[1]; if (engine > 0f) { DebugGUI.Graph("throttle", engine); DebugGUI.Graph("brake", 0f); } else { DebugGUI.Graph("throttle", 0f); DebugGUI.Graph("brake", Mathf.Abs(engine)); } //DebugGUI.Graph("throttle", cars[i].GetComponent<CarController>().output[1]); DebugGUI.Graph("steering", cars[i].GetComponent <CarController>().output[0]); float angle = cars[i].GetComponent <CarController>().output[0] * 90f; steeringWheel.transform.rotation = Quaternion.Euler(0f, 0f, -1f * angle); //DebugGUI.Graph("currentRPM", cars[i].GetComponent<CarController>().GetRPM() / 1000f); i = populationSize; } } } if (AllFinished()) { timeElapsed = 0f; mainCamera.GetComponent <CameraController>().ResetCamera(); // End of generation training cars = cars.OrderByDescending(e => e.GetComponent <CarController>().GetFitness()).ToList(); //cars = cars.OrderByDescending(e => e.GetComponent<CarController>().GradientSort()).ToList(); // Graphing DebugGUI.Graph("topFitness", cars[0].GetComponent <CarController>().GetFitness()); // calculate median float limit = (populationSize / 2f) - 1f; float medianIndex = (2 / 3f) * limit; float median; if (medianIndex % 1 != 0) { int temp1 = Mathf.FloorToInt(medianIndex); int temp2 = Mathf.CeilToInt(medianIndex); median = (cars[temp1].GetComponent <CarController>().GetFitness() + cars[temp2].GetComponent <CarController>().GetFitness()) / 2f; } else { median = cars[(int)medianIndex].GetComponent <CarController>().GetFitness(); } TrainingLog data = new TrainingLog { generation = genCount, topFitness = cars[0].GetComponent <CarController>().GetFitness(), medianFitness = median }; trainingLog.Add(data); JSONManager.SaveData(trainingLog.ToArray(), Application.dataPath + "/trainingLog.json"); DebugGUI.Graph("medianFitness", median); // calculate quartiles float Q3Index = (1 / 3f) * limit; // 0.25 is used because it's sorted in descending order float Q3; if (Q3Index % 1 != 0) { int temp1 = Mathf.FloorToInt(Q3Index); int temp2 = Mathf.CeilToInt(Q3Index); Q3 = (cars[temp1].GetComponent <CarController>().GetFitness() + cars[temp2].GetComponent <CarController>().GetFitness()) / 2f; } else { Q3 = cars[(int)Q3Index].GetComponent <CarController>().GetFitness(); } DebugGUI.Graph("upperQuartile", Q3); float Q1Index = limit; float Q1; if (Q1Index % 1 != 0) { int temp1 = Mathf.FloorToInt(Q1Index); int temp2 = Mathf.CeilToInt(Q1Index); Q1 = (cars[temp1].GetComponent <CarController>().GetFitness() + cars[temp2].GetComponent <CarController>().GetFitness()) / 2f; } else { Q1 = cars[(int)Q1Index].GetComponent <CarController>().GetFitness(); } DebugGUI.Graph("lowerQuartile", Q1); float IQR = Q3 - Q1; List <float> speedList = new List <float>(); foreach (GameObject item in cars) { speedList.Add(item.GetComponent <CarController>().avgSpeed); } speedList = speedList.OrderByDescending(e => e).ToList(); DebugGUI.Graph("medianSpeed", speedList[(populationSize / 2) - 1]); DebugGUI.Graph("topSpeed", speedList[0]); for (int i = 0; i < populationSize / 2; i++) { // check for outlier float outlier = Q3 + (1.5f * IQR); if (cars[0].GetComponent <CarController>().GetFitness() > outlier) { cars[(populationSize / 2) + i].GetComponent <CarController>().Mutate(cars[0]); } else { // take best half and delete worst half if (i + 1 == populationSize / 2) { cars[(populationSize / 2) + i].GetComponent <CarController>().Reproduce(cars[i], cars[0]); } else { cars[(populationSize / 2) + i].GetComponent <CarController>().Reproduce(cars[i], cars[i + 1]); } } //cars[(populationSize / 2) + i].GetComponent<CarController>().ResetCar(); //cars[i].GetComponent<CarController>().ResetCar(); } // reset all cars foreach (GameObject item in cars) { item.GetComponent <CarController>().ResetCar(); } // saving best network to file if (settings.saveBestNetwork) { cars[0].GetComponent <CarController>().SaveData(); } genCount++; } else { for (int i = 0; i < populationSize; i++) { if (!cars[i].GetComponent <CarController>().IsFinished()) { mainCamera.GetComponent <CameraController>().SetCamerTarget(cars[i]); i = populationSize; } } timeElapsed += Time.deltaTime; DebugGUI.LogPersistent("timeElapsed", "Time Elapsed: " + timeElapsed.ToString("F3")); } }