internal IEnumerable <CheckDupeResult> CalculateDuplicates(Dictionary <GUID, List <string> > implicitGuids, AddressableAssetsBuildContext aaContext)
        {
            //Get all guids that have more than one bundle referencing them
            IEnumerable <KeyValuePair <GUID, List <string> > > validGuids =
                from dupeGuid in implicitGuids
                where dupeGuid.Value.Distinct().Count() > 1
                where IsValidPath(AssetDatabase.GUIDToAssetPath(dupeGuid.Key.ToString()))
                select dupeGuid;

            return
                (from guidToFile in validGuids
                 from file in guidToFile.Value

                 //Get the files that belong to those guids
                 let fileToBundle = m_ExtractData.WriteData.FileToBundle[file]

                                    //Get the bundles that belong to those files
                                    let bundleToGroup = aaContext.bundleToAssetGroup[fileToBundle]

                                                        //Get the asset groups that belong to those bundles
                                                        let selectedGroup = aaContext.Settings.FindGroup(findGroup => findGroup != null && findGroup.Guid == bundleToGroup)

                                                                            select new CheckDupeResult
            {
                Group = selectedGroup,
                DuplicatedFile = file,
                AssetPath = AssetDatabase.GUIDToAssetPath(guidToFile.Key.ToString()),
                DuplicatedGroupGuid = guidToFile.Key
            });
        }
        private BuildLayout CreateBuildLayout()
        {
            LayoutLookupTables lookup = new LayoutLookupTables();

            foreach (string bundleName in m_WriteData.FileToBundle.Values.Distinct())
            {
                BuildLayout.Bundle bundle = new BuildLayout.Bundle();
                bundle.Name = bundleName;
                string path = m_Parameters.GetOutputFilePathForIdentifier(bundle.Name);
                UnityEngine.BuildCompression compression = m_Parameters.GetCompressionForIdentifier(bundle.Name);
                bundle.FileSize    = (ulong)new FileInfo(path).Length;
                bundle.Compression = compression.compression.ToString();
                lookup.Bundles.Add(bundle.Name, bundle);
            }

            // create files
            foreach (KeyValuePair <string, string> fileBundle in m_WriteData.FileToBundle)
            {
                BuildLayout.Bundle bundle = lookup.Bundles[fileBundle.Value];
                BuildLayout.File   f      = new BuildLayout.File();
                f.Name = fileBundle.Key;

                WriteResult result = m_Results.WriteResults[f.Name];
                foreach (ResourceFile rf in result.resourceFiles)
                {
                    var sf = new BuildLayout.SubFile();
                    sf.IsSerializedFile = rf.serializedFile;
                    sf.Name             = rf.fileAlias;
                    sf.Size             = (ulong)new FileInfo(rf.fileName).Length;
                    f.SubFiles.Add(sf);
                }

                bundle.Files.Add(f);
                lookup.Files.Add(f.Name, f);
            }

            // create assets
            foreach (KeyValuePair <GUID, List <string> > assetFile in m_WriteData.AssetToFiles)
            {
                BuildLayout.File          file = lookup.Files[assetFile.Value[0]];
                BuildLayout.ExplicitAsset a    = new BuildLayout.ExplicitAsset();
                a.Guid      = assetFile.Key.ToString();
                a.AssetPath = AssetDatabase.GUIDToAssetPath(a.Guid);
                file.Assets.Add(a);
                lookup.GuidToExplicitAsset.Add(a.Guid, a);
            }

            Dictionary <string, List <BuildLayout.DataFromOtherAsset> > guidToPulledInBuckets = new Dictionary <string, List <BuildLayout.DataFromOtherAsset> >();

            foreach (BuildLayout.File file in lookup.Files.Values)
            {
                Dictionary <string, AssetBucket> buckets = new Dictionary <string, AssetBucket>();
                WriteResult writeResult = m_Results.WriteResults[file.Name];
                List <ObjectSerializedInfo> sceneObjects = new List <ObjectSerializedInfo>();

                foreach (ObjectSerializedInfo info in writeResult.serializedObjects)
                {
                    string sourceGuid = string.Empty;
                    if (info.serializedObject.guid.Empty())
                    {
                        if (info.serializedObject.filePath.Equals("temp:/assetbundle", StringComparison.OrdinalIgnoreCase))
                        {
                            file.BundleObjectInfo      = new BuildLayout.AssetBundleObjectInfo();
                            file.BundleObjectInfo.Size = info.header.size;
                            continue;
                        }
                        else if (info.serializedObject.filePath.StartsWith("temp:/preloaddata", StringComparison.OrdinalIgnoreCase))
                        {
                            file.PreloadInfoSize = (int)info.header.size;
                            continue;
                        }
                        else if (info.serializedObject.filePath.StartsWith("temp:/", StringComparison.OrdinalIgnoreCase))
                        {
                            sceneObjects.Add(info);
                            continue;
                        }
                        else if (!string.IsNullOrEmpty(info.serializedObject.filePath))
                        {
                            AssetBucket pathBucket = GetOrCreate(buckets, info.serializedObject.filePath.ToString());
                            pathBucket.isFilePathBucket = true;
                            pathBucket.objs.Add(info);
                            continue;
                        }
                    }

                    AssetBucket bucket = GetOrCreate(buckets, info.serializedObject.guid.ToString());
                    bucket.objs.Add(info);
                }

                if (sceneObjects.Count > 0)
                {
                    BuildLayout.ExplicitAsset sceneAsset = file.Assets.First(x => x.AssetPath.EndsWith(".unity"));
                    AssetBucket bucket = GetOrCreate(buckets, sceneAsset.Guid);
                    bucket.objs.AddRange(sceneObjects);
                }

                // Update buckets with a reference to their explicit asset
                file.Assets.ForEach(eAsset =>
                {
                    if (!buckets.TryGetValue(eAsset.Guid, out AssetBucket b))
                    {
                        b = GetOrCreate(buckets, eAsset.Guid); // some assets might not pull in any objects
                    }
                    b.ExplictAsset = eAsset;
                });

                // Create entries for buckets that are implicitly pulled in
                Dictionary <string, BuildLayout.DataFromOtherAsset> guidToOtherData = new Dictionary <string, BuildLayout.DataFromOtherAsset>();
                foreach (AssetBucket bucket in buckets.Values.Where(x => x.ExplictAsset == null))
                {
                    string assetPath = bucket.isFilePathBucket ? bucket.guid : AssetDatabase.GUIDToAssetPath(bucket.guid);
                    if (assetPath.EndsWith(".cs", StringComparison.OrdinalIgnoreCase) || assetPath.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
                    {
                        file.MonoScriptCount++;
                        file.MonoScriptSize += bucket.CalcObjectSize();
                        continue;
                    }
                    var otherData = new BuildLayout.DataFromOtherAsset();
                    otherData.AssetPath      = assetPath;
                    otherData.AssetGuid      = bucket.guid;
                    otherData.SerializedSize = bucket.CalcObjectSize();
                    otherData.StreamedSize   = bucket.CalcStreamedSize();
                    otherData.ObjectCount    = bucket.objs.Count;
                    file.OtherAssets.Add(otherData);
                    guidToOtherData[otherData.AssetGuid] = otherData;

                    if (!guidToPulledInBuckets.TryGetValue(otherData.AssetGuid, out List <BuildLayout.DataFromOtherAsset> bucketList))
                    {
                        bucketList = guidToPulledInBuckets[otherData.AssetGuid] = new List <BuildLayout.DataFromOtherAsset>();
                    }
                    bucketList.Add(otherData);
                }

                // Add references
                foreach (BuildLayout.ExplicitAsset asset in file.Assets)
                {
                    AssetBucket bucket = buckets[asset.Guid];
                    asset.SerializedSize = bucket.CalcObjectSize();
                    asset.StreamedSize   = bucket.CalcStreamedSize();

                    IEnumerable <ObjectIdentifier> refs = null;
                    if (m_DependencyData.AssetInfo.TryGetValue(new GUID(asset.Guid), out AssetLoadInfo info))
                    {
                        refs = info.referencedObjects;
                    }
                    else
                    {
                        refs = m_DependencyData.SceneInfo[new GUID(asset.Guid)].referencedObjects;
                    }
                    foreach (string refGUID in refs.Select(x => x.guid.Empty() ? x.filePath : x.guid.ToString()).Distinct())
                    {
                        if (guidToOtherData.TryGetValue(refGUID, out BuildLayout.DataFromOtherAsset dfoa))
                        {
                            dfoa.ReferencingAssets.Add(asset);
                            asset.InternalReferencedOtherAssets.Add(dfoa);
                        }
                        else if (buckets.TryGetValue(refGUID, out AssetBucket refBucket))
                        {
                            asset.InternalReferencedExplicitAssets.Add(refBucket.ExplictAsset);
                        }
                        else if (lookup.GuidToExplicitAsset.TryGetValue(refGUID, out BuildLayout.ExplicitAsset refAsset))
                        {
                            asset.ExternallyReferencedAssets.Add(refAsset);
                        }
                    }
                }
            }

            BuildLayout layout = new BuildLayout();

            // This is the addressables section. Everything above could technically be moved to SBP.
            {
                AddressableAssetsBuildContext aaContext = (AddressableAssetsBuildContext)m_AaBuildContext;
                // Map from GUID to AddrssableAssetEntry
                Dictionary <string, AddressableAssetEntry> guidToEntry = aaContext.assetEntries.ToDictionary(x => x.guid, x => x);

                // create groups
                foreach (AddressableAssetGroup group in aaContext.Settings.groups)
                {
                    var grp = new BuildLayout.Group();
                    grp.Name = group.Name;
                    grp.Guid = group.Guid;

                    foreach (AddressableAssetGroupSchema schema in group.Schemas)
                    {
                        var sd = new BuildLayout.SchemaData();
                        sd.Guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(schema));
                        sd.Type = schema.GetType().Name.ToString();

                        BundledAssetGroupSchema bSchema = schema as BundledAssetGroupSchema;
                        if (bSchema != null)
                        {
                            sd.KvpDetails.Add(new Tuple <string, string>("PackingMode", bSchema.BundleMode.ToString()));
                            sd.KvpDetails.Add(new Tuple <string, string>("Compression", bSchema.Compression.ToString()));
                        }
                        grp.Schemas.Add(sd);
                    }

                    lookup.GroupLookup.Add(group.Guid, grp);
                    layout.Groups.Add(grp);
                }

                // go through all the bundles and put them in groups
                foreach (BuildLayout.Bundle b in lookup.Bundles.Values)
                {
                    if (aaContext.bundleToImmediateBundleDependencies.TryGetValue(b.Name, out List <string> deps))
                    {
                        b.Dependencies = deps.Select(x => lookup.Bundles[x]).Where(x => b != x).ToList();
                    }
                    if (aaContext.bundleToExpandedBundleDependencies.TryGetValue(b.Name, out List <string> deps2))
                    {
                        b.ExpandedDependencies = deps2.Select(x => lookup.Bundles[x]).Where(x => b != x).ToList();
                    }

                    if (aaContext.bundleToAssetGroup.TryGetValue(b.Name, out string grpName))
                    {
                        lookup.GroupLookup[grpName].Bundles.Add(b);
                    }
                    else
                    {
                        layout.BuiltInBundles.Add(b);
                    }
                }

                // Apply the addressable name to the asset
                foreach (BuildLayout.ExplicitAsset a in BuildLayoutHelpers.EnumerateAssets(layout))
                {
                    if (guidToEntry.TryGetValue(a.Guid, out AddressableAssetEntry entry))
                    {
                        a.AddressableName = entry.address;
                    }
                }

                // The addressables build script can rename the bundles
                foreach (BuildLayout.Bundle b in BuildLayoutHelpers.EnumerateBundles(layout))
                {
                    if (m_BundleNameRemap.TryGetValue(b.Name, out string newName))
                    {
                        b.Name = newName;
                    }
                }
            }

            return(layout);
        }
