Ejemplo n.º 1
0
        /// <summary>
        /// Function to select a target for the tank.
        /// It requires at least 2 buildings from a neighbourhood to be eligible.
        /// </summary>
        /// <returns></returns>
        private IVisualizedObject SelectTarget()
        {
            List <NeighbourhoodModel> randomNeighbourhoodQuery = CityManager.Instance.GameModel.Neighbourhoods
                                                                 .Where(neighbourhoodModel =>
                                                                        neighbourhoodModel.VisualizedObjects.Count(visualizedObject =>
                                                                                                                   visualizedObject is VisualizedBuildingModel) >= _minimumBuildings).ToList();

            if (TeamManager.Instance.SelectedTeam != null)
            {
                randomNeighbourhoodQuery =
                    randomNeighbourhoodQuery.Where(x => x.Team == TeamManager.Instance.SelectedTeam).ToList();
            }

            // No target found. Tank is probably going in standby mode now.
            if (randomNeighbourhoodQuery.Count == 0)
            {
                _foundTargets = false;
                return(null);
            }

            // Pick a random neighbourhood from the list
            NeighbourhoodModel randomNeighbourhoodModel =
                randomNeighbourhoodQuery.PickRandom();

            // We found a target and it's a building. Return the target.
            IVisualizedObject obj = randomNeighbourhoodModel.VisualizedObjects
                                    .First(visualizedObject =>
                                           visualizedObject.GameObject != null && visualizedObject is VisualizedBuildingModel);

            _foundTargets = true;
            return(obj);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Function to spawn a new building
        /// </summary>
        /// <param name="tile"></param>
        /// <param name="size"></param>
        /// <param name="age"></param>
        /// <param name="neighbourhood"></param>
        /// <param name="staging"></param>
        /// <returns></returns>
        public GameObject SpawnBuilding(Tile tile, int size, int age, NeighbourhoodModel neighbourhood, bool staging)
        {
            // Default rotation
            Quaternion buildingRotation = Quaternion.Euler(0, 90f, 0);
            GameObject building;

            if (staging)
            {
                building = AssetsManager.Instance.GetPredefinedPrefab(AssetsManager.PrefabType.StagingBuilding);
            }
            else
            {
                // Extract the tuple with the building prefab and the rotation
                (GameObject buildingObject, float rotation) = AssetsManager.Instance.GetBuildingPrefab(size, age);
                buildingRotation = Quaternion.Euler(0, rotation, 0);
                building         = buildingObject;
            }

            // Spawn the prefab with the correct location and rotation
            building = Instantiate(building, new Vector3(tile.X, 0.5f, tile.Z), buildingRotation);

            // Set the name of the object so we can use it later as a reference
            building.name = $"neighbourhood-{neighbourhood.Name}";
            return(building);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Function to add a new visualized object to the game.
        /// </summary>
        /// <param name="neighbourhoodName"></param>
        /// <param name="newVisualizedObject"></param>
        private void AddBuilding(string neighbourhoodName, IVisualizedObject newVisualizedObject)
        {
            // We only care about buildings in this manager
            if (!(newVisualizedObject is IVisualizedBuilding))
            {
                return;
            }

            NeighbourhoodModel neighbourhood =
                GameModel.Neighbourhoods.SingleOrDefault(x => x.Name == neighbourhoodName);

            if (neighbourhood == null)
            {
                Debug.LogWarning($"Adding object went wrong! Neighbourhood {neighbourhoodName} does not exists!");
                return;
            }

            // Check if there are buildings with the same identifier.
            List <IVisualizedBuilding> existingVisualizedObjects = neighbourhood.VisualizedObjects
                                                                   .OfType <IVisualizedBuilding>().Where(x =>
                                                                                                         x.Identifier == newVisualizedObject.Identifier)
                                                                   .ToList();

            // Destroy every building that has the same identifier.
            foreach (IVisualizedBuilding visualizedObject in existingVisualizedObjects)
            {
                GridManager.Instance.DestroyBuilding(visualizedObject);
                neighbourhood.VisualizedObjects.Remove(visualizedObject);
            }

            // TODO: We actually need to check if there are destroyed grass tiles, but haven't found a solution for it yet.
            neighbourhood.VisualizedObjects.Add(newVisualizedObject);
            GridManager.Instance.DestroyBlock(neighbourhood, false);
            GridManager.Instance.SpawnNeighbourhood(neighbourhood);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Function to parse all the JSON data and convert it into a GameModel object.
        /// If API structure changes happen it should be adjusted in here.
        /// </summary>
        /// <param name="jsonString"></param>
        /// <returns></returns>
        public static GameModel ParseGameModel(string jsonString)
        {
            HashSet <NeighbourhoodModel> neighbourhoodModels = new HashSet <NeighbourhoodModel>();
            HashSet <string>             teams = new HashSet <string>();
            JSONNode jsonOBj = JSON.Parse(jsonString);

            // Loop through all layers
            List <VisualLayerModel> visualLayerModels = jsonOBj["layers"].Children
                                                        .Select(layer => new VisualLayerModel {
                Icon = layer["icon"], Name = layer["layerType"]
            }).ToList();

            // Loop through neighboorhoods
            foreach (JSONNode neighbourhoodJsonObj in jsonOBj["neighbourhoods"].Children)
            {
                NeighbourhoodModel neighbourhood = ParseNeighbourhoodModel(neighbourhoodJsonObj);
                neighbourhoodModels.Add(neighbourhood);
            }

            // Loop through teams
            foreach (JSONNode team in jsonOBj["teams"])
            {
                teams.Add(team);
            }

            GameModel gameModel = new GameModel
            {
                Neighbourhoods = neighbourhoodModels, Layers = visualLayerModels, Teams = teams
            };

            return(gameModel);
        }
        /// <summary>
        /// Function to highlight vehicles when clicked.
        /// </summary>
        /// <param name="clickedObject"></param>
        public void HighlightVehicle(GameObject clickedObject)
        {
            InfoPanel.gameObject.SetActive(true);
            try
            {
                string infoText = string.Empty;
                if (clickedObject.CompareTag("Tank"))
                {
                    TankNavigator tankNavigator = clickedObject.GetComponent <TankNavigator>();
                    if (tankNavigator.IsStandby || tankNavigator.Target == null)
                    {
                        infoText = "Tank is in stand-by mode";
                    }
                    else
                    {
                        NeighbourhoodModel neighbourhoodModel = CityManager.Instance.GameModel.Neighbourhoods
                                                                .Select(x => x).SingleOrDefault(x =>
                                                                                                x.VisualizedObjects.Contains(tankNavigator.Target));
                        string firingEnabled = tankNavigator.IsFiringEnabled ? "yes" : "no";
                        if (neighbourhoodModel != null)
                        {
                            infoText = $"Target: {neighbourhoodModel.Name}\r\nFiring enabled: {firingEnabled}";
                        }
                    }
                }
                else
                {
                    TrafficManager.Vehicle v =
                        TrafficManager.Instance.Vehicles.Single(x => x.VehicleGameObject == clickedObject);

                    // Check if vehicle is visible
                    if (clickedObject.GetComponentsInChildren <Renderer>().Any(x => !x.enabled))
                    {
                        return;
                    }

                    infoText = v.NeighbourhoodModel == null
                                                ? "Vehicle driving towards deleted neighbourhood"
                                                : $"Vehicle driving towards {v.NeighbourhoodModel.Name}";
                }

                InfoPanel.GetComponentInChildren <TMP_Text>().text = infoText;
                NavMeshAgent agent = clickedObject.GetComponent <NavMeshAgent>();
                if (agent != null)
                {
                    CameraController.Instance.FollowTarget(clickedObject, agent.speed * 0.1f);
                }

                Renderer[] renderComponents = clickedObject.GetComponentsInChildren <Renderer>();
                foreach (Renderer renderComponent in renderComponents)
                {
                    _clickedObjects.Add(renderComponent, renderComponent.material.color);
                    renderComponent.material.color = Color.green;
                }
            }
            catch (Exception e)
            {
                Debug.LogError($"[OnObjectClickManager] {e.Message}");
            }
        }
Ejemplo n.º 6
0
 public Vehicle(GameObject vehicleGameObject, VisualizedVehicleModel vehicleModel,
                NeighbourhoodModel neighbourhoodModel, string vehicleName)
 {
     VehicleGameObject  = vehicleGameObject;
     VehicleModel       = vehicleModel;
     NeighbourhoodModel = neighbourhoodModel;
     VehicleName        = vehicleName;
 }
Ejemplo n.º 7
0
 private void SetMaterials(NeighbourhoodModel neighbourhood, bool fade)
 {
     foreach (IVisualizedObject visualizedObject in neighbourhood.VisualizedObjects.Where(visualizedObject =>
                                                                                          visualizedObject.GameObject != null))
     {
         SetMaterials(visualizedObject.GameObject, fade);
     }
 }
Ejemplo n.º 8
0
 /// <summary>
 /// Function to add a new neighbourhood to the game and spawn them.
 /// </summary>
 /// <param name="newNeighbourhood"></param>
 private void AddNeighbourhood(NeighbourhoodModel newNeighbourhood)
 {
     if (GameModel.Neighbourhoods.Any(neighbourhoodModel =>
                                      neighbourhoodModel.Name != newNeighbourhood.Name))
     {
         GridManager.Instance.SpawnNeighbourhood(newNeighbourhood);
         GameModel.Neighbourhoods.Add(newNeighbourhood);
     }
 }
        /// <summary>
        /// Function to highlight a neighbourhood when clicked.
        /// </summary>
        /// <param name="clickedObject"></param>
        /// <param name="showInfoPanel"></param>
        public void HighlightNeighbourhood(GameObject clickedObject, bool showInfoPanel = true)
        {
            if (showInfoPanel)
            {
                string neighbourhoodName = clickedObject.name.Replace("neighbourhood-", "");
                string infoText          = $"Neighbourhood: {neighbourhoodName}";
                try
                {
                    if (clickedObject.CompareTag("Building"))
                    {
                        NeighbourhoodModel neighboorhoud =
                            CityManager.Instance.GameModel.Neighbourhoods.SingleOrDefault(
                                (x => x.Name == neighbourhoodName));
                        if (neighboorhoud != null)
                        {
                            IVisualizedObject visualizedObject =
                                neighboorhoud.VisualizedObjects.SingleOrDefault(x => x.GameObject == clickedObject);
                            _selectedObject = visualizedObject;
                            string days = neighboorhoud.Age == 1 ? "day" : "days";
                            infoText =
                                $"Neighbourhood: {neighbourhoodName}\r\nAge: {neighboorhoud.Age} {days}";
                            VisualLayerModel selectedLayer = LayerManager.Instance.SelectedLayer;
                            if (visualizedObject is IVisualizedBuilding visualizedBuilding)
                            {
                                DestroyButton.SetActive(true);
                                OpenButton.SetActive(true);
                                if (selectedLayer != null)
                                {
                                    // Only enable destroy button for buildings
                                    infoText =
                                        $"Neighbourhood: {neighbourhoodName}\r\n{selectedLayer.Name.Replace("Layer", "")}: {visualizedBuilding.LayerValues[selectedLayer.Name]} / {neighboorhoud.LayerValues.Single(x => x.LayerType == selectedLayer.Name).MaxValue} ";
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Debug.LogError($"[OnObjectClickManager] {e.Message}");
                }
                finally
                {
                    InfoPanel.GetComponentInChildren <TMP_Text>().text = infoText;
                    InfoPanel.gameObject.SetActive(true);
                }
            }

            Renderer[] renderComponents = clickedObject.GetComponentsInChildren <Renderer>();
            foreach (Renderer renderComponent in renderComponents)
            {
                _clickedObjects.Add(renderComponent, renderComponent.material.color);
                renderComponent.material.color = Color.green;
            }
        }
        /// <summary>
        /// Function to bind a neighbourhood to a button
        /// </summary>
        /// <param name="neighbourhoodModel"></param>
        /// <param name="button"></param>
        private static void SetButton(NeighbourhoodModel neighbourhoodModel, Button button)
        {
            TMP_Text text = button.GetComponentInChildren <TMP_Text>();

            text.text = neighbourhoodModel.Name;

            button.gameObject.SetActive(true);

            // Remove all onclick listeners and create a new one
            button.onClick.RemoveAllListeners();
            button.onClick.AddListener(() => { OnButtonClick(neighbourhoodModel); });
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Function to remove the first building of a neighbourhood. This only happens in-game, no API calls involved!
        /// </summary>
        /// <param name="serviceName"></param>
        public void RemoveBuilding(string serviceName)
        {
            NeighbourhoodModel  neighbourhood = CityManager.Instance.GameModel.Neighbourhoods.FirstOrDefault(x => x.Name == serviceName);
            IVisualizedBuilding building      =
                (IVisualizedBuilding)neighbourhood?.VisualizedObjects.FirstOrDefault(x => x is IVisualizedBuilding);

            if (building != null)
            {
                ApiManager.Instance.ApiUpdateEvent?.Invoke(new UpdateEventModel
                {
                    RemovedVisualizedObject = building.Identifier
                });
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Function to search for a neighbourhood.
        /// </summary>
        /// <param name="serviceName"></param>
        public void SearchNeighbourhood(string serviceName)
        {
            NeighbourhoodModel search = CityManager.Instance.GameModel.Neighbourhoods
                                        .FirstOrDefault(x => x.Name.Contains(serviceName));
            IVisualizedObject randomContainer = search?.VisualizedObjects.FirstOrDefault(x => x.GameObject != null);

            if (randomContainer == null || randomContainer.GameObject == null)
            {
                return;
            }
            CameraController.Instance.FocusOnTarget(randomContainer.GameObject.transform.position);
            OnObjectClickManager.Instance.ResetHighlighting();
            OnObjectClickManager.Instance.HighlightNeighbourhood(randomContainer.GameObject);
        }
        /// <summary>
        /// Function that is executed when a button is pressed.
        /// The player will focus with the camera on the first building of a neighbourhood
        /// </summary>
        /// <param name="neighbourhoodModel"></param>
        private static void OnButtonClick(NeighbourhoodModel neighbourhoodModel)
        {
            IVisualizedObject visualizedBuilding =
                neighbourhoodModel.VisualizedObjects.FirstOrDefault(x =>
                                                                    x is IVisualizedBuilding && x.GameObject != null);

            if (visualizedBuilding == null)
            {
                return;
            }

            CameraController.Instance.FocusOnTarget(visualizedBuilding.GameObject.transform.position);
            OnObjectClickManager.Instance.ResetHighlighting();
            OnObjectClickManager.Instance.HighlightNeighbourhood(visualizedBuilding.GameObject);
        }
        public void OpenSelectedObjectUrl()
        {
            if (!(_selectedObject is IVisualizedBuilding))
            {
                return;
            }

            NeighbourhoodModel neighbourhoodModel = CityManager.Instance.GameModel.Neighbourhoods
                                                    .Select(x => x).SingleOrDefault(x =>
                                                                                    x.VisualizedObjects.Contains(_selectedObject));

            if (neighbourhoodModel != null)
            {
                StartCoroutine(ApiManager.Instance.OpenNeighbourhoodUrl(neighbourhoodModel.Name));
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Function to de-spawn and remove a complete neighbourhood.
        /// </summary>
        /// <param name="neighbourhoodName"></param>
        private void RemoveNeighbourhood(string neighbourhoodName)
        {
            NeighbourhoodModel removedNeighbourhood =
                GameModel.Neighbourhoods.SingleOrDefault(neighbourhoodModel =>
                                                         neighbourhoodModel.Name == neighbourhoodName);

            if (removedNeighbourhood != null)
            {
                // We could find one! Now let's destroy it
                GridManager.Instance.DestroyBlock(removedNeighbourhood, true);
                GameModel.Neighbourhoods.Remove(removedNeighbourhood);
            }
            else
            {
                Debug.LogWarning(
                    $"Removing a neighbourhood went wrong! Neighbourhood {neighbourhoodName} does not exists");
            }
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Function to update an existing neighbourhood.
        /// </summary>
        /// <param name="neighbourhoodName"></param>
        /// <param name="updatedNeighbourhood"></param>
        private void UpdateNeighbourhood(string neighbourhoodName, NeighbourhoodModel updatedNeighbourhood)
        {
            NeighbourhoodModel neighbourhood =
                GameModel.Neighbourhoods.SingleOrDefault(neighbourhoodModel =>
                                                         neighbourhoodModel.Name == neighbourhoodName);

            if (neighbourhood != null)
            {
                // Update the age and layer values of the neighbourhood
                neighbourhood.Age         = updatedNeighbourhood.Age;
                neighbourhood.LayerValues = updatedNeighbourhood.LayerValues;
            }
            else
            {
                Debug.LogWarning(
                    $"Updating neighbourhood went wrong! Neighbourhood {neighbourhoodName} does not exists!");
            }
        }
Ejemplo n.º 17
0
        private static NeighbourhoodModel ParseNeighbourhoodModel(JSONNode jsonNode)
        {
            NeighbourhoodModel neighbourhood = new NeighbourhoodModel();

            neighbourhood.Name = jsonNode["name"];
            neighbourhood.Age  = jsonNode["daysOld"];
            neighbourhood.Team = jsonNode["team"];

            List <LayerValueModel> visualLayers = jsonNode["layerValues"].Children.Select(visualLayer =>
                                                                                          new LayerValueModel
            {
                MinValue  = visualLayer["minValue"],
                LayerType = visualLayer["layerType"],
                MaxValue  = visualLayer["maxValue"]
            }).ToList();

            neighbourhood.LayerValues = visualLayers;

            // Loop through all visualized objects (buildings, traffic for later, etc)
            foreach (JSONNode visualizedObjectJson in jsonNode["visualizedObjects"].Children)
            {
                Dictionary <string, double> layerValues = new Dictionary <string, double>();
                foreach (KeyValuePair <string, JSONNode> layerValue in visualizedObjectJson["layerValues"])
                {
                    layerValues.Add(layerValue.Key, layerValue.Value);
                }

                IVisualizedObject visualizedObject =
                    VisualizedObjectFactory.Build(
                        visualizedObjectJson["type"],
                        visualizedObjectJson["size"],
                        layerValues, visualizedObjectJson["identifier"]);


                neighbourhood.VisualizedObjects.Add(visualizedObject);
            }

            return(neighbourhood);
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Function to destroy a complete neighbourhood/block
        /// </summary>
        /// <param name="neighbourhood"></param>
        /// <param name="destroyEffect"></param>
        public void DestroyBlock(NeighbourhoodModel neighbourhood, bool destroyEffect)
        {
            foreach (IVisualizedObject visualizedObject in neighbourhood.VisualizedObjects
                     .Where(x => !(x is VisualizedVehicleModel)).ToList())
            {
                if (visualizedObject.GameObject == null)
                {
                    continue;
                }

                // Find all grid objects that equal to the visualized object
                List <KeyValuePair <Tile, TileObject> > gridObjects = Grid.Where(x =>
                                                                                 x.Value != null && x.Value.GameObject != null &&
                                                                                 x.Value.GameObject.Equals(visualizedObject.GameObject)).ToList();

                foreach (KeyValuePair <Tile, TileObject> gridObject in gridObjects)
                {
                    if (destroyEffect)
                    {
                        visualizedObject.GameObject.AddComponent <DestroyGridTile>().Tile = gridObject.Key;
                    }
                    else
                    {
                        Destroy(visualizedObject.GameObject);
                        visualizedObject.GameObject = null;
                        Grid[gridObject.Key]        = null;
                    }
                }

                // Remove all grass tiles from a neighbourhood that is being destroyed
                if (visualizedObject is VisualizedGrassTileModel)
                {
                    neighbourhood.VisualizedObjects.Remove(visualizedObject);
                }
            }


            Debug.Log($"[GridManager] Removed block of neighbourhood: {neighbourhood.Name}");
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Function to remove a visualized object from the game. Vehicles are excluded.
        /// </summary>
        /// <param name="neighbourhoodName"></param>
        /// <param name="identifier"></param>
        private void RemoveVisualizedBuildings(string neighbourhoodName, string identifier)
        {
            NeighbourhoodModel neighbourhood =
                GameModel.Neighbourhoods.SingleOrDefault(neighbourhoodModel =>
                                                         neighbourhoodModel.Name == neighbourhoodName);
            // Make a list of buildings we need to remove. We don't want to remove vehicles in this manager.
            List <IVisualizedBuilding> removedBuildings =
                neighbourhood?.VisualizedObjects.OfType <IVisualizedBuilding>().Where(
                    x => x.Identifier == identifier).ToList();

            if (removedBuildings != null)
            {
                foreach (IVisualizedBuilding removedBuilding in removedBuildings)
                {
                    GridManager.Instance.DestroyBuilding(removedBuilding);
                    neighbourhood.VisualizedObjects.Remove(removedBuilding);
                }
            }
            else
            {
                Debug.LogWarning($"Removing object went wrong! Neighbourhood {neighbourhoodName} does not exists.");
            }
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Function to build a neighbourhood
        /// </summary>
        /// <param name="neighbourhoodModel"></param>
        public void SpawnNeighbourhood(NeighbourhoodModel neighbourhoodModel)
        {
            // If there are no visualized objects, destroy the block
            if (neighbourhoodModel.VisualizedObjects.Count < 1)
            {
                DestroyBlock(neighbourhoodModel, false);
                return;
            }

            // Make a list of buildings
            List <IVisualizedBuilding> visualizedObjects =
                neighbourhoodModel.VisualizedObjects.OfType <IVisualizedBuilding>().ToList();

            // Calculate total tile count we need to spawn this building (if building is wider than the TileSize)
            int tileCount = GetTotalTilesRequired(visualizedObjects, neighbourhoodModel.Age) + 1;

            // Find the amount of tiles we need to spawn this neighbourhood
            List <Tile> tiles = FindTiles(tileCount);

            if (tiles.Count != tileCount)
            {
                // Can't spawn the neighbourhood. Not enough tiles per street.
                Debug.LogError(
                    "Building block went wrong. Not enough tiles!\r\nIncrease the TilesPerStreet in the config.json");
                return;
            }

            // Set spawn offset and tile index to 0
            float spawnOffsetX = 0;
            int   tileIndex    = 0;

            // Loop through all the visualized objects
            for (int index = 0; index < visualizedObjects.Count; index++)
            {
                // Get the correct tile
                Tile tile = tiles[tileIndex];
                // If the tile is already filled, destroy it.
                if (Grid[tile] != null && Grid[tile].GameObject != null)
                {
                    Destroy(Grid[tile].GameObject);
                }

                // Spawn a building at this street
                GameObject building = SpawnBuilding(tile, visualizedObjects[index].Size, neighbourhoodModel.Age,
                                                    neighbourhoodModel, visualizedObjects[index] is VisualizedStagingBuildingModel);
                // Set the correct tile information
                Grid[tile] = new TileObject
                {
                    GameObject = building, ObjectType = ObjectType.Building
                };
                tileIndex++;

                // Check how many tiles we need to spawn this building
                int tilesRequired = GetTilesRequiredForBuilding(building);

                // Check if we need more than 1 tile for this building
                if (tilesRequired > 1)
                {
                    if (Physics.Raycast(building.transform.position, Vector3.left, out RaycastHit hit, 5))
                    {
                        // Check if there is grass or a road next to us and at the distance so we can align our building
                        if (hit.transform.gameObject.CompareTag("Grass") || hit.transform.gameObject.CompareTag("Road"))
                        {
                            spawnOffsetX += hit.distance;
                        }
                    }
                    // We might need to move the building to align perfectly like calculated in the raycast.
                    building.transform.position = new Vector3(building.transform.position.x + spawnOffsetX,
                                                              building.transform.position.y, building.transform.position.z);
                    for (int i = 1; i < tilesRequired; i++)
                    {
                        // If we need more than 1 tile fill the next tiles as well
                        // This will only happen if the building is wider than the TileSize
                        Tile tile2 = tiles[tileIndex];
                        // Destroy existing object if it's not the building we are trying to spawn
                        if (Grid[tile2] != null && !Grid[tile2].GameObject.Equals(building))
                        {
                            Destroy(Grid[tile2].GameObject);
                        }

                        // Set the correct tile information
                        Grid[tile2] = new TileObject
                        {
                            GameObject = building, ObjectType = ObjectType.Building
                        };
                        tileIndex++;
                    }
                }
                // Set the correct game object in the visualized object of the neighbourhood so we can use it as reference
                neighbourhoodModel
                .VisualizedObjects[neighbourhoodModel.VisualizedObjects.IndexOf(visualizedObjects[index])]
                .GameObject = building;
            }

            // Spawn a grass patch as a divider between buildings
            GameObject grassPatch = Instantiate(
                AssetsManager.Instance.GetPredefinedPrefab(AssetsManager.PrefabType.Grass),
                new Vector3(tiles.Last().X, 0.5f, tiles.Last().Z), Quaternion.Euler(0, 90f, 0));

            // Add the grass patch to the list of visualized objects
            neighbourhoodModel.VisualizedObjects.Add(new VisualizedGrassTileModel {
                GameObject = grassPatch
            });

            Grid[tiles.Last()] = new TileObject
            {
                GameObject = grassPatch, ObjectType = ObjectType.Grass
            };
        }