Пример #1
0
    public LateReferenceProcessor(IList <string> assetPaths)
    {
        var objSet = new HashSet <UnityEngine.Object>();

        AssetId.CurrentGenerator = obj => {
            string id = AssetId.DefaultGenerator(obj);

            if (!string.IsNullOrEmpty(id))
            {
                objSet.Add(obj);
            }

            return(id);
        };

        foreach (string assetPath in ScanningUtils.ItemsProcessor(assetPaths,
                                                                  "Scanning assets for late references",
                                                                  p => Path.GetFileName(p)))
        {
            var asset = AssetDatabase.LoadMainAssetAtPath(assetPath);
            ProcessObject(asset);
        }


        AssetId.CurrentGenerator = AssetId.DefaultGenerator;

        _referencedObjects = objSet.ToList();
    }
Пример #2
0
    private bool IsLateAttributeField(object obj, FieldInfo field, out FieldInfo targetField, bool performChecks)
    {
        targetField = null;

        LateAttribute lazyAttribute = Attribute.GetCustomAttribute(field, typeof(LateAttribute)) as LateAttribute;

        if (lazyAttribute == null)
        {
            return(false);
        }

        string targetIdField = lazyAttribute.TargetIdField ?? (field.Name + (field.FieldType.IsArray ? "Ids" : "Id"));

        targetField = obj.GetType().GetField(targetIdField, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
        if (targetField == null)
        {
            throw new UnityException(FormatTargetFieldErrorMessage("does not exist", obj, field, lazyAttribute.TargetIdField));
        }

        if (performChecks)
        {
            if (ScanningUtils.IsSerializableArray(field.FieldType))
            {
                if (!typeof(UnityEngine.Object).IsAssignableFrom(ScanningUtils.GetSerializableArrayType(field.FieldType)))
                {
                    throw new UnityException(FormatLateFieldErrorMessage("is not an UnityEngine.Object assignable array", obj, field.Name));
                }

                if (ScanningUtils.GetSerializableArrayType(targetField.FieldType) != typeof(string))
                {
                    throw new UnityException(FormatTargetFieldErrorMessage("is not a string array", obj, field, targetIdField));
                }
            }
            else
            {
                if (!typeof(UnityEngine.Object).IsAssignableFrom(field.FieldType))
                {
                    throw new UnityException(FormatLateFieldErrorMessage("is not an UnityEngine.Object assignable", obj, field.Name));
                }

                if (targetField.FieldType != typeof(string))
                {
                    throw new UnityException(FormatTargetFieldErrorMessage("is not a string", obj, field, targetIdField));
                }
            }

            if (!targetField.IsPublic && Attribute.GetCustomAttribute(targetField, typeof(SerializeField)) == null)
            {
                throw new UnityException(FormatTargetFieldErrorMessage("is not public or have [SerializeField] attribute", obj, field, lazyAttribute.TargetIdField));
            }

            if (targetField.IsPublic && Attribute.GetCustomAttribute(targetField, typeof(HideInInspector)) == null)
            {
                Debug.LogWarning(FormatTargetFieldErrorMessage("is public but don't have the [HideInInspector] attribute, " +
                                                               "this field is not meant to be editable by users", obj, field, lazyAttribute.TargetIdField));
            }
        }

        return(true);
    }
Пример #3
0
    private bool DetargetLateAttributeField(object obj, FieldInfo field)
    {
        FieldInfo targetField;

        if (IsLateAttributeField(obj, field, out targetField, true))
        {
            if (ScanningUtils.IsSerializableArray(field.FieldType))
            {
                IList referencesArray = (IList)field.GetValue(obj);

                var idsArray = new string[referencesArray.Count];
                for (int i = 0; i < referencesArray.Count; i++)
                {
                    UnityEngine.Object val = (UnityEngine.Object)referencesArray[i];
                    idsArray[i]        = AssetId.FromObject(val);
                    referencesArray[i] = null;
                }

                targetField.SetValue(obj, (object)idsArray);
            }
            else
            {
                UnityEngine.Object val = (UnityEngine.Object)field.GetValue(obj);
                targetField.SetValue(obj, (object)AssetId.FromObject(val));
                field.SetValue(obj, null);
            }

            return(true);
        }

        return(false);
    }
Пример #4
0
    private bool DetargetObject(UnityEngine.Object obj)
    {
        bool modified = false;

        foreach (var info in ScanningUtils.ScanObjectFields(obj))
        {
            //if (DetargetLateAttributeField(info.Obj, info.Field))
            //	modified = true;

            if (DetargetLateAttributeField(info.Obj, info.Field))
            {
                modified = true;

                                #if KEEP_BROKEN_LINKS
                if (modified)
                {
                    EditorUtility.SetDirty(obj);
                }
                                #endif

                //Console.WriteLine("---" + AssetDatabase.GetAssetPath(obj) + " true");
            }
            else
            {
                //Console.WriteLine("---" + AssetDatabase.GetAssetPath(obj) + " false");
            }
        }

        return(modified);
    }
Пример #5
0
    public static string[] CollectBuildAssets()
    {
        string oldScene = EditorApplication.currentScene;

        try
        {
            var buildAssets = new HashSet <string>();
            var scenes      = CollectBuildScenes();

            foreach (var scene in ScanningUtils.ItemsProcessor(scenes, "Collecting build assets", p => Path.GetFileName(p)))
            {
                EditorApplication.OpenScene(scene);

                buildAssets.Add(scene);
                UnityEngine.Debug.Log("current scene: " + scene);
                buildAssets.UnionWith(ScanningUtils.ScanCurrentSceneAssets().Select(o => AssetDatabase.GetAssetPath(o)));
            }

            buildAssets.Remove("");
            return(buildAssets.OrderBy(p => p).ToArray());
        }
        finally
        {
            EditorApplication.OpenScene(oldScene);
        }
    }
Пример #6
0
    // Note: Hashes are calculated for source files since unity seems to
    // serialize material maps in a way that yields a random order
    private void ComputeBuildAssetsHashes()
    {
        _buildAssetsHashes = new byte[_buildAssets.Length][];

        int i = 0;

        foreach (var assetPath in ScanningUtils.ItemsProcessor(_buildAssets, "Computing assets hashes", p => Path.GetFileName(p)))
        {
            _buildAssetsHashes[i] = BuilderCache.Instance.GetHashForAsset(assetPath);
            i++;
        }
    }
Пример #7
0
    private void MapBundles()
    {
        var bundlesMap = new Dictionary <string, AssetBundleBuildInfo>();

        foreach (string assetPath in ScanningUtils.ItemsProcessor(_buildAssets, "Mapping asset to bundles", p => Path.GetFileName(p)))
        {
            string matchAssetPath = assetPath.ToLower().Substring("assets/".Length);

            var rule = _bundlesConfig.MatchRules(matchAssetPath);
            if (rule != null && rule.Type == AssetBundlesConfig.RuleType.Include && !string.IsNullOrEmpty(rule.BundleName))
            {
                bool isSceneAsset = Path.GetExtension(assetPath) == ".unity";

                string bundleName = rule.GetReplacedBundleName(matchAssetPath);

                AssetBundleBuildInfo bundleInfo;
                if (!bundlesMap.TryGetValue(bundleName, out bundleInfo))
                {
                    bundleInfo = new AssetBundleBuildInfo(bundleName, rule, isSceneAsset);
                    bundlesMap.Add(bundleName, bundleInfo);
                }

                if (isSceneAsset)
                {
                    if (!bundleInfo.IsScene)
                    {
                        throw new UnityException("Scenes can only be added to scene bundles");
                    }
                }
                else
                {
                    var importer = AssetImporter.GetAtPath(assetPath);
                    if (importer != null)
                    {
                        AudioImporter audioImporter = importer as AudioImporter;
                        if (audioImporter != null)
                        {
                            //if (audioImporter.loadType == AudioImporterLoadType.StreamFromDisc)
                            //	throw new UnityException("Can't add streamed audio clips to asset bundles: " + assetPath);
                        }
                    }
                }

                bundleInfo.AssetsPaths.Add(assetPath);
            }
        }

        _bundles = bundlesMap.Values.OrderBy(b => b.Order).ThenBy(b => b.Name).ToList();
    }
Пример #8
0
    private void CreateLateResources(IList <UnityEngine.Object> objects)
    {
        const string lateResourcesDirectory = "Assets/Resources/Late";

        BuildUtils.PrepareCleanDirectory(lateResourcesDirectory);

        foreach (var obj in ScanningUtils.ItemsProcessor(objects,
                                                         "Creating late resources",
                                                         p => AssetDatabase.GetAssetPath(p)))
        {
            var lateResource = ScriptableObject.CreateInstance <LateResource>();
            lateResource.Target = obj;
            AssetDatabase.CreateAsset(lateResource, lateResourcesDirectory + "/" + AssetId.FromObject(obj) + ".asset");
        }
    }
Пример #9
0
    private bool ProcessObject(UnityEngine.Object sourceObj)
    {
        if (!(sourceObj is GameObject) && !(sourceObj is ScriptableObject))
        {
            return(false);
        }

        bool ret = false;

        foreach (var obj in ScanningUtils.ScanObject(sourceObj))
        {
            if (DetargetObject(obj))
            {
                _processedObjects.Add(obj);
                ret = true;
            }
        }

        return(ret);
    }
Пример #10
0
    private bool RetargetObject(UnityEngine.Object obj)
    {
        bool modified = false;

        foreach (var info in ScanningUtils.ScanObjectFields(obj))
        {
            if (RetargetLateAttributeField(info.Obj, info.Field))
            {
                modified = true;
            }
        }

                #if DEBUG_KEEP_IDS
        if (modified)
        {
            EditorUtility.SetDirty(obj);
        }
                #endif

        return(modified);
    }
Пример #11
0
    private bool RetargetLateAttributeField(object obj, FieldInfo field)
    {
        FieldInfo targetField;

        if (IsLateAttributeField(obj, field, out targetField, false))
        {
            if (ScanningUtils.IsSerializableArray(field.FieldType))
            {
                IList idsArray = (IList)targetField.GetValue(obj);

                UnityEngine.Object[] referencesArray = (UnityEngine.Object[])Activator.CreateInstance(field.FieldType, new object[] { idsArray.Count });
                for (int i = 0; i < idsArray.Count; i++)
                {
                    referencesArray[i] = AssetId.FromId((string)idsArray[i], ScanningUtils.GetSerializableArrayType(field.FieldType));
                }

                field.SetValue(obj, (object)referencesArray);

                                #if !DEBUG_KEEP_IDS
                targetField.SetValue(obj, null);
                                #endif
            }
            else
            {
#if !KEEP_BROKEN_LINKS
                string val = (string)targetField.GetValue(obj);
                field.SetValue(obj, (object)AssetId.FromId(val, field.FieldType));
#endif

                                #if !DEBUG_KEEP_IDS
                targetField.SetValue(obj, null);
                                #endif
            }

            return(true);
        }

        return(false);
    }
Пример #12
0
    private void PackBundles()
    {
        var referencedObjects = new HashSet <UnityEngine.Object>(_lateProcessor.ReferencedObjects);
        var packedObjects     = new HashSet <UnityEngine.Object>();

        var tempPath = Path.Combine(Path.GetTempPath(), "bundles_" + DateTime.UtcNow.Ticks.ToString());

        BuildUtils.PrepareCleanDirectory(tempPath);

        PushAssetDependencies();
        {
            foreach (var bundleInfo in ScanningUtils.ItemsProcessor(_bundles, "Packing asset bundles", p => Path.GetFileName(p.Name), true))
            {
                Console.WriteLine("Building bundle " + bundleInfo.Name + "...");

                string bundlePath = Path.Combine(tempPath, bundleInfo.Name);                //BuildUtils.GetPathHashString(bundleInfo.Name));

                if (bundleInfo.IsScene)
                {
                    var scenePaths = bundleInfo.AssetsPaths.ToArray();

                    PushAssetDependencies();
                    {
                        string buildResult = BuildPipeline.BuildStreamedSceneAssetBundle(scenePaths,
                                                                                         bundlePath,
                                                                                         _params.Target);
                        if (!String.IsNullOrEmpty(buildResult))
                        {
                            throw new UnityException(buildResult);
                        }
                    }
                    PopAssetDependencies();

                    // Find which assets were packed
                    var packedDependencies = new HashSet <UnityEngine.Object>();
                    foreach (var scenePath in scenePaths)
                    {
                        Debug.Log(scenePath);
                        EditorApplication.OpenScene(scenePath);
                        packedDependencies.UnionWith(ScanningUtils.ScanCurrentSceneAssets());
                        packedDependencies.ExceptWith(packedObjects);
                    }

                    bundleInfo.Dependencies = packedDependencies.ToList();

                    var hash = GetHashForBuildAssets(scenePaths.Concat(BuildUtils.GetAssetPathsForObjects(packedDependencies)));


                    int bundleLevel = _bundleLevelDataBase.GetBundleLevel(bundleInfo.Name);
                    bundleInfo.Data = _bundlesDatabaseBuilder.AddSceneBundle(bundleInfo.Name, hash, bundleLevel,
                                                                             scenePaths.Select(p => Path.GetFileNameWithoutExtension(p)).ToArray(),
                                                                             bundlePath);
                }
                else
                {
                    // Add only the main asset + any late referenced asset

                    var mainObjects     = bundleInfo.AssetsPaths.Select(p => AssetDatabase.LoadMainAssetAtPath(p));
                    var representations = bundleInfo.AssetsPaths.SelectMany(p => AssetDatabase.LoadAllAssetRepresentationsAtPath(p));
                    var objects         = mainObjects.Concat(representations.Where(o => referencedObjects.Contains(o))).ToArray();

                    var assetIds = objects.Select(o => AssetId.FromObject(o)).ToArray();


                    foreach (var obj in objects)
                    {
                        string assetPath = AssetDatabase.GetAssetPath(obj);
                        string guid      = AssetDatabase.AssetPathToGUID(assetPath);
                        Console.WriteLine("path: " + assetPath + "   guid:" + guid);
                    }


                    if (bundleInfo.Isolate)
                    {
                        PushAssetDependencies();
                    }
                    {
                        if (!BuildPipeline.BuildAssetBundleExplicitAssetNames(objects, assetIds, bundlePath,
                                                                              BuildAssetBundleOptions.CompleteAssets |
                                                                              BuildAssetBundleOptions.CollectDependencies |
                                                                              BuildAssetBundleOptions.DeterministicAssetBundle,
                                                                              _params.Target))
                        {
                            throw new UnityException("Error building bundle " + bundleInfo.Name);
                        }
                    }
                    if (bundleInfo.Isolate)
                    {
                        PopAssetDependencies();
                    }

                    // Find which assets were packed
                    var packedDependencies = new HashSet <UnityEngine.Object>(EditorUtility.CollectDependencies(objects.ToArray()));
                    packedDependencies.ExceptWith(packedObjects);
                    bundleInfo.Dependencies = packedDependencies.ToList();
                    if (!bundleInfo.Isolate)
                    {
                        packedObjects.UnionWith(packedDependencies);
                    }

                    var hash        = GetHashForBuildAssets(BuildUtils.GetAssetPathsForObjects(packedDependencies));
                    int bundleLevel = _bundleLevelDataBase.GetBundleLevel(bundleInfo.Name);
                    bundleInfo.Data = _bundlesDatabaseBuilder.AddBundle(bundleInfo.Name, hash, bundleLevel, bundlePath, assetIds.ToList());

                    foreach (var obj in objects)
                    {
                        referencedObjects.Remove(obj);
                    }
                }
            }
        }
        PopAssetDependencies();

        // Move to right destination
        Directory.CreateDirectory(_params.BundlesLocation);
        _bundlesPath = Path.Combine(_params.BundlesLocation, _bundlesDatabaseBuilder.Database.Id);
        FileUtil.DeleteFileOrDirectory(_bundlesPath);
        FileUtil.MoveFileOrDirectory(tempPath, _bundlesPath);

        // To create late reference for any late object not added to bundles
        _objectsToLateReference = referencedObjects.ToList();
    }