Beispiel #3
0
    string ProcessTextureScaler(TextureVariationSchema schema, AddressableAssetGroup assetGroup, AddressableAssetsBuildContext aaContext)
    {
        m_SourceGroupList.Add(assetGroup);

        var entries = new List <AddressableAssetEntry>(assetGroup.entries);//获取对应Group下面的所有条目

        foreach (var entry in entries)
        {
            var entryPath = entry.AssetPath;
            if (AssetDatabase.GetMainAssetTypeAtPath(entryPath) == typeof(Texture2D))
            {
                var fileName = Path.GetFileNameWithoutExtension(entryPath);
                if (string.IsNullOrEmpty(fileName))
                {
                    return("Failed to get file name for: " + entryPath);
                }
                if (!Directory.Exists("Assets/GeneratedTextures"))
                {
                    Directory.CreateDirectory("Assets/GeneratedTextures");
                }
                if (!Directory.Exists("Assets/GeneratedTextures/Texture"))
                {
                    Directory.CreateDirectory("Assets/GeneratedTextures/Texture");
                }

                var sourceTex = AssetDatabase.LoadAssetAtPath <Texture2D>(entryPath);
                var aiSource  = AssetImporter.GetAtPath(entryPath) as TextureImporter;
                int maxDim    = Math.Max(sourceTex.width, sourceTex.height);

                foreach (var pair in schema.Variations)//根据对应的策略开始处理 (现在是根据这一张图片分别设置不同的标签)
                {
                    var newGroup = FindOrCopyGroup(assetGroup.Name + "_" + pair.label, assetGroup, aaContext.settings, schema);
                    var newFile  = entryPath.Replace(fileName, fileName + "_variationCopy_" + pair.label);
                    newFile = newFile.Replace("Assets/", "Assets/GeneratedTextures/"); //生成新的对应条目原始文件fullName

                    AssetDatabase.CopyAsset(entryPath, newFile);                       //创建对应新的文件

                    var aiDest = AssetImporter.GetAtPath(newFile) as TextureImporter;  //转换成texture
                    if (aiDest == null)
                    {
                        var message = "failed to get TextureImporter on new texture asset: " + newFile;
                        return(message);
                    }

                    float scaleFactor = pair.textureScale;

                    float desiredLimiter = maxDim * scaleFactor;
                    aiDest.maxTextureSize = NearestMaxTextureSize(desiredLimiter); //生成里18*32*64*128*256等最近的尺寸

                    aiDest.isReadable = true;                                      //可以通过脚本获取纹理信息

                    aiDest.SaveAndReimport();                                      //保存并导入(如果资产导入器是脏的,则保存资产导入器设置。)
                    var newEntry = aaContext.settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(newFile), newGroup);
                    newEntry.address = entry.address;                              //对应条目的名称或者地址
                    newEntry.SetLabel(pair.label, true);                           //设置为true将添加标签,设置为false将删除标签。
                }
                entry.SetLabel(schema.BaselineLabel, true);
            }
        }

        return(string.Empty);
    }
        protected override TResult DoBuild <TResult>(AddressablesDataBuilderInput builderInput, AddressableAssetsBuildContext aaContext)
        {
            // Build AssetBundles
            TResult result = base.DoBuild <TResult>(builderInput, aaContext);

            // Don't prepare content for asset packs if the build target isn't set to Android
            if (builderInput.Target != BuildTarget.Android)
            {
                Addressables.LogWarning("Build target is not set to Android. No custom asset pack config files will be created.");
                return(result);
            }

            var resetAssetPackSchemaData = !CustomAssetPackSettings.SettingsExists;
            var customAssetPackSettings  = CustomAssetPackSettings.GetSettings(true);

            CreateCustomAssetPacks(aaContext.Settings, customAssetPackSettings, resetAssetPackSchemaData);
            return(result);
        }
