Beispiel #1
0
        unsafe void ReceiveAssetTargetHash(MessageEventArgs args)
        {
            using (var resolvedAssets = args.ReceiveArray <ResolvedAssetID>())
            {
                foreach (var asset in resolvedAssets)
                {
                    if (!asset.TargetHash.IsValid)
                    {
                        // If hash is invalid, then it means we should be waiting on it, but the hash will come later when it finishes importing on the editor
                        LiveLinkMsg.LogReceived($"ReceiveAssetTargetHash => {asset.GUID} | {asset.TargetHash}, Invalid Hash (Still waiting)");
                        m_WaitingForAssets[asset.GUID] = new Hash128();
                    }
                    else
                    {
                        //TODO: Should we compare against already loaded assets here?
                        if (File.Exists(GetCachePath(asset.TargetHash)))
                        {
                            LiveLinkMsg.LogReceived($"ReceiveAssetTargetHash => {asset.GUID} | {asset.TargetHash}, File.Exists => 'True'");
                            m_WaitingForAssets[asset.GUID] = asset.TargetHash;
                        }
                        else
                        {
                            LiveLinkMsg.LogReceived($"ReceiveAssetTargetHash => {asset.GUID} | {asset.TargetHash}, File.Exists => 'False'");
                            m_WaitingForAssets[asset.GUID] = new Hash128();

                            LiveLinkMsg.LogSend($"AssetBundleBuild request '{asset.GUID}'");
                            PlayerConnection.instance.Send(LiveLinkMsg.RequestAssetByGUID, asset.GUID);
                        }
                    }
                }
            }
        }
Beispiel #2
0
        unsafe void ReceiveSubSceneTargetHash(MessageEventArgs args)
        {
            using (var subSceneAssets = args.ReceiveArray <ResolvedSubSceneID>())
            {
                foreach (var subSceneAsset in subSceneAssets)
                {
                    if (m_WaitingForSubScenes.ContainsKey(subSceneAsset.SubSceneGUID))
                    {
                        return;
                    }

                    // If subscene exists locally already, just load it
                    if (IsSubSceneAvailable(subSceneAsset))
                    {
                        LiveLinkMsg.LogInfo($"ReceiveResponseSubSceneTargetHash => {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash}, File.Exists => 'True'");

                        AddWaitForSubScene(subSceneAsset);
                    }
                    else
                    {
                        LiveLinkMsg.LogInfo($"ReceiveResponseSubSceneTargetHash => {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash}, File.Exists => 'False'");
                        m_Connection.Send(LiveLinkMsg.PlayerRequestSubSceneForGUID, subSceneAsset);
                    }
                }
            }
        }
Beispiel #3
0
        void ResetGame()
        {
            while (m_ResourcePacketQueue.Count != 0)
            {
                m_ResourcePacketQueue.Dequeue().Dispose();
            }

            EntityManager.DestroyEntity(EntityManager.UniversalQuery);

            //@TODO: Once we have build settings & loading of game object scenes we can remove this hack.
            var scenes = Object.FindObjectsOfType <SubScene>();

            foreach (var scene in scenes)
            {
                scene.enabled = false;
                scene.enabled = true;
            }

            LiveLinkPlayerAssetRefreshSystem.Reset();

            LiveLinkMsg.LogSend("ConnectLiveLink");
            PlayerConnection.instance.Send(LiveLinkMsg.ConnectLiveLink, World.GetExistingSystem <SceneSystem>().BuildSettingsGUID);

            m_LiveLinkSceneChange.Reset();
            SendSetLoadedScenes();
        }
