コード例 #1
0
ファイル: Loader.cs プロジェクト: team19032/team19032
        public static void StopAsync()
        {
            Debug.Assert(Instance.CurrentSimulation != null);

            if (Instance.masterManager != null)
            {
                Instance.masterManager.BroadcastSimulationStop();
            }

            Instance.Actions.Enqueue(() =>
            {
                var simulation = Instance.CurrentSimulation;
                using (var db = DatabaseManager.Open())
                {
                    try
                    {
                        simulation.Status = "Stopping";
                        NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);

                        if (ApiManager.Instance != null)
                        {
                            SceneManager.MoveGameObjectToScene(ApiManager.Instance.gameObject, SceneManager.GetActiveScene());
                        }
                        SIM.LogSimulation(SIM.Simulation.ApplicationClick, "Exit");
                        var loader        = SceneManager.LoadSceneAsync(Instance.LoaderScene);
                        loader.completed += op =>
                        {
                            if (op.isDone)
                            {
                                AssetBundle.UnloadAllAssetBundles(false);
                                Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.START);

                                simulation.Status = "Valid";
                                NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);
                                Instance.CurrentSimulation = null;
                                if (Instance.masterManager != null)
                                {
                                    Instance.masterManager.StopConnection();
                                }
                            }
                        };
                    }
                    catch (Exception ex)
                    {
                        Debug.Log($"Failed to stop '{simulation.Name}' simulation");
                        Debug.LogException(ex);

                        // NOTE: In case of failure we have to update Simulation state
                        simulation.Status = "Invalid";
                        simulation.Error  = ex.Message;
                        db.Update(simulation);

                        // TODO: take ex.Message and append it to response here
                        NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);
                    }
                }
            });
        }
コード例 #2
0
ファイル: Loader.cs プロジェクト: team19032/team19032
        static void SetupScene(SimulationModel simulation)
        {
            Dictionary <string, GameObject> cachedVehicles = new Dictionary <string, GameObject>();

            using (var db = DatabaseManager.Open())
            {
                try
                {
                    foreach (var agentConfig in Instance.SimConfig.Agents)
                    {
                        var         bundlePath    = agentConfig.AssetBundle;
                        AssetBundle textureBundle = null;
                        AssetBundle vehicleBundle = null;
                        if (cachedVehicles.ContainsKey(agentConfig.Name))
                        {
                            agentConfig.Prefab = cachedVehicles[agentConfig.Name];
                            continue;
                        }

                        using (ZipFile zip = new ZipFile(bundlePath))
                        {
                            Manifest manifest;
                            ZipEntry entry = zip.GetEntry("manifest");
                            using (var ms = zip.GetInputStream(entry))
                            {
                                int    streamSize = (int)entry.Size;
                                byte[] buffer     = new byte[streamSize];
                                streamSize = ms.Read(buffer, 0, streamSize);
                                manifest   = new Deserializer().Deserialize <Manifest>(Encoding.UTF8.GetString(buffer, 0, streamSize));
                            }

                            if (manifest.bundleFormat != BundleConfig.VehicleBundleFormatVersion)
                            {
                                zip.Close();

                                // TODO: proper exception
                                throw new ZipException("BundleFormat version mismatch");
                            }

                            var texStream = zip.GetInputStream(zip.GetEntry($"{manifest.bundleGuid}_vehicle_textures"));
                            textureBundle = AssetBundle.LoadFromStream(texStream, 0, 1 << 20);

                            string platform  = SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows ? "windows" : "linux";
                            var    mapStream = zip.GetInputStream(zip.GetEntry($"{manifest.bundleGuid}_vehicle_main_{platform}"));

                            vehicleBundle = AssetBundle.LoadFromStream(mapStream, 0, 1 << 20);

                            if (vehicleBundle == null)
                            {
                                throw new Exception($"Failed to load '{agentConfig.Name}' vehicle asset bundle");
                            }

                            try
                            {
                                var vehicleAssets = vehicleBundle.GetAllAssetNames();
                                if (vehicleAssets.Length != 1)
                                {
                                    throw new Exception($"Unsupported '{agentConfig.Name}' vehicle asset bundle, only 1 asset expected");
                                }

                                // TODO: make this async
                                if (!AssetBundle.GetAllLoadedAssetBundles().Contains(textureBundle))
                                {
                                    textureBundle?.LoadAllAssets();
                                }

                                agentConfig.Prefab = vehicleBundle.LoadAsset <GameObject>(vehicleAssets[0]);
                                cachedVehicles.Add(agentConfig.Name, agentConfig.Prefab);
                            }
                            finally
                            {
                                textureBundle?.Unload(false);
                                vehicleBundle.Unload(false);
                            }
                        }
                    }

                    var sim = CreateSimulationManager();

                    Instance.CurrentSimulation        = simulation;
                    Instance.CurrentSimulation.Status = "Running";
                    // Notify WebUI simulation is running
                    NotificationManager.SendNotification("simulation",
                                                         SimulationResponse.Create(Loader.Instance.CurrentSimulation),
                                                         Loader.Instance.CurrentSimulation.Owner);

                    if (Instance.SimConfig.Clusters.Length == 0)
                    {
                        // Flash main window to let user know simulation is ready
                        WindowFlasher.Flash();
                    }
                }
                catch (ZipException ex)
                {
                    Debug.Log($"Failed to start '{simulation.Name}' simulation - out of date asset bundles");
                    Debug.LogException(ex);

                    // NOTE: In case of failure we have to update Simulation state
                    simulation.Status = "Invalid";
                    simulation.Error  = "Out of date Vehicle AssetBundle. Please check content website for updated bundle or rebuild the bundle.";
                    db.Update(simulation);

                    // TODO: take ex.Message and append it to response here
                    NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);

                    ResetLoaderScene();
                }
                catch (Exception ex)
                {
                    Debug.Log($"Failed to start '{simulation.Name}' simulation");
                    Debug.LogException(ex);

                    // NOTE: In case of failure we have to update Simulation state
                    simulation.Status = "Invalid";
                    simulation.Error  = ex.Message;
                    db.Update(simulation);

                    // TODO: take ex.Message and append it to response here
                    NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);

                    ResetLoaderScene();
                }
            }
        }