Beispiel #5
0
    void ProcessTextureScaler(TextureVariationSchema schema, AddressableAssetGroup assetGroup, AddressableAssetsBuildContext aaContext)
    {
        m_SourceGroupList.Add(assetGroup);

        var entries = new List <AddressableAssetEntry>(assetGroup.entries);

        foreach (var entry in entries)
        {
            foreach (var pair in schema.Variations)
            {
                entry.SetLabel(pair.label, true);
            }
            entry.SetLabel(schema.BaselineLabel, true);
        }
    }
Beispiel #6
0
    string ProcessTextureScaler(
        TextureVariationSchema schema,
        AddressableAssetGroup assetGroup,
        AddressableAssetsBuildContext aaContext)
    {
        var entries = new List <AddressableAssetEntry>(assetGroup.entries);

        foreach (var entry in entries)
        {
            var entryPath = entry.AssetPath;
            if (AssetDatabase.GetMainAssetTypeAtPath(entryPath) == typeof(Texture2D))
            {
                var fileName = Path.GetFileNameWithoutExtension(entryPath);
                if (string.IsNullOrEmpty(fileName))
                {
                    return("Failed to get file name for: " + entryPath);
                }
                if (!Directory.Exists("Assets/GeneratedTextures"))
                {
                    Directory.CreateDirectory("Assets/GeneratedTextures");
                }
                if (!Directory.Exists("Assets/GeneratedTextures/Texture"))
                {
                    Directory.CreateDirectory("Assets/GeneratedTextures/Texture");
                }

                var sourceTex = AssetDatabase.LoadAssetAtPath <Texture2D>(entryPath);
                var aiSource  = AssetImporter.GetAtPath(entryPath) as TextureImporter;
                int maxDim    = Math.Max(sourceTex.width, sourceTex.height);

                foreach (var pair in schema.Variations)
                {
                    var newGroup = FindOrCopyGroup(assetGroup.Name + "_" + pair.label, assetGroup, aaContext.Settings, schema);
                    var newFile  = entryPath.Replace(fileName, fileName + "_variationCopy_" + pair.label);
                    newFile = newFile.Replace("Assets/", "Assets/GeneratedTextures/");

                    AssetDatabase.CopyAsset(entryPath, newFile);

                    var aiDest = AssetImporter.GetAtPath(newFile) as TextureImporter;
                    if (aiDest == null)
                    {
                        var message = "failed to get TextureImporter on new texture asset: " + newFile;
                        return(message);
                    }

                    float scaleFactor = pair.textureScale;

                    float desiredLimiter = maxDim * scaleFactor;
                    aiDest.maxTextureSize = NearestMaxTextureSize(desiredLimiter);

                    aiDest.isReadable = true;

                    aiDest.SaveAndReimport();
                    var newEntry = aaContext.Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(newFile), newGroup);
                    newEntry.address = entry.address;
                    newEntry.SetLabel(pair.label, true);
                }
                entry.SetLabel(schema.BaselineLabel, true);
            }
        }

        if (!schema.IncludeSourceTextureInBuild)
        {
            assetGroup.GetSchema <BundledAssetGroupSchema>().IncludeInBuild = false;
        }
        m_SourceGroupList.Add(assetGroup); // need to reset labels for every texture variant group

        return(string.Empty);
    }
