예제 #1
0
    public IEnumerator TrainingWorkerCoroutine()
    {
        while (true)
        {
            TrainingRequest request;
            while (!trainingManager.requests.TryDequeue(out request))
            {
                yield return(null);
            }

            // dereference to the actual objects that will be passed around
            var path   = trainingManager.Circuit(request.circuit);
            var prefab = trainingManager.Car(request.car);

            // load the scene and create the agent trainer
            var asyncoperation = SceneManager.LoadSceneAsync(path, LoadSceneMode.Additive);

            while (!asyncoperation.isDone)
            {
                yield return(null);
            }

            var scene = SceneManager.GetSceneByName(path);
            var root  = scene.GetRootGameObjects().Select(x => x.GetComponentInChildren <Track>()).Where(x => x != null).First();

            // set up interpolated paths. this should be done before the manager is added.
            var geometry = root.GetComponentInChildren <TrackGeometry>();

            // delete existing interpolations
            var existing = geometry.GetComponentsInChildren <InterpolatedPath>();
            foreach (var item in existing)
            {
                DestroyImmediate(item); // delete immediately as the manager should search for paths in its Start() method.
            }

            // and cars
            var cars = geometry.transform.Find("Cars");
            if (cars)
            {
                Destroy(cars.gameObject);
            }

            foreach (var item in interpolationCoefficients)
            {
                var interpolated = geometry.gameObject.AddComponent <InterpolatedPath>();
                interpolated.coefficient = item;
                interpolated.Initialise();
            }

            // we add the manager right away. we don't need to worry about removing the old one, because the scene will be unloaded at the end of this

            IAgentManager manager = null;
            if (request.agent == "profile")
            {
                manager = root.gameObject.AddComponent <ProfileAgentManager>();
            }
            if (request.agent == "path")
            {
                manager = root.gameObject.AddComponent <PathAgentManager>();
            }

            manager.SetAgentPrefab(prefab);

            var training = true;
            var running  = true;

            // setup the callbacks
            manager.OnComplete.RemoveAllListeners();
            manager.OnComplete.AddListener((x) =>
            {
                Debug.Log("TrainingRequest Complete");
                OnTrainingRequestComplete?.Invoke(manager);
                request.circuit = "";
                request.car     = "";
                OnTrainingFrame?.Invoke(request, manager);
                training = false;
                SceneManager.UnloadSceneAsync(path).completed += (asyncresult) =>
                {
                    running = false;
                };
            });

            // and let it go...

            while (running)
            {
                if (training)
                {
                    OnTrainingFrame?.Invoke(request, manager);
                }
                yield return(null);
            }
        }
    }