コード例 #3
0
ファイル: Loader.cs プロジェクト: team19032/team19032
        public static void StartAsync(SimulationModel simulation)
        {
            Debug.Assert(Instance.CurrentSimulation == null);

            Instance.Actions.Enqueue(() =>
            {
                using (var db = DatabaseManager.Open())
                {
                    AssetBundle textureBundle = null;
                    AssetBundle mapBundle     = null;
                    try
                    {
                        if (Config.Headless && (simulation.Headless.HasValue && !simulation.Headless.Value))
                        {
                            throw new Exception("Simulator is configured to run in headless mode, only headless simulations are allowed");
                        }

                        simulation.Status = "Starting";
                        NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);
                        Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.PROGRESS);

                        Instance.SimConfig = new SimulationConfig()
                        {
                            Name           = simulation.Name,
                            Clusters       = db.Single <ClusterModel>(simulation.Cluster).Ips.Split(',').Where(c => c != "127.0.0.1").ToArray(),
                            ClusterName    = db.Single <ClusterModel>(simulation.Cluster).Name,
                            ApiOnly        = simulation.ApiOnly.GetValueOrDefault(),
                            Headless       = simulation.Headless.GetValueOrDefault(),
                            Interactive    = simulation.Interactive.GetValueOrDefault(),
                            TimeOfDay      = simulation.TimeOfDay.GetValueOrDefault(new DateTime(1980, 3, 24, 12, 0, 0)),
                            Rain           = simulation.Rain.GetValueOrDefault(),
                            Fog            = simulation.Fog.GetValueOrDefault(),
                            Wetness        = simulation.Wetness.GetValueOrDefault(),
                            Cloudiness     = simulation.Cloudiness.GetValueOrDefault(),
                            UseTraffic     = simulation.UseTraffic.GetValueOrDefault(),
                            UsePedestrians = simulation.UsePedestrians.GetValueOrDefault(),
                            Seed           = simulation.Seed,
                        };

                        if (simulation.Vehicles == null || simulation.Vehicles.Length == 0 || simulation.ApiOnly.GetValueOrDefault())
                        {
                            Instance.SimConfig.Agents = Array.Empty <AgentConfig>();
                        }
                        else
                        {
                            Instance.SimConfig.Agents = simulation.Vehicles.Select(v =>
                            {
                                var vehicle = db.SingleOrDefault <VehicleModel>(v.Vehicle);

                                var config = new AgentConfig()
                                {
                                    Name        = vehicle.Name,
                                    Url         = vehicle.Url,
                                    AssetBundle = vehicle.LocalPath,
                                    Connection  = v.Connection,
                                    Sensors     = vehicle.Sensors,
                                };

                                if (!string.IsNullOrEmpty(vehicle.BridgeType))
                                {
                                    config.Bridge = Config.Bridges.Find(bridge => bridge.Name == vehicle.BridgeType);
                                    if (config.Bridge == null)
                                    {
                                        throw new Exception($"Bridge {vehicle.BridgeType} not found");
                                    }
                                }

                                return(config);
                            }).ToArray();
                        }

                        // load environment
                        if (Instance.SimConfig.ApiOnly)
                        {
                            var api  = Instantiate(Instance.ApiManagerPrefab);
                            api.name = "ApiManager";

                            Instance.CurrentSimulation = simulation;

                            // ready to go!
                            Instance.CurrentSimulation.Status = "Running";
                            NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);

                            Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.READY);
                        }
                        else
                        {
                            var mapModel      = db.Single <MapModel>(simulation.Map);
                            var mapBundlePath = mapModel.LocalPath;
                            mapBundle         = null;
                            textureBundle     = null;

                            ZipFile zip = new ZipFile(mapBundlePath);
                            {
                                string manfile;
                                ZipEntry entry = zip.GetEntry("manifest");
                                using (var ms = zip.GetInputStream(entry))
                                {
                                    int streamSize = (int)entry.Size;
                                    byte[] buffer  = new byte[streamSize];
                                    streamSize     = ms.Read(buffer, 0, streamSize);
                                    manfile        = Encoding.UTF8.GetString(buffer);
                                }

                                Manifest manifest = new Deserializer().Deserialize <Manifest>(manfile);

                                if (manifest.bundleFormat != BundleConfig.MapBundleFormatVersion)
                                {
                                    zip.Close();

                                    // TODO: proper exception
                                    throw new ZipException("BundleFormat version mismatch");
                                }

                                if (zip.FindEntry($"{manifest.bundleGuid}_environment_textures", false) != -1)
                                {
                                    var texStream = zip.GetInputStream(zip.GetEntry($"{manifest.bundleGuid}_environment_textures"));
                                    textureBundle = AssetBundle.LoadFromStream(texStream, 0, 1 << 20);
                                }

                                string platform = SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows ? "windows" : "linux";
                                var mapStream   = zip.GetInputStream(zip.GetEntry($"{manifest.bundleGuid}_environment_main_{platform}"));
                                mapBundle       = AssetBundle.LoadFromStream(mapStream, 0, 1 << 20);

                                if (mapBundle == null)
                                {
                                    throw new Exception($"Failed to load environment from '{mapModel.Name}' asset bundle");
                                }

                                textureBundle?.LoadAllAssets();

                                var scenes = mapBundle.GetAllScenePaths();
                                if (scenes.Length != 1)
                                {
                                    throw new Exception($"Unsupported environment in '{mapModel.Name}' asset bundle, only 1 scene expected");
                                }

                                var sceneName = Path.GetFileNameWithoutExtension(scenes[0]);
                                Instance.SimConfig.MapName = sceneName;
                                Instance.SimConfig.MapUrl  = mapModel.Url;

                                var isMasterSimulation = Instance.SimConfig.Clusters.Length > 0;
                                var loader             =
                                    SceneManager.LoadSceneAsync(sceneName,
                                                                isMasterSimulation? LoadSceneMode.Additive : LoadSceneMode.Single);
                                loader.completed += op =>
                                {
                                    if (op.isDone)
                                    {
                                        if (isMasterSimulation)
                                        {
                                            SceneManager.SetActiveScene(SceneManager.GetSceneByName(sceneName));
                                        }
                                        textureBundle?.Unload(false);
                                        mapBundle.Unload(false);
                                        zip.Close();
                                        SetupScene(simulation);
                                    }
                                };
                            }
                        }
                    }
                    catch (ZipException ex)
                    {
                        Debug.Log($"Failed to start '{simulation.Name}' simulation");
                        Debug.LogException(ex);

                        // NOTE: In case of failure we have to update Simulation state
                        simulation.Status = "Invalid";
                        simulation.Error  = "Out of date Map AssetBundle. Please check content website for updated bundle or rebuild the bundle.";
                        db.Update(simulation);

                        if (SceneManager.GetActiveScene().name != Instance.LoaderScene)
                        {
                            SceneManager.LoadScene(Instance.LoaderScene);
                        }

                        textureBundle?.Unload(false);
                        mapBundle?.Unload(false);
                        AssetBundle.UnloadAllAssetBundles(true);
                        Instance.CurrentSimulation = null;

                        // TODO: take ex.Message and append it to response here
                        NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);
                    }
                    catch (Exception ex)
                    {
                        Debug.Log($"Failed to start '{simulation.Name}' simulation");
                        Debug.LogException(ex);

                        // NOTE: In case of failure we have to update Simulation state
                        simulation.Status = "Invalid";
                        simulation.Error  = ex.Message;
                        db.Update(simulation);

                        if (SceneManager.GetActiveScene().name != Instance.LoaderScene)
                        {
                            SceneManager.LoadScene(Instance.LoaderScene);
                        }

                        textureBundle?.Unload(false);
                        mapBundle?.Unload(false);
                        AssetBundle.UnloadAllAssetBundles(true);
                        Instance.CurrentSimulation = null;

                        // TODO: take ex.Message and append it to response here
                        NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);
                    }
                }
            });
        }