Beispiel #7
0
        protected override TResult DoBuild <TResult>(AddressablesDataBuilderInput builderInput, AddressableAssetsBuildContext aaContext)
        {
            if (Directory.Exists(ETModel.PathHelper.RemoteBuildPath))
            {
                FileHelper.CleanDirectory(ETModel.PathHelper.RemoteBuildPath);
            }

            AddressableAssetSettings settings = AssetDatabase.LoadAssetAtPath <AddressableAssetSettings>($"{AddressableAssetSettingsDefaultObject.kDefaultConfigFolder}/{AddressableAssetSettingsDefaultObject.kDefaultConfigAssetName}.asset");

            //更新Group模板的发布路径和加载路径
            UpdateGroupTemplateBuildAndLoadPath(settings, $"{settings.GroupTemplateFolder}/Packed Assets.asset");
            //UpdateGroupBuildAndLoadPath(settings, $"{settings.GroupFolder}/Default Local Group.asset");

            //清除旧有资源
            CleanGroup(settings);
            List <AddressableAssetGroupSchema> schemas = AssetDatabase.LoadAssetAtPath <AddressableAssetGroupTemplate>($"{settings.GroupTemplateFolder}/Packed Assets.asset").SchemaObjects;

            string[] directories = Directory.GetDirectories($"{UnityEngine.Application.dataPath}/AddressableAssets/");
            string   buildPath   = $"./{UnityEngine.AddressableAssets.Addressables.BuildPath}";

            tempAddress = string.Empty;
            foreach (string folderPath in directories)
            {
                if (folderPath.Substring(folderPath.LastIndexOf('/') + 1).StartsWith("~"))
                {
                    continue;
                }
                BuildGroup(folderPath, settings, schemas);
            }


            var result = base.DoBuild <TResult>(builderInput, aaContext);

            return(result);
        }
    /// <summary>
    /// The processing of the bundled asset schema.  This is where the bundle(s) for a given group are actually setup.
    /// </summary>
    /// <param name="schema">The BundledAssetGroupSchema to process</param>
    /// <param name="assetGroup">The group this schema was pulled from</param>
    /// <param name="aaContext">The general Addressables build builderInput</param>
    /// <returns>The error string, if any.</returns>
    protected virtual string ProcessBundledAssetSchema(
        BundledAssetGroupSchema schema,
        AddressableAssetGroup assetGroup,
        AddressableAssetsBuildContext aaContext)
    {
        if (schema == null || !schema.IncludeInBuild)
        {
            return(string.Empty);
        }

        var errorStr = ErrorCheckBundleSettings(schema, assetGroup, aaContext.settings);

        if (!string.IsNullOrEmpty(errorStr))
        {
            return(errorStr);
        }

        var bundledProviderId = schema.GetBundleCachedProviderId();
        var assetProviderId   = schema.GetAssetCachedProviderId();

        if (!m_CreatedProviderIds.Contains(bundledProviderId))
        {
            m_CreatedProviderIds.Add(bundledProviderId);

            var bundleProviderType = schema.AssetBundleProviderType.Value;
            var bundleProviderData = ObjectInitializationData.CreateSerializedInitializationData(bundleProviderType, bundledProviderId);
            m_ResourceProviderData.Add(bundleProviderData);
        }

        if (!m_CreatedProviderIds.Contains(assetProviderId))
        {
            m_CreatedProviderIds.Add(assetProviderId);
            var assetProviderType = schema.BundledAssetProviderType.Value;
            var assetProviderData = ObjectInitializationData.CreateSerializedInitializationData(assetProviderType, assetProviderId);
            m_ResourceProviderData.Add(assetProviderData);
        }

        var bundleInputDefs = new List <AssetBundleBuild>();

        PrepGroupBundlePacking(assetGroup, bundleInputDefs, schema.BundleMode);
        for (int i = 0; i < bundleInputDefs.Count; i++)
        {
            string assetBundleName = bundleInputDefs[i].assetBundleName;
            if (aaContext.bundleToAssetGroup.ContainsKey(assetBundleName))
            {
                int count   = 1;
                var newName = assetBundleName;
                while (aaContext.bundleToAssetGroup.ContainsKey(newName) && count < 1000)
                {
                    newName = assetBundleName.Replace(".bundle", string.Format("{0}.bundle", count++));
                }
                assetBundleName = newName;
            }

            string hashedAssetBundleName = HashingMethods.Calculate(assetBundleName) + ".bundle";
            m_OutputAssetBundleNames.Add(assetBundleName);
            m_AllBundleInputDefs.Add(new AssetBundleBuild
            {
                addressableNames   = bundleInputDefs[i].addressableNames,
                assetNames         = bundleInputDefs[i].assetNames,
                assetBundleName    = hashedAssetBundleName,
                assetBundleVariant = bundleInputDefs[i].assetBundleVariant
            });
            aaContext.bundleToAssetGroup.Add(hashedAssetBundleName, assetGroup.Guid);
        }
        return(string.Empty);
    }
        protected override TResult DoBuild <TResult>(AddressablesDataBuilderInput builderInput, AddressableAssetsBuildContext aaContext)
        {
            foreach (var assetGroup in builderInput.AddressableSettings.groups)
            {
                var schema = assetGroup.GetSchema <BundledAssetGroupSchema>();
                if (schema == null)
                {
                    continue;
                }

                SerializedType _ty = schema.AssetBundleProviderType;
                if (_ty.Value != typeof(FirebaseStorageAssetBundleProvider))
                {
                    string _errMsg = $"Firebase Build 는 '{assetGroup.name}' Group의 AssetBundleProvider 를 FirebaseStorageAssetBundleProvider 로 바꿔줘야 합니다.";
                    return(AddressableAssetBuildResult.CreateResult <TResult>(null, 0, _errMsg));
                }
            }

            //원격빌드이므로 IsRemoteCatalog 값은 true
            builderInput.AddressableSettings.BuildRemoteCatalog = true;

            var result = base.DoBuild <TResult>(builderInput, aaContext);

            var settingsPath = Addressables.BuildPath + "/" + builderInput.RuntimeSettingsFilename;

            var data = JsonUtility.FromJson <ResourceManagerRuntimeData>(File.ReadAllText(settingsPath));

            var remoteHash = data.CatalogLocations.Find(locationData =>
                                                        locationData.Keys[0] == "AddressablesMainContentCatalogRemoteHash");

            if (remoteHash != null)
            {
                var newRemoteHash = new ResourceLocationData(remoteHash.Keys, remoteHash.InternalId,
                                                             typeof(FirebaseStorageHashProvider), remoteHash.ResourceType, remoteHash.Dependencies);

                data.CatalogLocations.Remove(remoteHash);
                data.CatalogLocations.Add(newRemoteHash);
            }

            File.WriteAllText(settingsPath, JsonUtility.ToJson(data));

            Debug.Log($"Player Version : {builderInput.PlayerVersion}");

            return(result);
        }
    /// <summary>
    /// The method that does the actual building after all the groups have been processed.
    /// </summary>
    /// <param name="builderInput">The generic builderInput of the</param>
    /// <param name="aaContext"></param>
    /// <typeparam name="TResult"></typeparam>
    /// <returns></returns>
    protected virtual TResult DoBuild <TResult>(AddressablesDataBuilderInput builderInput, AddressableAssetsBuildContext aaContext) where TResult : IDataBuilderResult
    {
        ExtractDataTask extractData = new ExtractDataTask();
        var             tempPath    = Path.GetDirectoryName(Application.dataPath) + "/Library/com.unity.addressables/StreamingAssetsCopy/" + PlatformMappingService.GetPlatform() + "/addressables_content_state.bin";


        string buildPath          = "";
        var    playerBuildVersion = builderInput.PlayerVersion;

        if (m_AllBundleInputDefs.Count > 0)
        {
            if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
            {
                return(AddressableAssetBuildResult.CreateResult <TResult>(null, 0, "Unsaved scenes"));
            }

            var buildTarget      = builderInput.Target;
            var buildTargetGroup = builderInput.TargetGroup;

            var buildParams = new AddressableAssetsBundleBuildParameters(
                aaContext.settings,
                aaContext.bundleToAssetGroup,
                buildTarget,
                buildTargetGroup,
                aaContext.settings.buildSettings.bundleBuildPath);

            var builtinShaderBundleName = aaContext.settings.DefaultGroup.Guid + "_unitybuiltinshaders.bundle";
            var buildTasks = RuntimeDataBuildTasks(builtinShaderBundleName);
            buildTasks.Add(extractData);

            string aaPath = aaContext.settings.AssetPath;
            IBundleBuildResults results;
            var exitCode = ContentPipeline.BuildAssetBundles(buildParams, new BundleBuildContent(m_AllBundleInputDefs), out results, buildTasks, aaContext);

            if (exitCode < ReturnCode.Success)
            {
                return(AddressableAssetBuildResult.CreateResult <TResult>(null, 0, "SBP Error" + exitCode));
            }
            if (aaContext.settings == null && !string.IsNullOrEmpty(aaPath))
            {
                aaContext.settings = AssetDatabase.LoadAssetAtPath <AddressableAssetSettings>(aaPath);
            }

            GenerateLocationListsTask.Run(aaContext, extractData.WriteData);

            foreach (var assetGroup in aaContext.settings.groups)
            {
                if (assetGroup == null)
                {
                    continue;
                }


                List <string> buildBundles;
                if (aaContext.assetGroupToBundles.TryGetValue(assetGroup, out buildBundles))
                {
                    List <string> outputBundles = new List <string>();
                    for (int i = 0; i < buildBundles.Count; ++i)
                    {
                        var b = m_AllBundleInputDefs.FindIndex(inputDef => buildBundles[i].StartsWith(inputDef.assetBundleName));
                        outputBundles.Add(b >= 0 ? m_OutputAssetBundleNames[b] : buildBundles[i]);
                    }
                    var schema = assetGroup.GetSchema <BundledAssetGroupSchema>();
                    //schema.BuildPath.SetVariableByName( assetGroup.Settings, $"ExportedAddressables/{assetGroup.Name}/{EditorUserBuildSettings.activeBuildTarget}" );
                    //foreach ( var name in assetGroup.Settings.profileSettings.GetVariableNames() )
                    //{
                    //	Debug.Log( $"name: {name}" );
                    //}

                    //assetGroup.Settings.profileSettings.SetValue( assetGroup.Settings.activeProfileId, "BuildPath", $"ExportedAddressables/{assetGroup.Name}/{EditorUserBuildSettings.activeBuildTarget}" );

                    buildPath = schema.BuildPath.GetValue(assetGroup.Settings);
                    Debug.Log($"buildPath: {buildPath}");
                    PostProcessBundles(assetGroup, buildBundles, outputBundles, results, extractData.WriteData, aaContext.runtimeData, aaContext.locations, builderInput.Registry);
                    PostProcessCatalogEnteries(assetGroup, extractData.WriteData, aaContext.locations, builderInput.Registry);
                }
            }
            foreach (var r in results.WriteResults)
            {
                m_Linker.AddTypes(r.Value.includedTypes);
            }
        }

        //save catalog
        var contentCatalog = new ContentCatalogData(aaContext.locations, ResourceManagerRuntimeData.kCatalogAddress);

        contentCatalog.ResourceProviderData.AddRange(m_ResourceProviderData);
        foreach (var t in aaContext.providerTypes)
        {
            contentCatalog.ResourceProviderData.Add(ObjectInitializationData.CreateSerializedInitializationData(t));
        }

        contentCatalog.InstanceProviderData = ObjectInitializationData.CreateSerializedInitializationData(instanceProviderType.Value);
        contentCatalog.SceneProviderData    = ObjectInitializationData.CreateSerializedInitializationData(sceneProviderType.Value);
        CreateCatalog(aaContext.settings, contentCatalog, aaContext.runtimeData.CatalogLocations, playerBuildVersion, builderInput.RuntimeCatalogFilename, builderInput.Registry, buildPath);
        foreach (var pd in contentCatalog.ResourceProviderData)
        {
            m_Linker.AddTypes(pd.ObjectType.Value);
            m_Linker.AddTypes(pd.GetRuntimeTypes());
        }
        m_Linker.AddTypes(contentCatalog.InstanceProviderData.ObjectType.Value);
        m_Linker.AddTypes(contentCatalog.InstanceProviderData.GetRuntimeTypes());
        m_Linker.AddTypes(contentCatalog.SceneProviderData.ObjectType.Value);
        m_Linker.AddTypes(contentCatalog.SceneProviderData.GetRuntimeTypes());

        foreach (var io in aaContext.settings.InitializationObjects)
        {
            var provider = io as IObjectInitializationDataProvider;
            if (provider != null)
            {
                var id = provider.CreateObjectInitializationData();
                aaContext.runtimeData.InitializationObjects.Add(id);
                m_Linker.AddTypes(id.ObjectType.Value);
                m_Linker.AddTypes(id.GetRuntimeTypes());
            }
        }

        aaContext.runtimeData.DisableCatalogUpdateOnStartup = aaContext.settings.DisableCatalogUpdateOnStartup;

        m_Linker.AddTypes(typeof(Addressables));
        m_Linker.Save(buildPath + "/link.xml");
        var settingsPath = buildPath + "/" + builderInput.RuntimeSettingsFilename;

        WriteFile(settingsPath, JsonUtility.ToJson(aaContext.runtimeData), builderInput.Registry);

        var opResult = AddressableAssetBuildResult.CreateResult <TResult>(settingsPath, aaContext.locations.Count);
        //save content update data if building for the player
        var allEntries = new List <AddressableAssetEntry>();

        aaContext.settings.GetAllAssets(allEntries, false, g => g != null && g.HasSchema <ContentUpdateGroupSchema>() && g.GetSchema <ContentUpdateGroupSchema>().StaticContent);

        var remoteCatalogLoadPath = aaContext.settings.BuildRemoteCatalog ? aaContext.settings.RemoteCatalogLoadPath.GetValue(aaContext.settings) : string.Empty;

        if (extractData.BuildCache != null && ContentUpdateScript.SaveContentState(aaContext.locations, tempPath, allEntries, extractData.DependencyData, playerBuildVersion, remoteCatalogLoadPath))
        {
            try
            {
                var contentStatePath = ContentUpdateScript.GetContentStateDataPath(false);
                File.Copy(tempPath, contentStatePath, true);
                builderInput.Registry.AddFile(contentStatePath);
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }
        }

        return(opResult);
    }
    /// <summary>
    /// Called per group per schema to evaluate that schema.  This can be an easy entry point for implementing the
    ///  build aspects surrounding a custom schema.  Note, you should not rely on schemas getting called in a specific
    ///  order.
    /// </summary>
    /// <param name="schema">The schema to process</param>
    /// <param name="assetGroup">The group this schema was pulled from</param>
    /// <param name="aaContext">The general Addressables build builderInput</param>
    /// <returns></returns>
    protected virtual string ProcessGroupSchema(AddressableAssetGroupSchema schema, AddressableAssetGroup assetGroup, AddressableAssetsBuildContext aaContext)
    {
        var playerDataSchema = schema as PlayerDataGroupSchema;

        if (playerDataSchema != null)
        {
            return(ProcessPlayerDataSchema(playerDataSchema, assetGroup, aaContext));
        }
        var bundledAssetSchema = schema as BundledAssetGroupSchema;

        if (bundledAssetSchema != null)
        {
            return(ProcessBundledAssetSchema(bundledAssetSchema, assetGroup, aaContext));
        }
        return(string.Empty);
    }
        List <AnalyzeResult> DoFakeBuild(AddressableAssetSettings settings)
        {
            m_ImplicitAssets = new HashSet <GUID>();
            List <AnalyzeResult> emptyResult = new List <AnalyzeResult>();

            emptyResult.Add(new AnalyzeResult(ruleName + " - No issues found"));
            var context = new AddressablesDataBuilderInput(settings);
            var timer   = new Stopwatch();

            timer.Start();
            var aaSettings = context.AddressableSettings;

            //gather entries
            var locations          = new List <ContentCatalogDataEntry>();
            var allBundleInputDefs = new List <AssetBundleBuild>();
            var bundleToAssetGroup = new Dictionary <string, string>();
            var runtimeData        = new ResourceManagerRuntimeData();

            runtimeData.LogResourceManagerExceptions = aaSettings.buildSettings.LogResourceManagerExceptions;

            foreach (var assetGroup in aaSettings.groups)
            {
                var schema = assetGroup.GetSchema <BundledAssetGroupSchema>();
                if (schema == null)
                {
                    continue;
                }

                var bundleInputDefs = new List <AssetBundleBuild>();
                BuildScriptPackedMode.PrepGroupBundlePacking(assetGroup, bundleInputDefs, locations, schema.BundleMode);
                for (int i = 0; i < bundleInputDefs.Count; i++)
                {
                    if (bundleToAssetGroup.ContainsKey(bundleInputDefs[i].assetBundleName))
                    {
                        var bid     = bundleInputDefs[i];
                        int count   = 1;
                        var newName = bid.assetBundleName;
                        while (bundleToAssetGroup.ContainsKey(newName) && count < 1000)
                        {
                            newName = bid.assetBundleName.Replace(".bundle", string.Format("{0}.bundle", count++));
                        }
                        bundleInputDefs[i] = new AssetBundleBuild {
                            assetBundleName = newName, addressableNames = bid.addressableNames, assetBundleVariant = bid.assetBundleVariant, assetNames = bid.assetNames
                        };
                    }

                    bundleToAssetGroup.Add(bundleInputDefs[i].assetBundleName, assetGroup.Guid);
                }
                allBundleInputDefs.AddRange(bundleInputDefs);
            }
            ExtractDataTask extractData = new ExtractDataTask();

            if (allBundleInputDefs.Count > 0)
            {
                if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
                {
                    Debug.LogError("Cannot run Analyze with unsaved scenes");
                    return(emptyResult);
                }

                var buildTarget             = context.Target;
                var buildTargetGroup        = context.TargetGroup;
                var buildParams             = new AddressableAssetsBundleBuildParameters(aaSettings, bundleToAssetGroup, buildTarget, buildTargetGroup, aaSettings.buildSettings.bundleBuildPath);
                var builtinShaderBundleName = aaSettings.DefaultGroup.Name.ToLower().Replace(" ", "").Replace('\\', '/').Replace("//", "/") + "_unitybuiltinshaders.bundle";
                var buildTasks = RuntimeDataBuildTasks(builtinShaderBundleName);
                buildTasks.Add(extractData);

                var aaContext = new AddressableAssetsBuildContext
                {
                    settings           = aaSettings,
                    runtimeData        = runtimeData,
                    bundleToAssetGroup = bundleToAssetGroup,
                    locations          = locations
                };

                IBundleBuildResults buildResults;
                var exitCode = ContentPipeline.BuildAssetBundles(buildParams, new BundleBuildContent(allBundleInputDefs), out buildResults, buildTasks, aaContext);
                GenerateLocationListsTask.Run(aaContext, extractData.WriteData);
                if (exitCode < ReturnCode.Success)
                {
                    Debug.LogError("Analyze build failed. " + exitCode);
                    return(emptyResult);
                }

                HashSet <GUID> explicitGuids = new HashSet <GUID>();
                foreach (var atf in extractData.WriteData.AssetToFiles)
                {
                    explicitGuids.Add(atf.Key);
                }

                Dictionary <GUID, List <string> > implicitGuids = new Dictionary <GUID, List <string> >();
                foreach (var fto in extractData.WriteData.FileToObjects)
                {
                    foreach (ObjectIdentifier g in fto.Value)
                    {
                        if (!explicitGuids.Contains(g.guid))
                        {
                            if (!implicitGuids.ContainsKey(g.guid))
                            {
                                implicitGuids.Add(g.guid, new List <string>());
                            }
                            implicitGuids[g.guid].Add(fto.Key);
                        }
                    }
                }

                //dictionary<group, dictionary<bundle, implicit assets >>
                Dictionary <string, Dictionary <string, List <string> > > allIssues = new Dictionary <string, Dictionary <string, List <string> > >();
                foreach (var g in implicitGuids)
                {
                    if (g.Value.Count > 1) //it's duplicated...
                    {
                        var path = AssetDatabase.GUIDToAssetPath(g.Key.ToString());
                        if (!AddressableAssetUtility.IsPathValidForEntry(path) ||
                            path.ToLower().Contains("/resources/") ||
                            path.ToLower().StartsWith("resources/"))
                        {
                            continue;
                        }

                        foreach (var file in g.Value)
                        {
                            var    bun = extractData.WriteData.FileToBundle[file];
                            string groupGuid;
                            if (aaContext.bundleToAssetGroup.TryGetValue(bun, out groupGuid))
                            {
                                var group = aaSettings.FindGroup(grp => grp.Guid == groupGuid);
                                if (group != null)
                                {
                                    Dictionary <string, List <string> > groupData;
                                    if (!allIssues.TryGetValue(group.Name, out groupData))
                                    {
                                        groupData = new Dictionary <string, List <string> >();
                                        allIssues.Add(group.Name, groupData);
                                    }

                                    List <string> assets;
                                    if (!groupData.TryGetValue(bun, out assets))
                                    {
                                        assets = new List <string>();
                                        groupData.Add(bun, assets);
                                    }
                                    assets.Add(path);

                                    m_ImplicitAssets.Add(g.Key);
                                }
                            }
                        }
                    }
                }

                List <AnalyzeResult> result = new List <AnalyzeResult>();
                foreach (var group in allIssues)
                {
                    foreach (var bundle in group.Value)
                    {
                        foreach (var item in bundle.Value)
                        {
                            var issueName = ruleName + kDelimiter + group.Key + kDelimiter + bundle.Key + kDelimiter + item;
                            result.Add(new AnalyzeResult(issueName, MessageType.Warning));
                        }
                    }
                }

                if (result.Count > 0)
                {
                    return(result);
                }
            }
            return(emptyResult);
        }
    protected override TResult DoBuild <TResult>(AddressablesDataBuilderInput builderInput, AddressableAssetsBuildContext aaContext)
    {
        List <string> buildInABHashLines = new List <string>();

        TResult opResult = base.DoBuild <TResult>(builderInput, aaContext);
        var     groups   = aaContext.Settings.groups;

        for (int i = 0; i < groups.Count; i++)
        {
            List <string> bundles;
            if (aaContext.assetGroupToBundles.TryGetValue(groups[i], out bundles))
            {
                var locations = aaContext.locations;
                for (int j = 0; j < locations.Count; j++)
                {
                    var d = locations[j].Data as AssetBundleRequestOptions;
                    if (d != null)
                    {
                        for (int k = 0; k < bundles.Count; k++)
                        {
                            if (d.BundleName == bundles[k])
                            {
                                if (d.BundleSize > 2097152 || d.BundleSize < 1572864)//大于2M和小于1.5M的
                                {
                                    // Logger.Log(string.Format("the size of group:{0} is {1},bundleName is :{2}", groups[i].name, GetFormatSizeString(d.BundleSize), bundles[k]));
                                }
                                else
                                {
                                    //Logger.Log(string.Format("the size of group:{0} is {1},bundleName is :{2}", groups[i].name, GetFormatSizeString(d.BundleSize), bundles[k]));
                                }
                                if (IsBuildInAssetBundle(groups[i].name))
                                {
                                    buildInABHashLines.Add(d.Hash);
                                }
                            }
                        }
                    }
                }
            }
        }

        //写文件
        string RuntimePath = UnityEngine.AddressableAssets.Addressables.RuntimePath;
        string BuildInABHashInfoFilePath = Path.Combine(System.Environment.CurrentDirectory, RuntimePath, "BuildInABHashFile.bytes");

        //   Logger.Log("BuildInABHashInfoFilePath  = " + BuildInABHashInfoFilePath);
        if (File.Exists(BuildInABHashInfoFilePath))
        {
            File.Delete(BuildInABHashInfoFilePath);
        }
        Debug.Log(buildInABHashLines);
        File.WriteAllLines(BuildInABHashInfoFilePath, buildInABHashLines);

        return(opResult);
    }
        protected override string ProcessGroup(AddressableAssetGroup assetGroup, AddressableAssetsBuildContext aaContext)
        {
            bool include = Check(assetGroup);

            return(include ? base.ProcessGroup(assetGroup, aaContext) : string.Empty);
        }
    public void AddHashToBundleNameTask_DoesNotChangeHash_WhenAssetsChangeOrder()
    {
        //Setup
        string path1 = $"{TempPath}/test1.prefab";
        string path2 = $"{TempPath}/test2.prefab";
        string path3 = $"{TempPath}/test3.prefab";

        GUID guid1 = new GUID(CreateAsset(path1, "1"));
        GUID guid2 = new GUID(CreateAsset(path2, "2"));
        GUID guid3 = new GUID(CreateAsset(path3, "3"));

        List <GUID> list1 = new List <GUID>()
        {
            guid1,
            guid2,
            guid3
        };

        List <GUID> list2 = new List <GUID>()
        {
            guid2,
            guid1,
            guid3
        };

        AddressableAssetGroup group = m_Settings.CreateGroup("AddHashTestGroup", false, false, false,
                                                             new List <AddressableAssetGroupSchema>());

        m_Settings.CreateOrMoveEntry(guid1.ToString(), group);
        m_Settings.CreateOrMoveEntry(guid2.ToString(), group);
        m_Settings.CreateOrMoveEntry(guid3.ToString(), group);

        IDependencyData dependencyData = new BuildDependencyData()
        {
            AssetInfo =
            {
                { guid1, new AssetLoadInfo()
                    {
                        referencedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(guid1, EditorUserBuildSettings.activeBuildTarget).ToList()
                    } },
                { guid2, new AssetLoadInfo()
                    {
                        referencedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(guid2, EditorUserBuildSettings.activeBuildTarget).ToList()
                    } },
                { guid3, new AssetLoadInfo()
                    {
                        referencedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(guid3, EditorUserBuildSettings.activeBuildTarget).ToList()
                    } }
            }
        };

        AddressableAssetsBuildContext context = new AddressableAssetsBuildContext()
        {
            Settings = m_Settings
        };

        AddHashToBundleNameTask addHashTask = new AddHashToBundleNameTask();
        var field = typeof(AddHashToBundleNameTask).GetField("m_DependencyData", BindingFlags.Instance | BindingFlags.NonPublic);

        field.SetValue(addHashTask, dependencyData);

        //Test
        RawHash hash1 = addHashTask.GetAssetsHash(list1, context);
        RawHash hash2 = addHashTask.GetAssetsHash(list2, context);

        //Assert
        Assert.AreEqual(hash1, hash2);

        //Cleanup
        m_Settings.RemoveGroup(group);
    }
