void RequestAssetBundleTargetHash(MessageEventArgs args)
        {
            //@TODO: should be based on connection / BuildSetting
            var buildTarget = EditorUserBuildSettings.activeBuildTarget;

            using (var assets = args.ReceiveArray <GUID>())
            {
                var resolvedAssets = new HashSet <ResolvedAssetID>();
                foreach (var asset in assets)
                {
                    LiveLinkMsg.LogReceived($"AssetBundleTargetHash request => {asset}");

                    var targetHash = LiveLinkBuildPipeline.CalculateTargetHash(asset, buildTarget);
                    resolvedAssets.Add(new ResolvedAssetID {
                        GUID = asset, TargetHash = targetHash
                    });

                    LiveLinkBuildPipeline.CalculateTargetDependencies(asset, buildTarget, out ResolvedAssetID[] dependencies);
                    resolvedAssets.UnionWith(dependencies);
                }

                var resolved = new NativeArray <ResolvedAssetID>(resolvedAssets.Count, Allocator.Temp);
                int j        = 0;
                foreach (var id in resolvedAssets)
                {
                    resolved[j++] = id;
                }

                SendAssetBundleTargetHash(resolved, args.playerId);
            }
        }
Exemple #2
0
        void RequestAssetTargetHash(MessageEventArgs args)
        {
            //@TODO: should be based on connection / BuildSetting
            var buildTarget = EditorUserBuildSettings.activeBuildTarget;

            // Array of Asset GUIDs the player is requesting the asset hash of
            using (var assets = args.ReceiveArray <GUID>())
            {
                // Set of ready to send (all valid target hashes) assets
                var resolvedAssets = new HashSet <ResolvedAssetID>();
                foreach (var asset in assets)
                {
                    LiveLinkMsg.LogReceived($"AssetBundleTargetHash request => {asset} | {AssetDatabase.GUIDToAssetPath(asset.ToString())}");

                    // For each Asset- queue calculating target hash and add to tracked assets
                    Unity.Entities.Hash128 targetHash = LiveLinkBuildPipeline.CalculateTargetHash(asset, buildTarget, ImportMode.Asynchronous);
                    m_TrackedAssets[asset] = targetHash;

                    resolvedAssets.Add(new ResolvedAssetID {
                        GUID = asset, TargetHash = targetHash
                    });

                    // If asset hash is valid (meaning import is ready) then also do the same for dependencies
                    if (targetHash.IsValid)
                    {
                        LiveLinkBuildPipeline.CalculateTargetDependencies(targetHash, buildTarget, out ResolvedAssetID[] dependencies, ImportMode.Asynchronous, asset);
                        foreach (var dependency in dependencies)
                        {
                            m_TrackedAssets[dependency.GUID] = dependency.TargetHash;
                            resolvedAssets.Add(new ResolvedAssetID {
                                GUID = dependency.GUID, TargetHash = dependency.TargetHash
                            });
                        }
                    }
                }

                // Callback to re-send tracked assets when their targethash changes
                if (m_TrackedAssets.Count > 0)
                {
                    TimeBasedCallbackInvoker.SetCallback(DetectChangedAssets);
                }

                // No assets? Send nothing and set no callback
                if (resolvedAssets.Count == 0)
                {
                    return;
                }

                var resolved = new NativeArray <ResolvedAssetID>(resolvedAssets.Count, Allocator.Temp);
                int j        = 0;
                foreach (var id in resolvedAssets)
                {
                    resolved[j++] = id;
                }

                SendAssetTargetHash(resolved, args.playerId);
            }
        }
        void DetectChangedAssets()
        {
            if (_UsedAssetsTargetHash.Count == 0)
            {
                TimeBasedCallbackInvoker.ClearCallback(DetectChangedAssets);
                return;
            }

            var changedAssets = new NativeList <ResolvedAssetID>(Allocator.Temp);
            var buildTarget   = EditorUserBuildSettings.activeBuildTarget;

            foreach (var asset in _UsedAssetsTargetHash)
            {
                //@TODO: Artifact hash API should give error message when used on V1 pipeline (currently does not).

                var targetHash = LiveLinkBuildPipeline.CalculateTargetHash(asset.Key, buildTarget);

                if (asset.Value != targetHash)
                {
                    var path = AssetDatabase.GUIDToAssetPath(asset.Key.ToString());
                    LiveLinkMsg.LogInfo("Detected asset change: " + path);
                    changedAssets.Add(new ResolvedAssetID {
                        GUID = asset.Key, TargetHash = targetHash
                    });

                    LiveLinkBuildPipeline.CalculateTargetDependencies(asset.Key, buildTarget, out ResolvedAssetID[] dependencies);
                    foreach (var dependency in dependencies)
                    {
                        if (_UsedAssetsTargetHash.ContainsKey(dependency.GUID))
                        {
                            continue;
                        }

                        // New Dependency
                        var dependencyHash = LiveLinkBuildPipeline.CalculateTargetHash(dependency.GUID, buildTarget);
                        changedAssets.Add(new ResolvedAssetID {
                            GUID = dependency.GUID, TargetHash = dependencyHash
                        });
                    }
                }
            }

            if (changedAssets.Length != 0)
            {
                SendAssetBundleTargetHash(changedAssets, 0);
            }
        }
        //@TODO: The asset pipeline should be building & cache the asset bundle
        public string BuildAssetBundleIfNotCached(GUID guid, out Hash128 targetHash)
        {
            //@TODO Get build target from player requesting it...
            var buildTarget = EditorUserBuildSettings.activeBuildTarget;

            targetHash = LiveLinkBuildPipeline.CalculateTargetHash(guid, buildTarget);

            // TODO: Move caching into LiveLinkBuildPipeline
            var cachePath = ResolveCachePath(targetHash);

            if (File.Exists(cachePath))
            {
                return(cachePath);
            }

            if (!Directory.Exists(cachePath))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
            }

            // Debug.Log($"Building {guid} fresh");
            // Patching only works if the ObjectManifest comes from the same GUID every time.
            // So we can't delete this file. Optimally we would control the build pipeline
            // to make it always be at a specific local identifier in file
            var manifest = ScriptableObject.CreateInstance <AssetObjectManifest>();

            AssetObjectManifestBuilder.BuildManifest(guid, manifest);
            UnityEditorInternal.InternalEditorUtility.SaveToSerializedFileAndForget(new[] { manifest }, AssetObjectManifestPath, true);

            var didSucceed = LiveLinkBuildPipeline.BuildAssetBundle(guid, $"{cachePath}", EditorUserBuildSettings.activeBuildTarget);

            if (!didSucceed)
            {
                Debug.LogError($"Failed to build asset bundle: '{guid}'");
                return(null);
            }

            return(cachePath);
        }