コード例 #4
0
        /// <summary>
        /// Download required for the simulation vehicle bundles from the server
        /// </summary>
        /// <param name="load">Load command from the server</param>
        /// <param name="mapBundlePath">Path where the map bundle will be saved</param>
        private void LoadMapBundle(Commands.Load load, string mapBundlePath)
        {
            var vehicleBundles = new List <string>();

            DownloadVehicleBundles(load, vehicleBundles, () =>
            {
                if (MasterPeer == null)
                {
                    Debug.LogWarning("Master peer has disconnected while loading the simulation scene.");
                    Loader.ResetLoaderScene();
                    return;
                }
                var zip = new ZipFile(mapBundlePath);
                {
                    string manfile;
                    ZipEntry entry = zip.GetEntry("manifest");
                    using (var ms = zip.GetInputStream(entry))
                    {
                        int streamSize = (int)entry.Size;
                        byte[] buffer  = new byte[streamSize];
                        streamSize     = ms.Read(buffer, 0, streamSize);
                        manfile        = Encoding.UTF8.GetString(buffer);
                    }

                    Manifest manifest = new Deserializer().Deserialize <Manifest>(manfile);

                    AssetBundle textureBundle = null;

                    if (zip.FindEntry(($"{manifest.assetGuid}_environment_textures"), false) != -1)
                    {
                        var texStream = zip.GetInputStream(zip.GetEntry($"{manifest.assetGuid}_environment_textures"));
                        textureBundle = AssetBundle.LoadFromStream(texStream, 0, 1 << 20);
                    }

                    string platform = SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows
                        ? "windows"
                        : "linux";
                    var mapStream =
                        zip.GetInputStream(zip.GetEntry($"{manifest.assetGuid}_environment_main_{platform}"));
                    var mapBundle = AssetBundle.LoadFromStream(mapStream, 0, 1 << 20);

                    if (mapBundle == null)
                    {
                        throw new Exception($"Failed to load environment from '{load.MapName}' asset bundle");
                    }

                    textureBundle?.LoadAllAssets();

                    var scenes = mapBundle.GetAllScenePaths();
                    if (scenes.Length != 1)
                    {
                        throw new Exception(
                            $"Unsupported environment in '{load.MapName}' asset bundle, only 1 scene expected");
                    }

                    var sceneName = Path.GetFileNameWithoutExtension(scenes[0]);

                    var loader        = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
                    loader.completed += op =>
                    {
                        if (op.isDone)
                        {
                            SceneManager.SetActiveScene(SceneManager.GetSceneByName(sceneName));
                            textureBundle?.Unload(false);
                            mapBundle.Unload(false);
                            zip.Close();

                            try
                            {
                                var prefabs = LoadVehicleBundles(vehicleBundles);

                                Loader.Instance.SimConfig = new SimulationConfig()
                                {
                                    Name           = load.Name,
                                    ApiOnly        = load.ApiOnly,
                                    Headless       = load.Headless,
                                    Interactive    = load.Interactive,
                                    TimeOfDay      = DateTime.ParseExact(load.TimeOfDay, "o", CultureInfo.InvariantCulture),
                                    Rain           = load.Rain,
                                    Fog            = load.Fog,
                                    Wetness        = load.Wetness,
                                    Cloudiness     = load.Cloudiness,
                                    UseTraffic     = load.UseTraffic,
                                    UsePedestrians = load.UsePedestrians,
                                    Agents         = load.Agents.Zip(prefabs, (agent, prefab) =>
                                    {
                                        var config = new AgentConfig()
                                        {
                                            Name       = agent.Name,
                                            Prefab     = prefab,
                                            Connection = agent.Connection,
                                            Sensors    = agent.Sensors,
                                        };

                                        if (!string.IsNullOrEmpty(agent.Bridge))
                                        {
                                            config.Bridge =
                                                Web.Config.Bridges.Find(bridge => bridge.Name == agent.Bridge);
                                            if (config.Bridge == null)
                                            {
                                                throw new Exception($"Bridge {agent.Bridge} not found");
                                            }
                                        }

                                        return(config);
                                    }).ToArray(),
                                };

                                Loader.Instance.CurrentSimulation        = CreateSimulationModel(Loader.Instance.SimConfig);
                                Loader.Instance.CurrentSimulation.Status = "Running";
                                if (Loader.Instance.SimConfig.ApiOnly)
                                {
                                    var api  = Instantiate(Loader.Instance.ApiManagerPrefab);
                                    api.name = "ApiManager";
                                }

                                var simulatorManager = Loader.CreateSimulatorManager();
                                if (load.UseSeed)
                                {
                                    simulatorManager.Init(load.Seed);
                                }
                                else
                                {
                                    simulatorManager.Init();
                                }
                                InitializeSimulation(simulatorManager.gameObject);

                                // Notify WebUI simulation is running
                                NotificationManager.SendNotification("simulation",
                                                                     SimulationResponse.Create(Loader.Instance.CurrentSimulation),
                                                                     Loader.Instance.CurrentSimulation.Owner);

                                Debug.Log($"Client ready to start");

                                var result = new Commands.LoadResult()
                                {
                                    Success = true,
                                };

                                Loader.Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.READY);
                                if (MasterPeer == null)
                                {
                                    Debug.LogWarning("Master peer has disconnected while loading the simulation scene.");
                                    Loader.ResetLoaderScene();
                                    return;
                                }
                                var resultData     = PacketsProcessor.Write(result);
                                var message        = MessagesPool.Instance.GetMessage(resultData.Length);
                                message.AddressKey = Key;
                                message.Content.PushBytes(resultData);
                                message.Type = DistributedMessageType.ReliableOrdered;
                                UnicastMessage(MasterPeer.PeerEndPoint, message);

                                State = SimulationState.Ready;
                            }
                            catch (Exception ex)
                            {
                                Debug.LogException(ex);

                                var err = new Commands.LoadResult()
                                {
                                    Success      = false,
                                    ErrorMessage = ex.ToString(),
                                };
                                var errData        = PacketsProcessor.Write(err);
                                var message        = MessagesPool.Instance.GetMessage(errData.Length);
                                message.AddressKey = Key;
                                message.Content.PushBytes(errData);
                                message.Type = DistributedMessageType.ReliableOrdered;
                                UnicastMessage(MasterPeer.PeerEndPoint, message);

                                Loader.ResetLoaderScene();
                            }
                        }
                    };
                }
            });
        }