Beispiel #16
0
    protected override TResult DoBuild <TResult>(AddressablesDataBuilderInput builderInput, AddressableAssetsBuildContext aaContext)
    {
        var buildResult = base.DoBuild <TResult>(builderInput, aaContext);

        if (aaContext.settings.BuildRemoteCatalog)
        {
            PatchSettingsFile(builderInput);
        }
        else
        {
            Debug.LogWarning("[TheGamedevGuru] PlayFab: Addressables Remote Catalog is not enabled, skipping patching of the settings file");
        }
        return(buildResult);
    }
Beispiel #17
0
    protected override TResult BuildDataImplementation <TResult>(AddressablesDataBuilderInput context)
    {
        TResult result = default(TResult);

        var timer = new Stopwatch();

        timer.Start();
        var aaSettings = context.AddressableSettings;
        var pathFormat = "{0}Library/com.unity.addressables/{1}_BuildScriptFastMode.json";

        //create runtime data
        var aaContext = new AddressableAssetsBuildContext
        {
            Settings           = aaSettings,
            runtimeData        = new ResourceManagerRuntimeData(),
            bundleToAssetGroup = null,
            locations          = new List <ContentCatalogDataEntry>()
        };

        aaContext.runtimeData.BuildTarget = context.Target.ToString();
        aaContext.runtimeData.LogResourceManagerExceptions = aaSettings.buildSettings.LogResourceManagerExceptions;
        aaContext.runtimeData.ProfileEvents = context.ProfilerEventsEnabled;
        aaContext.runtimeData.CatalogLocations.Add(new ResourceLocationData(new[] { ResourceManagerRuntimeData.kCatalogAddress },
                                                                            string.Format(pathFormat, "file://{UnityEngine.Application.dataPath}/../", "catalog"),
                                                                            typeof(ContentCatalogProvider),
                                                                            typeof(ContentCatalogData)));

        var errorString = ProcessAllGroups(aaContext);

        if (!string.IsNullOrEmpty(errorString))
        {
            result = AddressableAssetBuildResult.CreateResult <TResult>(null, 0, errorString);
        }

        if (result == null)
        {
            foreach (var io in aaSettings.InitializationObjects)
            {
                if (io is IObjectInitializationDataProvider)
                {
                    aaContext.runtimeData.InitializationObjects.Add((io as IObjectInitializationDataProvider).CreateObjectInitializationData());
                }
            }

            var settingsPath = string.Format(pathFormat, "", "settings");
            WriteFile(settingsPath, JsonUtility.ToJson(aaContext.runtimeData), context.Registry);

            //save catalog
            var catalogData = new ContentCatalogData(aaContext.locations);
            if (m_legacy)
            {
                catalogData.ResourceProviderData.Add(ObjectInitializationData.CreateSerializedInitializationData(typeof(LegacyResourcesProvider)));
            }
            catalogData.ResourceProviderData.Add(ObjectInitializationData.CreateSerializedInitializationData <SyncAssetDatabaseProvider>());
            catalogData.InstanceProviderData = ObjectInitializationData.CreateSerializedInitializationData(instanceProviderType.Value);
            catalogData.SceneProviderData    = ObjectInitializationData.CreateSerializedInitializationData(sceneProviderType.Value);
            WriteFile(string.Format(pathFormat, "", "catalog"), JsonUtility.ToJson(catalogData), context.Registry);


            //inform runtime of the init data path
            var runtimeSettingsPath = string.Format(pathFormat, "file://{UnityEngine.Application.dataPath}/../", "settings");
            PlayerPrefs.SetString(Addressables.kAddressablesRuntimeDataPath, runtimeSettingsPath);
            result = AddressableAssetBuildResult.CreateResult <TResult>(settingsPath, aaContext.locations.Count);
        }

        if (result != null)
        {
            result.Duration = timer.Elapsed.TotalSeconds;
        }

        return(result);
    }
        string ProcessVariants(ProcessVariantAssetsSchema schema, AddressableAssetGroup group, AddressableAssetsBuildContext context)
        {
            var settings = context.Settings;

            var entries = new List <AddressableAssetEntry>(group.entries);

            foreach (var mainEntry in entries)
            {
                if (AssetDatabase.GetMainAssetTypeAtPath(mainEntry.AssetPath) != typeof(GameObject))
                {
                    continue;
                }

                GameObject mainAsset = AssetDatabase.LoadMainAssetAtPath(mainEntry.AssetPath) as GameObject;
                if (!schema.PreprocessCheck(mainAsset))
                {
                    continue;
                }

                string fileName      = Path.GetFileNameWithoutExtension(mainEntry.AssetPath);
                string mainAssetPath = AssetDatabase.GUIDToAssetPath(mainEntry.guid);

                string groupDirectory = Path.Combine(defaultBaseDirectory, $"{group.Name}").Replace('\\', '/');
                string newPrefabPath  = groupDirectory + '/' + Path.GetFileName(mainEntry.AssetPath).Replace(fileName, $"{fileName}_variant");
                Directory.CreateDirectory(groupDirectory);

                if (!AssetDatabase.CopyAsset(mainAssetPath, newPrefabPath))
                {
                    Debug.LogError("Failed to copy asset " + mainAssetPath);
                    continue;
                }
                if (schema.deleteVariants)
                {
                    variantsPrefabsToDelete.Add(newPrefabPath);
                }
                GameObject variant = AssetDatabase.LoadAssetAtPath <GameObject>(newPrefabPath);

                foreach (var script in schema.variantAssetsScripts)
                {
                    script.ProcessVariantAsset(variant);
                }

                //Create the Variant Entry and set it's address and labels.
                var variantEntry = settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(newPrefabPath), mainEntry.parentGroup, false, false);
                variantEntry.address = mainEntry.address;
                foreach (string label in mainEntry.labels)
                {
                    variantEntry.SetLabel(label, true, false, false);
                }
                variantEntriesToRemove.Add(AssetDatabase.AssetPathToGUID(newPrefabPath));
                entriesToRestore.Add(new AssetEntry {
                    address = mainEntry.address, assetGUID = mainEntry.guid, group = mainEntry.parentGroup, labels = mainEntry.labels
                });
                settings.RemoveAssetEntry(AssetDatabase.AssetPathToGUID(mainEntry.AssetPath), false);
            }

            return(string.Empty);
        }