Beispiel #4
0
        unsafe void ReceiveSubSceneTargetHash(MessageEventArgs args)
        {
            using (var subSceneAssets = args.ReceiveArray <ResolvedSubSceneID>())
            {
                foreach (var subSceneAsset in subSceneAssets)
                {
                    if (m_WaitingForSubScenes.ContainsKey(subSceneAsset.SubSceneGUID))
                    {
                        return;
                    }

                    // If subscene exists locally already, just load it
                    var assetDependencies = new HashSet <RuntimeGlobalObjectId>();
                    if (IsSubSceneAvailable(subSceneAsset, assetDependencies))
                    {
                        LiveLinkMsg.LogInfo($"ReceiveResponseSubSceneTargetHash => {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash}, File.Exists => 'True'");

                        //TODO: This is a hack to make sure assets are managed by asset manifest when loading from cache for first run
                        AddWaitForSubScene(subSceneAsset, assetDependencies);
                    }
                    else
                    {
                        LiveLinkMsg.LogInfo($"ReceiveResponseSubSceneTargetHash => {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash}, File.Exists => 'False'");

                        PlayerConnection.instance.Send(LiveLinkMsg.RequestSubSceneByGUID, subSceneAsset);
                    }
                }
            }
        }
Beispiel #5
0
        protected override void OnUpdate()
        {
            // BuildConfigurationGUID isn't known in OnCreate since it could be configured from OnCreate of other systems,
            // So we delay connecting live link until first OnUpdate
            if (!m_DidRequestConnection)
            {
                if (!m_SessionHandshake)
                {
                    if (m_SessionHandshakeTimeoutTimstamp < Time.ElapsedTime)
                    {
                        Debug.LogError("LiveLink handshake timed out. This may be because your player connection is connected to an AssetWorker process or incorrect Editor.");
                        World.GetExistingSystem <LiveLinkRuntimeSystemGroup>().Enabled = false;
                    }

                    return;
                }

                m_DidRequestConnection = true;
                LiveLinkMsg.LogSend("ConnectLiveLink");
                m_Connection.Send(LiveLinkMsg.PlayerRequestConnectLiveLink, World.GetExistingSystem <SceneSystem>().BuildConfigurationGUID);
            }

            SendSetLoadedScenes();

            while (m_ResourcePacketQueue.Count != 0 && IsResourceReady(m_ResourcePacketQueue.Peek().GlobalObjectIds))
            {
                LiveLinkMsg.LogInfo($"Applying changeset ({m_ResourcePacketQueue.Count-1} left in queue)");
                using (var resourcePacket = m_ResourcePacketQueue.Dequeue())
                {
                    ApplyChangeSet(resourcePacket);
                }
            }
        }
Beispiel #6
0
 void SendSetLoadedScenes()
 {
     if (m_LiveLinkSceneChange.GetSceneMessage(out var msg))
     {
         LiveLinkMsg.LogSend($"SetLoadedScenes: Loaded {msg.LoadedScenes.ToDebugString()}, Removed {msg.RemovedScenes.ToDebugString()}");
         m_Connection.Send(LiveLinkMsg.PlayerSetLoadedScenes, msg.ToMsg());
         msg.Dispose();
     }
 }
        //@TODO: Support some sort of transaction like API so we can reload all changed things in batch.
        unsafe void ReceiveAssetBundle(MessageEventArgs args)
        {
            LiveLinkMsg.LogReceived($"AssetBundle: '{args.data.Length}' bytes");

            fixed(byte *ptr = args.data)
            {
                var reader = new UnsafeAppendBuffer.Reader(ptr, args.data.Length);
                var asset  = reader.ReadNext <ResolvedAssetID>();

                var assetBundleCachePath = GetCachePath(asset.TargetHash);
                var tempCachePath        = GetTempCachePath();

                // cache: look up asset by target hash to see if the version we want is already on the target device

                //if we already have the asset bundle revision we want, then just put that in the resolver as the active revision of the asset
                // cache: if not in cache, write actual file to Application.persistentDatapath
                var stream = File.OpenWrite(tempCachePath);

                stream.Write(args.data, reader.Offset, args.data.Length - reader.Offset);
                stream.Close();
                stream.Dispose();

                LiveLinkMsg.LogInfo($"ReceiveAssetBundle => {asset.GUID} | {asset.TargetHash}, '{tempCachePath}' => '{assetBundleCachePath}'");

                if (File.Exists(assetBundleCachePath))
                {
                    Debug.LogError($"Received {asset.GUID} | {asset.TargetHash} but it already exists on disk");
                    LiveLinkMsg.LogInfo($"Received {asset.GUID} | {asset.TargetHash} but it already exists on disk");
                    File.Delete(tempCachePath);
                }
                else
                {
                    try
                    {
                        File.Move(tempCachePath, assetBundleCachePath);
                    }
                    catch (Exception e)
                    {
                        File.Delete(tempCachePath);
                        if (!File.Exists(assetBundleCachePath))
                        {
                            Debug.LogError($"Failed to move temporary file. Exception: {e.Message}");
                            LiveLinkMsg.LogInfo($"Failed to move temporary file. Exception: {e.Message}");
                        }
                    }
                }


                if (!_WaitingForAssets.ContainsKey(asset.GUID))
                {
                    Debug.LogError($"Received {asset.GUID} | {asset.TargetHash} without requesting it");
                    LiveLinkMsg.LogInfo($"Received {asset.GUID} | {asset.TargetHash} without requesting it");
                }

                _WaitingForAssets[asset.GUID] = asset.TargetHash;
            }
        }