コード例 #5
0
        static void SetupScene(SimulationModel simulation)
        {
            using (var db = DatabaseManager.Open())
            {
                try
                {
                    foreach (var agentConfig in Instance.SimConfig.Agents)
                    {
                        var bundlePath = agentConfig.AssetBundle;

                        // TODO: make this async
                        var vehicleBundle = AssetBundle.LoadFromFile(bundlePath);
                        if (vehicleBundle == null)
                        {
                            throw new Exception($"Failed to load '{agentConfig.Name}' vehicle asset bundle");
                        }

                        try
                        {
                            var vehicleAssets = vehicleBundle.GetAllAssetNames();
                            if (vehicleAssets.Length != 1)
                            {
                                throw new Exception($"Unsupported '{agentConfig.Name}' vehicle asset bundle, only 1 asset expected");
                            }

                            // TODO: make this async
                            agentConfig.Prefab = vehicleBundle.LoadAsset <GameObject>(vehicleAssets[0]);
                        }
                        finally
                        {
                            vehicleBundle.Unload(false);
                        }
                    }

                    var sim = CreateSimulationManager();

                    // TODO: connect to cluster instances
                    //if (Instance.SimConfig.Clusters.Length > 0)
                    //{
                    //    SimulatorManager.SetTimeScale(0);

                    //    Instance.PendingSimulation = simulation;

                    //    StartNetworkMaster();
                    //    Instance.Master.AddClients(Instance.SimConfig.Clusters);
                    //}
                    //else
                    {
                        Instance.CurrentSimulation = simulation;

                        // Notify WebUI simulation is running
                        Instance.CurrentSimulation.Status = "Running";
                        NotificationManager.SendNotification("simulation", SimulationResponse.Create(Instance.CurrentSimulation), Instance.CurrentSimulation.Owner);

                        // Flash main window to let user know simulation is ready
                        WindowFlasher.Flash();
                    }
                }
                catch (Exception ex)
                {
                    Debug.Log($"Failed to start '{simulation.Name}' simulation");
                    Debug.LogException(ex);

                    // NOTE: In case of failure we have to update Simulation state
                    simulation.Status = "Invalid";
                    db.Update(simulation);

                    // TODO: take ex.Message and append it to response here
                    NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);

                    ResetLoaderScene();
                }
            }
        }