Beispiel #19
0
    string ProcessVariants(PrefabTextureVariantSchema schema,
                           AddressableAssetGroup group,
                           AddressableAssetsBuildContext context)
    {
        var settings = context.Settings;

        Directory.CreateDirectory(m_BaseDirectory);

        var entries = new List <AddressableAssetEntry>(group.entries);

        foreach (var mainEntry in entries)
        {
            if (AssetDatabase.GetMainAssetTypeAtPath(mainEntry.AssetPath) != typeof(GameObject))
            {
                continue;
            }

            string fileName = Path.GetFileNameWithoutExtension(mainEntry.AssetPath);
            string ext      = Path.GetExtension(mainEntry.AssetPath);
            mainEntry.SetLabel(schema.DefaultLabel, true, true);

            string  mainAssetPath = AssetDatabase.GUIDToAssetPath(mainEntry.guid);
            Hash128 assetHash     = AssetDatabase.GetAssetDependencyHash(mainAssetPath);

            bool assetHashChanged = false;
            if (!m_AssetPathToHashCode.ContainsKey(mainAssetPath))
            {
                m_AssetPathToHashCode.Add(mainAssetPath, assetHash);
            }
            else if (m_AssetPathToHashCode[mainAssetPath] != assetHash)
            {
                assetHashChanged = true;
                m_AssetPathToHashCode[mainAssetPath] = assetHash;
            }

            foreach (var variant in schema.Variants)
            {
                string groupDirectory = Path.Combine(m_BaseDirectory, $"{group.Name}-{Path.GetFileNameWithoutExtension(mainEntry.address)}").Replace('\\', '/');
                m_DirectoriesInUse.Add(groupDirectory);
                var variantGroup = CreateTemporaryGroupCopy($"{group.Name}_VariantGroup_{variant.Label}", group.Schemas, settings);

                string baseVariantDirectory = Path.Combine(groupDirectory, variant.Label).Replace('\\', '/');
                string newPrefabPath        = mainAssetPath.Replace("Assets/", baseVariantDirectory + '/').Replace($"{fileName}{ext}", $"{fileName}_variant_{variant.Label}{ext}");

                string variantDirectory = Path.GetDirectoryName(newPrefabPath).Replace('\\', '/');
                m_DirectoriesInUse.Add(variantDirectory);
                Directory.CreateDirectory(variantDirectory);

                if (assetHashChanged || !File.Exists(newPrefabPath))
                {
                    if (!AssetDatabase.CopyAsset(mainAssetPath, newPrefabPath))
                    {
                        return($"Copying asset from {mainAssetPath} to variant path {newPrefabPath} failed.");
                    }
                }

                var dependencies = AssetDatabase.GetDependencies(newPrefabPath);
                foreach (var dependency in dependencies)
                {
                    if (AssetDatabase.GetMainAssetTypeAtPath(dependency) == typeof(GameObject))
                    {
                        var gameObject = AssetDatabase.LoadAssetAtPath <GameObject>(dependency);
                        foreach (var childRender in gameObject.GetComponentsInChildren <MeshRenderer>())
                        {
                            ConvertToVariant(childRender, variantDirectory, variant, assetHashChanged);
                        }
                    }
                }

                var entry = settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(newPrefabPath), variantGroup, false, false);
                entry.address = mainEntry.address;
                entry.SetLabel(variant.Label, true, true, false);
            }
        }

        if (!schema.IncludeSourcePrefabInBuild)
        {
            group.GetSchema <BundledAssetGroupSchema>().IncludeInBuild = false;
            m_SourceGroupList.Add(group);
        }

        return(string.Empty);
    }
