private static bool ExportWorld(FileInfo outputFile, Project project, string scenePath, World world, bool performConversion = true)
        {
            if (performConversion)
            {
                SceneConversion.Convert(world);
            }

            // Null out any references to avoid the SerializeUtility from trying to patch asset entities.
            world.GetOrCreateSystem <ClearRemappedEntityReferenceSystem>().Update();

            // Check for missing assembly references
            var unresolvedComponentTypes = GetAllUsedComponentTypes(world).Where(t => !DomainCache.IsIncludedInProject(project, t.GetManagedType())).ToArray();

            if (unresolvedComponentTypes.Length > 0)
            {
                foreach (var unresolvedComponentType in unresolvedComponentTypes)
                {
                    var type = unresolvedComponentType.GetManagedType();
                    Debug.LogError($"Could not resolve component type '{type.FullName}' while exporting {scenePath.HyperLink()}. Are you missing an assembly reference to '{type.Assembly.GetName().Name}' ?");
                }
                return(false);
            }

            // Remove non-exported components
            var nonExportedComponentTypes = UnityEditor.TypeCache.GetTypesWithAttribute <NonExportedAttribute>().Select(t => new ComponentType(t));

            world.EntityManager.RemoveComponent(world.EntityManager.UniversalQuery, new ComponentTypes(nonExportedComponentTypes.ToArray()));

            // Merges the entities and shared component streams, (optionally) compresses them, and finally serializes to disk with a small header in front
            using (var fileStream = new StreamBinaryWriter(outputFile.FullName))
                using (var entitiesWriter = new MemoryBinaryWriter())
                    using (var sharedComponentWriter = new MemoryBinaryWriter())
                        using (var combinedDataWriter = new MemoryBinaryWriter())
                        {
                            SerializeUtility.SerializeWorld(world.EntityManager, entitiesWriter, out var sharedComponentsToSerialize);
                            if (sharedComponentsToSerialize.Length > 0)
                            {
                                SerializeUtility.SerializeSharedComponents(world.EntityManager, sharedComponentWriter, sharedComponentsToSerialize);
                            }

                            unsafe
                            {
                                combinedDataWriter.WriteBytes(sharedComponentWriter.Data, sharedComponentWriter.Length);
                                combinedDataWriter.WriteBytes(entitiesWriter.Data, entitiesWriter.Length);

                                var worldHeader = new SceneHeader();
                                worldHeader.SharedComponentCount = sharedComponentsToSerialize.Length;
                                worldHeader.DecompressedSize     = entitiesWriter.Length + sharedComponentWriter.Length;
                                worldHeader.Codec = Codec.LZ4;
                                worldHeader.SerializeHeader(fileStream);

                                if (worldHeader.Codec != Codec.None)
                                {
                                    int compressedSize = CodecService.Compress(worldHeader.Codec, combinedDataWriter.Data, combinedDataWriter.Length, out var compressedData);
                                    fileStream.WriteBytes(compressedData, compressedSize);
                                }
                                else
                                {
                                    fileStream.WriteBytes(combinedDataWriter.Data, combinedDataWriter.Length);
                                }
                            }
                        }

            return(true);
        }
        public override void InvokeAtAwake()
        {
            base.InvokeAtAwake();

            // TODO: Comment this line when you want to see city
            if (!IS_DEMO && !forceDemo)
#pragma warning disable 162
            {
                return;
            }
#pragma warning restore 162

            if (singlePlaneSize == -1)
            {
                singlePlaneSize = 12.2f;
            }

            // The first thing we will do, is fill the fields of city class (to allow it to have what it need)
            if (SConv == null)
            {
                SConv = new SceneConversion(realScaleZoom, singlePlaneSize, conversionFactor, new Vector2(mapWidth, mapHeight));
            }

            string path;

#if !UNITY_WEBGL
            path = CityJSONPath;
#else
            path = CityBINPath;
#endif

            DoesCityFileExists = File.Exists(path);

            if (DoesCityFileExists)
            {
                //ThreadedDebug.Log("Starting loading city from file!");
                Debug.Log("Starting loading city from file!");

                //if (playerObject != null)
                HoldPosition = FirstPersonController.Pos;
                //holdPosition.y = 100;
                //characterController.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezePositionY;

                // TODO: Unfreeze player
                //OnGenerationFinishedEvent += UnfreezePlayer;

                // playerObject.transform.position;

#if !UNITY_WEBGL
                //StartCoroutine(AsyncReadAllFileText(s =>
                //{
                //    city = s.Deserialize<City>();
                //    CityModel = city;
                //    Debug.Log($"Deserialized city with {city.BuildingCount} buildings!");

                //    isCityReady = true;
                //}));
#else
                var url = WebRequestUtils.MakeInitialUrl(path);
                Debug.Log($"City: '{path}' -> '{url}'");
                url.ReadDataFromWebAsync(result =>
                {
                    Func <City> cityAsync = () => F.Deserialize <City>(result, evnt =>
                    {
                        Progress = evnt.Progress;
                    });
                    AsyncHelper.RunAsync(cityAsync, cityResult =>
                    {
                        city      = cityResult;
                        CityModel = city;
                        Debug.Log($"Deserialized city with {city.BuildingCount} buildings!");
                        isCityReady = true;
                    });
                });

                //StartCoroutine(F.AsyncReadFileWithWWW<byte[]>(path, s =>
                //{
                //    city = F.Deserialize<City>(s);
                //    Debug.Log($"Deserialized city with {city.BuildingCount} buildings!");

                //    isCityReady = true;
                //}));
#endif
            }
            else
            {
                if (characterController != null)
                {
                    characterController.enabled = false;
                }

                IsCityLoaded(false);
            }

#if UNITY_WEBGL
            //Debug.Log(CityBINPath);
            //Debug.Log($"Exists: {File.Exists(CityBINPath)}\n" +
            //          $"City exists: {DoesCityFileExists}\n" +
            //          $"if: {!File.Exists(CityBINPath) && DoesCityFileExists}");
            if (!File.Exists(CityBINPath) && DoesCityFileExists)
            {
                Debug.Log("Started coroutine!");
                StartCoroutine(SerializeBin());
            }
#endif
        }