コード例 #6
0
        public static void StartAsync(SimulationModel simulation)
        {
            Debug.Assert(Instance.CurrentSimulation == null);

            Instance.Actions.Enqueue(() =>
            {
                using (var db = DatabaseManager.Open())
                {
                    AssetBundle mapBundle = null;
                    try
                    {
                        if (Config.Headless && (simulation.Headless.HasValue && !simulation.Headless.Value))
                        {
                            throw new Exception("Simulator is configured to run in headless mode, only headless simulations are allowed");
                        }

                        simulation.Status = "Starting";
                        NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);
                        Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.PROGRESS);

                        Instance.SimConfig = new SimulationConfig()
                        {
                            Name           = simulation.Name,
                            Clusters       = db.Single <ClusterModel>(simulation.Cluster).Ips.Split(',').Where(c => c != "127.0.0.1").ToArray(),
                            ClusterName    = db.Single <ClusterModel>(simulation.Cluster).Name,
                            ApiOnly        = simulation.ApiOnly.GetValueOrDefault(),
                            Headless       = simulation.Headless.GetValueOrDefault(),
                            Interactive    = simulation.Interactive.GetValueOrDefault(),
                            TimeOfDay      = simulation.TimeOfDay.GetValueOrDefault(DateTime.MinValue.AddHours(12)),
                            Rain           = simulation.Rain.GetValueOrDefault(),
                            Fog            = simulation.Fog.GetValueOrDefault(),
                            Wetness        = simulation.Wetness.GetValueOrDefault(),
                            Cloudiness     = simulation.Cloudiness.GetValueOrDefault(),
                            UseTraffic     = simulation.UseTraffic.GetValueOrDefault(),
                            UsePedestrians = simulation.UsePedestrians.GetValueOrDefault(),
                            Seed           = simulation.Seed,
                        };

                        if (simulation.Vehicles == null || simulation.Vehicles.Length == 0 || simulation.ApiOnly.GetValueOrDefault())
                        {
                            Instance.SimConfig.Agents = Array.Empty <AgentConfig>();
                        }
                        else
                        {
                            Instance.SimConfig.Agents = simulation.Vehicles.Select(v =>
                            {
                                var vehicle = db.SingleOrDefault <VehicleModel>(v.Vehicle);

                                var config = new AgentConfig()
                                {
                                    Name        = vehicle.Name,
                                    AssetBundle = vehicle.LocalPath,
                                    Connection  = v.Connection,
                                    Sensors     = vehicle.Sensors,
                                };

                                if (!string.IsNullOrEmpty(vehicle.BridgeType))
                                {
                                    config.Bridge = Config.Bridges.Find(bridge => bridge.Name == vehicle.BridgeType);
                                    if (config.Bridge == null)
                                    {
                                        throw new Exception($"Bridge {vehicle.BridgeType} not found");
                                    }
                                }

                                return(config);
                            }).ToArray();
                        }

                        // load environment
                        if (Instance.SimConfig.ApiOnly)
                        {
                            var api  = Instantiate(Instance.ApiManagerPrefab);
                            api.name = "ApiManager";

                            Instance.CurrentSimulation = simulation;

                            // ready to go!
                            Instance.CurrentSimulation.Status = "Running";
                            NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);

                            Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.READY);
                        }
                        else
                        {
                            var mapModel      = db.Single <MapModel>(simulation.Map);
                            var mapBundlePath = mapModel.LocalPath;

                            // TODO: make this async
                            mapBundle = AssetBundle.LoadFromFile(mapBundlePath);
                            if (mapBundle == null)
                            {
                                throw new Exception($"Failed to load environment from '{mapModel.Name}' asset bundle");
                            }

                            var scenes = mapBundle.GetAllScenePaths();
                            if (scenes.Length != 1)
                            {
                                throw new Exception($"Unsupported environment in '{mapModel.Name}' asset bundle, only 1 scene expected");
                            }

                            var sceneName = Path.GetFileNameWithoutExtension(scenes[0]);
                            Instance.SimConfig.MapName = sceneName;

                            var loader        = SceneManager.LoadSceneAsync(sceneName);
                            loader.completed += op =>
                            {
                                if (op.isDone)
                                {
                                    mapBundle.Unload(false);
                                    SetupScene(simulation);
                                }
                            };
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.Log($"Failed to start '{simulation.Name}' simulation");
                        Debug.LogException(ex);

                        // NOTE: In case of failure we have to update Simulation state
                        simulation.Status = "Invalid";
                        db.Update(simulation);

                        if (SceneManager.GetActiveScene().name != Instance.LoaderScene)
                        {
                            SceneManager.LoadScene(Instance.LoaderScene);
                        }
                        mapBundle?.Unload(false);
                        AssetBundle.UnloadAllAssetBundles(true);
                        Instance.CurrentSimulation = null;

                        // TODO: take ex.Message and append it to response here
                        NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);
                    }
                }
            });
        }