Beispiel #20
0
    internal IEnumerable <CheckDupeResult> CalculateDuplicates(Dictionary <GUID, List <string> > implicitGuids, AddressableAssetsBuildContext aaContext)
    {
        //Get all guids that have more than one bundle referencing them
        IEnumerable <KeyValuePair <GUID, List <string> > > validGuids =
            from dupeGuid in implicitGuids
            where dupeGuid.Value.Distinct().Count() > 1
            where IsValidPath(AssetDatabase.GUIDToAssetPath(dupeGuid.Key.ToString()))
            select dupeGuid;

        // Key = bundle parents
        // Value = asset paths that share the same bundle parents
        duplicateAssetsAndParents.Clear();
        foreach (var entry in validGuids)
        {
            string        assetPath    = AssetDatabase.GUIDToAssetPath(entry.Key.ToString());
            List <string> assetParents = entry.Value;
            // Purge duplicate parents (assets inside a Scene can show multiple copies of the Scene AssetBundle as a parent)
            List <string> nonDupeParents = new List <string>();
            foreach (var parent in assetParents)
            {
                if (nonDupeParents.Contains(parent))
                {
                    continue;
                }
                nonDupeParents.Add(parent);
            }
            assetParents = nonDupeParents;
            bool found = false;
            // Try to find assetParents in existing dictionary
            foreach (var bundleParentSetup in duplicateAssetsAndParents.Keys)
            {
                if (Enumerable.SequenceEqual(bundleParentSetup, assetParents))
                {
                    duplicateAssetsAndParents[bundleParentSetup].Add(assetPath);
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                duplicateAssetsAndParents.Add(assetParents, new List <string>()
                {
                    assetPath
                });
            }
        }

        return
            (from guidToFile in validGuids
             from file in guidToFile.Value

             //Get the files that belong to those guids
             let fileToBundle = m_ExtractData.WriteData.FileToBundle[file]

                                //Get the bundles that belong to those files
                                let bundleToGroup = aaContext.bundleToAssetGroup[fileToBundle]

                                                    //Get the asset groups that belong to those bundles
                                                    let selectedGroup = aaContext.Settings.FindGroup(findGroup => findGroup != null && findGroup.Guid == bundleToGroup)

                                                                        select new CheckDupeResult
        {
            Group = selectedGroup,
            DuplicatedFile = file,
            AssetPath = AssetDatabase.GUIDToAssetPath(guidToFile.Key.ToString()),
            DuplicatedGroupGuid = guidToFile.Key
        });
    }