Beispiel #8
0
        void ReceiveEntityChangeSet(MessageEventArgs args)
        {
            var resourcePacket = new EntityChangeSetSerialization.ResourcePacket(args.data);

            LiveLinkMsg.LogReceived($"EntityChangeSet patch: '{args.data.Length}' bytes, " +
                                    $"object GUIDs: {resourcePacket.GlobalObjectIds.ToDebugString(id => id.AssetGUID.ToString())}");

            m_ResourcePacketQueue.Enqueue(resourcePacket);
        }
        //TODO: There is too much code duplication here, refactor this to receive general artifacts from the editor
        unsafe void ReceiveSubSceneRefGUIDs(MessageEventArgs args)
        {
            fixed(byte *ptr = args.data)
            {
                var reader        = new UnsafeAppendBuffer.Reader(ptr, args.data.Length);
                var subSceneAsset = reader.ReadNext <ResolvedSubSceneID>();
                var sectionIndex  = reader.ReadNext <int>();

                reader.ReadNext(out NativeArray <RuntimeGlobalObjectId> objRefGUIDs, Allocator.Persistent);
                var refObjGUIDsPath = EntityScenesPaths.GetLiveLinkCachePath(subSceneAsset.TargetHash, EntityScenesPaths.PathType.EntitiesUnityObjectReferences, sectionIndex);

                // Not printing error because this can happen when running the same player multiple times on the same machine
                if (File.Exists(refObjGUIDsPath))
                {
                    LiveLinkMsg.LogInfo($"Received {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash} but it already exists on disk");
                }
                else
                {
                    LiveLinkMsg.LogInfo($"ReceieveSubSceneRefGUIDs => {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash},");

                    var tempCachePath = GetTempCachePath();
                    using (var writer = new StreamBinaryWriter(tempCachePath))
                    {
                        writer.Write(objRefGUIDs.Length);
                        writer.WriteArray(objRefGUIDs);
                    }

                    try
                    {
                        File.Move(tempCachePath, refObjGUIDsPath);
                    }
                    catch (Exception e)
                    {
                        File.Delete(tempCachePath);
                        if (!File.Exists(refObjGUIDsPath))
                        {
                            Debug.LogError($"Failed to move temporary file. Exception: {e.Message}");
                            LiveLinkMsg.LogInfo($"Failed to move temporary file. Exception: {e.Message}");
                        }
                    }
                }

                if (!_WaitingForSubScenes.ContainsKey(subSceneAsset.SubSceneGUID))
                {
                    Debug.LogError($"Received {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash} without requesting it");
                    LiveLinkMsg.LogInfo($"Received {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash} without requesting it");
                    return;
                }

                var waitingSubScene = _WaitingForSubScenes[subSceneAsset.SubSceneGUID];

                waitingSubScene.SubSections.Add(objRefGUIDs);
                _WaitingForSubScenes[subSceneAsset.SubSceneGUID] = waitingSubScene;
            }
        }
        unsafe void ReceiveResponseSubSceneTargetHash(MessageEventArgs args)
        {
            using (var subSceneAssets = args.ReceiveArray <ResolvedSubSceneID>())
            {
                foreach (var subSceneAsset in subSceneAssets)
                {
                    if (_WaitingForSubScenes.ContainsKey(subSceneAsset.SubSceneGUID))
                    {
                        return;
                    }

                    var headerPath = EntityScenesPaths.GetLiveLinkCachePath(subSceneAsset.TargetHash, EntityScenesPaths.PathType.EntitiesHeader, -1);

                    if (File.Exists(headerPath))
                    {
                        LiveLinkMsg.LogInfo($"ReceiveResponseSubSceneTargetHash => {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash}, File.Exists => 'True', {Path.GetFullPath(headerPath)}");

                        //TODO: This is a hack to make sure assets are managed by asset manifest when loading from cache for first run
                        if (!BlobAssetReference <SceneMetaData> .TryRead(headerPath, SceneMetaDataSerializeUtility.CurrentFileFormatVersion, out var sceneMetaDataRef))
                        {
                            Debug.LogError("Loading Entity Scene failed because the entity header file was an old version: " + subSceneAsset.SubSceneGUID);
                            return;
                        }

                        ref var sceneMetaData = ref sceneMetaDataRef.Value;

                        var waitingSubScene = new WaitingSubScene
                        {
                            TargetHash      = subSceneAsset.TargetHash,
                            SubSections     = new List <NativeArray <RuntimeGlobalObjectId> >(),
                            SubSectionCount = sceneMetaData.Sections.Length
                        };

                        for (int i = 0; i < sceneMetaData.Sections.Length; i++)
                        {
                            if (sceneMetaData.Sections[i].ObjectReferenceCount != 0)
                            {
                                var refObjGUIDsPath = EntityScenesPaths.GetLiveLinkCachePath(subSceneAsset.TargetHash, EntityScenesPaths.PathType.EntitiesUnityObjectReferences, i);
                                using (var reader = new StreamBinaryReader(refObjGUIDsPath))
                                {
                                    var numObjRefGUIDs = reader.ReadInt();
                                    NativeArray <RuntimeGlobalObjectId> objRefGUIDs = new NativeArray <RuntimeGlobalObjectId>(numObjRefGUIDs, Allocator.Persistent);
                                    reader.ReadArray(objRefGUIDs, numObjRefGUIDs);
                                    waitingSubScene.SubSections.Add(objRefGUIDs);
                                }
                            }
                            else
                            {
                                waitingSubScene.SubSections.Add(new NativeArray <RuntimeGlobalObjectId>(0, Allocator.Persistent));
                            }
                        }

                        _WaitingForSubScenes[subSceneAsset.SubSceneGUID] = waitingSubScene;
                    }
Beispiel #11
0
 void ReceiveLoadScenes(MessageEventArgs args)
 {
     using (var scenes = args.ReceiveArray <Hash128>())
     {
         LiveLinkMsg.LogReceived($"LoadScenes {scenes.ToDebugString()}");
         foreach (var scene in scenes)
         {
             m_Patcher.TriggerLoad(scene);
         }
     }
 }
        unsafe void ReceiveSubSceneHeader(MessageEventArgs args)
        {
            fixed(byte *ptr = args.data)
            {
                var reader          = new UnsafeAppendBuffer.Reader(ptr, args.data.Length);
                var subSceneAsset   = reader.ReadNext <ResolvedSubSceneID>();
                var subSectionCount = reader.ReadNext <int>();
                var headerPath      = EntityScenesPaths.GetLiveLinkCachePath(subSceneAsset.TargetHash, EntityScenesPaths.PathType.EntitiesHeader, -1);

                // Not printing error because this can happen when running the same player multiple times on the same machine
                if (File.Exists(headerPath))
                {
                    LiveLinkMsg.LogInfo($"Received {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash} but it already exists on disk");
                }
                else
                {
                    var tempCachePath = GetTempCachePath();
                    LiveLinkMsg.LogInfo($"ReceiveSubSceneHeader => {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash}, '{tempCachePath}' => '{headerPath}'");

                    var stream = File.OpenWrite(tempCachePath);
                    stream.Write(args.data, reader.Offset, args.data.Length - reader.Offset);
                    stream.Close();
                    stream.Dispose();

                    try
                    {
                        File.Move(tempCachePath, headerPath);
                    }
                    catch (Exception e)
                    {
                        File.Delete(tempCachePath);
                        if (!File.Exists(headerPath))
                        {
                            Debug.LogError($"Failed to move temporary file. Exception: {e.Message}");
                            LiveLinkMsg.LogInfo($"Failed to move temporary file. Exception: {e.Message}");
                        }
                    }
                }

                if (!_WaitingForSubScenes.ContainsKey(subSceneAsset.SubSceneGUID))
                {
                    Debug.LogError($"Received {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash} without requesting it");
                    LiveLinkMsg.LogInfo($"Received {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash} without requesting it");
                    return;
                }

                var waitingSubScene = _WaitingForSubScenes[subSceneAsset.SubSceneGUID];

                waitingSubScene.TargetHash      = subSceneAsset.TargetHash;
                waitingSubScene.SubSectionCount = subSectionCount;
                _WaitingForSubScenes[subSceneAsset.SubSceneGUID] = waitingSubScene;
            }
        }
Beispiel #13
0
 unsafe void ReceiveUnloadScenes(MessageEventArgs args)
 {
     using (var scenes = args.ReceiveArray <Hash128>())
     {
         LiveLinkMsg.LogReceived($"UnloadScenes {scenes.ToDebugString()}");
         foreach (var scene in scenes)
         {
             m_Patcher.UnloadScene(scene);
             m_LiveLinkedScenes.Remove(scene);
         }
     }
 }
Beispiel #14
0
        unsafe void ReceiveSubScene(MessageEventArgs args)
        {
            var subSceneId = args.Receive <ResolvedSubSceneID>();

            LiveLinkMsg.LogInfo($"ReceiveSubScene => SubScene received {subSceneId}");

            if (!IsSubSceneAvailable(subSceneId))
            {
                Debug.LogError("SubScene is missing artifacts!");
                return;
            }

            AddWaitForSubScene(subSceneId);
        }
Beispiel #15
0
 void ReceiveInitialScenes(MessageEventArgs args)
 {
     using (var scenes = args.ReceiveArray <Hash128>())
     {
         if (scenes.Length > 0)
         {
             LiveLinkMsg.LogReceived($"ReceiveInitialScenes {scenes.ToString()}");
             var sceneSystem = World.GetOrCreateSystem <SceneSystem>();
             for (int i = 0; i < scenes.Length; i++)
             {
                 sceneSystem.LoadSceneAsync(scenes[i], new SceneSystem.LoadParameters()
                 {
                     Flags = SceneLoadFlags.LoadAdditive | SceneLoadFlags.LoadAsGOScene
                 });
             }
         }
     }
 }
Beispiel #16
0
        unsafe void ReceiveBuildArtifact(MessageEventArgs args)
        {
            fixed(byte *ptr = args.data)
            {
                LiveLinkMsg.LogInfo($"ReceiveBuildArtifact => Buffer Size: {args.data.Length}");
                var reader = new UnsafeAppendBuffer.Reader(ptr, args.data.Length);

                reader.ReadNext(out string artifactFileName);
                string artifactPath = EntityScenesPaths.ComposeLiveLinkCachePath(artifactFileName);

                if (!File.Exists(artifactPath))
                {
                    LiveLinkMsg.LogInfo($"ReceiveBuildArtifact => {artifactPath}");

                    var tempCachePath = GetTempCachePath();

                    try
                    {
                        var stream = File.OpenWrite(tempCachePath);
                        stream.Write(args.data, reader.Offset, args.data.Length - reader.Offset);
                        stream.Close();
                        stream.Dispose();

                        File.Move(tempCachePath, artifactPath);

                        LiveLinkMsg.LogInfo($"ReceiveBuildArtifact => Successfully written to disc.");
                    }
                    catch (Exception e)
                    {
                        if (File.Exists(tempCachePath))
                        {
                            File.Delete(tempCachePath);
                        }

                        if (!File.Exists(artifactPath))
                        {
                            Debug.LogError($"Failed to move temporary file. Exception: {e.Message}");
                        }
                    }
                }
            }
        }
Beispiel #17
0
        unsafe void ReceiveSubScene(MessageEventArgs args)
        {
            fixed(byte *ptr = args.data)
            {
                var reader = new UnsafeAppendBuffer.Reader(ptr, args.data.Length);

                reader.ReadNext(out ResolvedSubSceneID subSceneId);
                reader.ReadNext(out NativeArray <RuntimeGlobalObjectId> runtimeGlobalObjectIds, Allocator.Persistent);

                LiveLinkMsg.LogInfo($"ReceiveSubScene => SubScene received {subSceneId} | Asset Dependencies {runtimeGlobalObjectIds.Length}");

                if (!IsSubSceneAvailable(subSceneId))
                {
                    Debug.LogError("SubScene is missing artifacts!");
                    return;
                }

                AddWaitForSubScene(subSceneId, runtimeGlobalObjectIds);
            }
        }
Beispiel #18
0
        void ResetGame()
        {
            var sceneSystem = World.GetExistingSystem <SceneSystem>();

            sceneSystem.UnloadAllScenes();

            while (m_ResourcePacketQueue.Count != 0)
            {
                m_ResourcePacketQueue.Dequeue().Dispose();
            }

            EntityManager.DestroyEntity(EntityManager.UniversalQuery);
            LiveLinkPlayerAssetRefreshSystem.Reset();

            LiveLinkMsg.LogSend("ConnectLiveLink");
            m_Connection.Send(LiveLinkMsg.PlayerRequestConnectLiveLink, sceneSystem.BuildConfigurationGUID);

            m_LiveLinkSceneChange.Reset();
            SendSetLoadedScenes();
        }
        protected override void OnUpdate()
        {
            // Request any new guids that we haven't seen yet from the editor
            using (var requestedGuids = _ResourceRequests.ToComponentDataArray <ResourceGUID>(Allocator.TempJob))
            {
                if (requestedGuids.Length > 0)
                {
                    EntityManager.AddComponent(_ResourceRequests, typeof(ResourceRequested));
                    LiveLinkMsg.LogSend($"AssetBundleTargetHash request {requestedGuids.Reinterpret<Hash128>().ToDebugString()}");
                    PlayerConnection.instance.SendArray(LiveLinkMsg.RequestAssetBundleTargetHash, requestedGuids);
                }
            }

            // * Ensure all assets we are waiting for have arrived.
            // * LoadAll asset bundles in one go when everything is ready
            if (_WaitingForAssets.Count != 0)
            {
                bool hasAllAssets = true;
                var  assets       = new NativeArray <ResolvedAssetID>(_WaitingForAssets.Count, Allocator.TempJob);
                int  o            = 0;
                foreach (var asset in _WaitingForAssets)
                {
                    if (asset.Value == new Hash128())
                    {
                        hasAllAssets = false;
                    }
                    assets[o++] = new ResolvedAssetID {
                        GUID = asset.Key, TargetHash = asset.Value
                    };
                }

                if (hasAllAssets)
                {
                    LoadAssetBundles(assets);
                    _WaitingForAssets.Clear();
                }

                assets.Dispose();
            }
        }
Beispiel #20
0
        protected override void OnUpdate()
        {
            var sceneSystem = World.GetExistingSystem <SceneSystem>();

            Entities.With(m_AllScenes).ForEach((Entity e, ref SceneReference sceneRef) =>
            {
                if (m_LiveLinkedScenes.Contains(sceneRef.SceneGUID))
                {
                    EntityManager.AddComponent <DisableSceneResolveAndLoad>(e);
                }
                else
                {
                    EntityManager.RemoveComponent <DisableSceneResolveAndLoad>(e);
                }
            }
                                               );


            // BuildSettingsGUID isn't known in OnCreate since it could be configured from OnCreate of other systems,
            // So we delay connecting live link until first OnUpdate
            if (!m_DidRequestConnection)
            {
                m_DidRequestConnection = true;
                LiveLinkMsg.LogSend("ConnectLiveLink");
                PlayerConnection.instance.Send(LiveLinkMsg.ConnectLiveLink, World.GetExistingSystem <SceneSystem>().BuildSettingsGUID);
            }

            SendSetLoadedScenes();

            while (m_ResourcePacketQueue.Count != 0 && IsResourceReady(m_ResourcePacketQueue.Peek()))
            {
                LiveLinkMsg.LogInfo($"Applying changeset ({m_ResourcePacketQueue.Count-1} left in queue)");
                using (var resourcePacket = m_ResourcePacketQueue.Dequeue())
                {
                    ApplyChangeSet(resourcePacket);
                }
            }
        }
        unsafe void ReceiveResponseAssetBundleTargetHash(MessageEventArgs args)
        {
            using (var resolvedAssets = args.ReceiveArray <ResolvedAssetID>())
            {
                foreach (var asset in resolvedAssets)
                {
                    //TODO: Should we compare against already loaded assets here?
                    if (File.Exists(GetCachePath(asset.TargetHash)))
                    {
                        LiveLinkMsg.LogReceived($"AssetBundleTargetHash => {asset.GUID} | {asset.TargetHash}, File.Exists => 'True'");
                        _WaitingForAssets[asset.GUID] = asset.TargetHash;
                    }
                    else
                    {
                        LiveLinkMsg.LogReceived($"AssetBundleTargetHash => {asset.GUID} | {asset.TargetHash}, File.Exists => 'False'");
                        _WaitingForAssets[asset.GUID] = new Hash128();

                        LiveLinkMsg.LogSend($"AssetBundleBuild request '{asset.GUID}'");
                        PlayerConnection.instance.Send(LiveLinkMsg.RequestAssetBundleForGUID, asset.GUID);
                    }
                }
            }
        }
        protected override void OnUpdate()
        {
            var sceneSystem = World.GetExistingSystem <SceneSystem>();

            // BuildConfigurationGUID isn't known in OnCreate since it could be configured from OnCreate of other systems,
            // So we delay connecting live link until first OnUpdate
            if (!m_DidRequestConnection)
            {
                m_DidRequestConnection = true;
                LiveLinkMsg.LogSend("ConnectLiveLink");
                PlayerConnection.instance.Send(LiveLinkMsg.RequestConnectLiveLink, World.GetExistingSystem <SceneSystem>().BuildConfigurationGUID);
            }

            SendSetLoadedScenes();

            while (m_ResourcePacketQueue.Count != 0 && IsResourceReady(m_ResourcePacketQueue.Peek().GlobalObjectIds))
            {
                LiveLinkMsg.LogInfo($"Applying changeset ({m_ResourcePacketQueue.Count-1} left in queue)");
                using (var resourcePacket = m_ResourcePacketQueue.Dequeue())
                {
                    ApplyChangeSet(resourcePacket);
                }
            }
        }
Beispiel #23
0
 void ReceiveResetGame(MessageEventArgs args)
 {
     LiveLinkMsg.LogReceived("ResetGame");
     ResetGame();
 }
Beispiel #24
0
        void LoadAssetBundles(NativeArray <ResolvedAssetID> assets)
        {
            LiveLinkMsg.LogInfo("--- Begin Load asset bundles");

            var patchAssetBundles     = new List <AssetBundle>();
            var patchAssetBundlesPath = new List <string>();
            var newAssetBundles       = new List <Hash128>();
            var assetBundleToValidate = new List <Hash128>();


            foreach (var asset in assets)
            {
                var assetGUID            = asset.GUID;
                var targetHash           = asset.TargetHash;
                var assetBundleCachePath = GetCachePath(targetHash);

                //if we already loaded an asset bundle and we just need a refresh
                var oldAssetBundle = globalAssetObjectResolver.GetAssetBundle(assetGUID);
                if (oldAssetBundle != null)
                {
                    if (oldAssetBundle.isStreamedSceneAssetBundle)
                    {
                        LiveLinkMsg.LogInfo($"Unloading scene bundle: {assetGUID}");
                        var sceneSystem = World.GetExistingSystem <SceneSystem>();
                        if (sceneSystem != null)
                        {
                            sceneSystem.ReloadScenesWithHash(assetGUID, targetHash);
                        }
                        globalAssetObjectResolver.UnloadAsset(assetGUID);
                        continue;
                    }
                    else
                    {
                        LiveLinkMsg.LogInfo($"patching asset bundle: {assetGUID}");

                        patchAssetBundles.Add(oldAssetBundle);
                        patchAssetBundlesPath.Add(assetBundleCachePath);

                        globalAssetObjectResolver.UpdateTargetHash(assetGUID, targetHash);
                        newAssetBundles.Add(assetGUID);
                    }
                }
                else
                {
                    LiveLinkMsg.LogInfo($"Loaded asset bundle: {assetGUID}");

                    var loadedAssetBundle = AssetBundle.LoadFromFile(assetBundleCachePath);
                    globalAssetObjectResolver.AddAsset(assetGUID, targetHash, null, loadedAssetBundle);
                    newAssetBundles.Add(assetGUID);
                }

                assetBundleToValidate.Add(assetGUID);

                //@TODO: Keep a hashtable of guid -> entity?
                Entities.ForEach((Entity entity, ref ResourceGUID guid) =>
                {
                    if (guid.Guid == assetGUID)
                    {
                        EntityManager.AddComponentData(entity, new ResourceLoaded());
                    }
                });
            }


            AssetBundleUtility.PatchAssetBundles(patchAssetBundles.ToArray(), patchAssetBundlesPath.ToArray());

            foreach (var assetGUID in newAssetBundles)
            {
                var assetBundle = globalAssetObjectResolver.GetAssetBundle(assetGUID);
                if (assetBundle == null)
                {
                    Debug.LogError($"Could not load requested asset bundle.'");
                    return;
                }

                if (!assetBundle.isStreamedSceneAssetBundle)
                {
                    var loadedManifest = assetBundle.LoadAsset <AssetObjectManifest>(assetGUID.ToString());
                    if (loadedManifest == null)
                    {
                        Debug.LogError($"Loaded {assetGUID} failed to load ObjectManifest");
                        return;
                    }

                    globalAssetObjectResolver.UpdateObjectManifest(assetGUID, loadedManifest);
                }
            }

            foreach (var assetGUID in assetBundleToValidate)
            {
                globalAssetObjectResolver.Validate(assetGUID);
            }

            LiveLinkMsg.LogInfo("--- End Load asset bundles");
        }