Beispiel #1
0
        void OnEnable()
        {
            encryptionKeysEnabled     = UMAABMSettings.GetEncryptionEnabled();
            currentEncryptionPassword = newEncryptionPassword = UMAABMSettings.GetEncryptionPassword();
            currentEncryptionSuffix   = newEncryptionSuffix = UMAABMSettings.GetEncryptionSuffix();
            if (currentEncryptionSuffix == "")
            {
                currentEncryptionSuffix = newEncryptionSuffix = DEFAULT_ENCRYPTION_SUFFIX;
            }
            currentEncodeNamesSetting = newEncodeNamesSetting = UMAABMSettings.GetEncodeNames();

            //localAssetBundleServer status
            _enableLocalAssetBundleServer = EditorPrefs.GetBool(Application.dataPath + "LocalAssetBundleServerEnabled");
            _port = EditorPrefs.GetInt(Application.dataPath + "LocalAssetBundleServerPort", 7888);
            //When the window is opened we still need to tell the user if the port is available so
            if (!_enableLocalAssetBundleServer)
            {
                UpdateServer(true);
                ServerStop();
                if (serverException)
                {
                    portError = true;
                }
            }
            else
            {
                UpdateServer();
            }
        }
Beispiel #2
0
 void OnFocus()
 {
     encryptionKeysEnabled     = UMAABMSettings.GetEncryptionEnabled();
     currentEncryptionPassword = newEncryptionPassword = UMAABMSettings.GetEncryptionPassword();
     currentEncryptionSuffix   = newEncryptionSuffix = UMAABMSettings.GetEncryptionSuffix();
     if (currentEncryptionSuffix == "")
     {
         currentEncryptionSuffix = newEncryptionSuffix = DEFAULT_ENCRYPTION_SUFFIX;
     }
     currentEncodeNamesSetting = newEncodeNamesSetting = UMAABMSettings.GetEncodeNames();
 }
Beispiel #3
0
        //we dont want this editor only
#if UNITY_EDITOR
        //used in the editor to encrypt assetbundles
        public static byte[] Encrypt(byte[] value, ref byte[] IVout)
        {
            var pass = UMAABMSettings.GetEncryptionPassword();

            if (String.IsNullOrEmpty(pass))
            {
                throw new Exception("[EncryptUtil] could not perform any encryption because not encryption password was set in UMAAssetBundleManager.");
            }
            IVout = GenerateIV(pass);
            var thisKey = GenerateKey(pass);
            SymmetricAlgorithm algorithm = new AesManaged();
            ICryptoTransform   transform = algorithm.CreateEncryptor(thisKey, IVout);

            return(CryptoTransform(transform, value));
        }
Beispiel #4
0
        void OnGUI()
        {
            scrollPos = EditorGUILayout.BeginScrollView(scrollPos, false, true);
            EditorGUILayout.BeginVertical(GUILayout.Width(EditorGUIUtility.currentViewWidth - 20f));
            EditorGUILayout.Space();
            GUILayout.Label("UMA AssetBundle Manager", EditorStyles.boldLabel);

            BeginVerticalPadded(5, new Color(0.75f, 0.875f, 1f));

            GUILayout.Label("AssetBundle Options", EditorStyles.boldLabel);

            //Asset Bundle Encryption
            //defined here so we can modify the message if encryption settings change
            string      buildBundlesMsg     = "";
            MessageType buildBundlesMsgType = MessageType.Info;

            EditorGUI.BeginChangeCheck();
            encryptionKeysEnabled = EditorGUILayout.ToggleLeft("Enable AssetBundle Encryption", encryptionKeysEnabled);
            if (EditorGUI.EndChangeCheck())
            {
                //If encryption was turned ON generate the encryption password if necessary
                if (encryptionKeysEnabled)
                {
                    if (currentEncryptionPassword == "")
                    {
                        if (UMAABMSettings.GetEncryptionPassword() != "")
                        {
                            currentEncryptionPassword = UMAABMSettings.GetEncryptionPassword();
                        }
                        else
                        {
                            currentEncryptionPassword = EncryptionUtil.GenerateRandomPW();
                        }
                    }
                    UMAABMSettings.SetEncryptionPassword(currentEncryptionPassword);
                    buildBundlesMsg     = "You have turned on encryption and need to Rebuild your bundles to encrypt them.";
                    buildBundlesMsgType = MessageType.Warning;
                }
                else
                {
                    UMAABMSettings.DisableEncryption();
                    currentEncryptionPassword = "";
                }
            }
            if (encryptionKeysEnabled)
            {
                BeginVerticalIndented(10, new Color(0.75f, 0.875f, 1f));
                //tip
                EditorGUILayout.HelpBox("Make sure you turn on 'Use Encrypted Bundles' in the 'DynamicAssetLoader' components in your scenes.", MessageType.Info);
                //Encryption key
                //If we can work out a way for people to download a key we can use this tip and the 'EncryptionKeyURL' field
                //string encryptionKeyToolTip = "This key is used to generate the required encryption keys used when encrypting your bundles. If you change this key you will need to rebuild your bundles otherwise they wont decrypt. If you use the 'Encryption Key URL' field below you MUST ensure this field is set to the same key the url will return.";
                string encryptionKeyToolTip = "This key is used to generate the required encryption keys used when encrypting your bundles. If you change this key you will need to rebuild your bundles otherwise they wont decrypt.";
                EditorGUILayout.LabelField(new GUIContent("Bundle Encryption Password", encryptionKeyToolTip));
                EditorGUILayout.BeginHorizontal();
                if (!manualEditEncryptionKey)
                {
                    if (GUILayout.Button(new GUIContent("Edit", encryptionKeyToolTip)))
                    {
                        manualEditEncryptionKey = true;
                    }
                    EditorGUI.BeginDisabledGroup(!manualEditEncryptionKey);
                    EditorGUILayout.TextField("", UMAABMSettings.GetEncryptionPassword());                    //THis bloody field WILL NOT update when you click edit, then canel, the value stays
                    EditorGUI.EndDisabledGroup();
                }
                else
                {
                    EditorGUI.BeginChangeCheck();
                    newEncryptionPassword = EditorGUILayout.TextArea(newEncryptionPassword);
                    if (EditorGUI.EndChangeCheck())
                    {
                        encryptionSaveButEnabled = EncryptionUtil.PasswordValid(newEncryptionPassword);
                    }
                    if (encryptionSaveButEnabled)
                    {
                        if (GUILayout.Button(new GUIContent("Save"), GUILayout.MaxWidth(60)))
                        {
                            currentEncryptionPassword = newEncryptionPassword;
                            UMAABMSettings.SetEncryptionPassword(newEncryptionPassword);
                            EditorGUIUtility.keyboardControl = 0;
                            manualEditEncryptionKey          = false;
                        }
                    }
                    else
                    {
                        GUI.enabled = false;
                        if (GUILayout.Button(new GUIContent("Save", "Your Encryptiom Password should be at least 16 characters long"), GUILayout.MaxWidth(60)))
                        {
                            //Do nothing
                        }
                        GUI.enabled = true;
                    }
                    if (GUILayout.Button(new GUIContent("Cancel", "Reset to previous value: " + currentEncryptionPassword), GUILayout.MaxWidth(60)))
                    {
                        manualEditEncryptionKey          = false;
                        newEncryptionPassword            = currentEncryptionPassword = UMAABMSettings.GetEncryptionPassword();
                        encryptionSaveButEnabled         = false;
                        EditorGUIUtility.keyboardControl = 0;
                    }
                }

                EditorGUILayout.EndHorizontal();
                //EncryptionKey URL
                //not sure how this would work- the delivered key would itself need to be encrypted probably
                //Encrypted bundle suffix
                string encryptionSuffixToolTip = "This suffix is appled to the end of your encrypted bundle names when they are built. Must be lower case and alphaNumeric. Cannot be empty. Defaults to " + DEFAULT_ENCRYPTION_SUFFIX;
                EditorGUILayout.LabelField(new GUIContent("Encrypted Bundle Suffix", encryptionSuffixToolTip));
                EditorGUILayout.BeginHorizontal();
                if (!manualEditEncryptionSuffix)
                {
                    if (GUILayout.Button(new GUIContent("Edit", encryptionSuffixToolTip)))
                    {
                        manualEditEncryptionSuffix = true;
                    }
                    EditorGUI.BeginDisabledGroup(!manualEditEncryptionSuffix);
                    EditorGUILayout.TextField(new GUIContent("", encryptionSuffixToolTip), currentEncryptionSuffix);
                    EditorGUI.EndDisabledGroup();
                }
                else
                {
                    newEncryptionSuffix = EditorGUILayout.TextArea(newEncryptionSuffix);
                    if (GUILayout.Button(new GUIContent("Save")))
                    {
                        if (newEncryptionSuffix != "")
                        {
                            Regex rgx          = new Regex("[^a-zA-Z0-9 -]");
                            var   suffixToSend = rgx.Replace(newEncryptionSuffix, "");
                            currentEncryptionSuffix = suffixToSend;
                            UMAABMSettings.SetEncryptionSuffix(suffixToSend.ToLower());
                            EditorGUIUtility.keyboardControl = 0;
                            manualEditEncryptionSuffix       = false;
                        }
                    }
                }
                EditorGUILayout.EndHorizontal();

                //Encode Bundle Names
                string encodeBundleNamesTooltip = "If true encrypted bundle names will be base64 encoded";
                EditorGUI.BeginChangeCheck();
                newEncodeNamesSetting = EditorGUILayout.ToggleLeft(new GUIContent("Encode Bundle Names", encodeBundleNamesTooltip), currentEncodeNamesSetting);
                if (EditorGUI.EndChangeCheck())
                {
                    currentEncodeNamesSetting = newEncodeNamesSetting;
                    UMAABMSettings.SetEncodeNames(newEncodeNamesSetting);
                }

                EndVerticalIndented();
            }

            //Asset Bundle Building
            EditorGUILayout.Space();
            string buttonBuildAssetBundlesText = "Build AssetBundles";
            //Now defined above the encryption
            //string buildBundlesText = "Click the button below to build your bundles if you have not done so already.";
            string fullPathToBundles         = Path.Combine(Directory.GetParent(Application.dataPath).FullName, Utility.AssetBundlesOutputPath);
            string fullPathToPlatformBundles = Path.Combine(fullPathToBundles, Utility.GetPlatformName());

            //if we have not built any asset bundles there wont be anything in the cache to clear
            bool showClearCache = false;

            if (Directory.Exists(fullPathToPlatformBundles))
            {
                buttonBuildAssetBundlesText = "Rebuild AssetBundles";
                buildBundlesMsg             = buildBundlesMsg == "" ? "Rebuild your assetBundles to reflect your latest changes" : buildBundlesMsg;
                showClearCache = true;
            }
            else
            {
                buildBundlesMsg     = "You have not built your asset bundles for " + EditorUserBuildSettings.activeBuildTarget.ToString() + " yet. Click this button to build them.";
                buildBundlesMsgType = MessageType.Warning;
                showClearCache      = false;
            }
            EditorGUILayout.HelpBox(buildBundlesMsg, buildBundlesMsgType);
            if (GUILayout.Button(buttonBuildAssetBundlesText))
            {
                try
                {
                    BuildScript.BuildAssetBundles();
                    _statusMessage = "Asset Bundles Built";
                }
                catch (Exception e)
                {
                    _statusMessage = string.Format("Building Asset Bundle Exception: {0}\nStack Trace\n{1}", e.ToString(), e.StackTrace);
                    Debug.LogException(e);
                }
            }

            if (!BuildScript.CanRunLocally(EditorUserBuildSettings.activeBuildTarget))
            {
                EditorGUILayout.HelpBox("Builds for " + EditorUserBuildSettings.activeBuildTarget.ToString() + " cannot access this local server, but you can still use it in the editor.", MessageType.Warning);
            }
            EndVerticalPadded(5);
            EditorGUILayout.Space();

            //Local AssetBundleServer
            BeginVerticalPadded(5, new Color(0.75f, 0.875f, 1f));
            GUILayout.Label("AssetBundle Testing Server", EditorStyles.boldLabel);
            EditorGUILayout.HelpBox("Once you have built your bundles this local Testing Server can be enabled and it will load those AssetBundles rather than the files inside the project.", MessageType.Info);

            bool updateURL = false;

            EnableLocalAssetBundleServer = EditorGUILayout.Toggle("Start Server", EnableLocalAssetBundleServer);

            //If the server is off we need to show the user a message telling them that they will have to have uploaded their bundles to an external server
            //and that they need to set the address of that server in DynamicAssetLoader
            int newPort = Port;

            EditorGUI.BeginChangeCheck();
            newPort = EditorGUILayout.IntField("Port", Port);
            if (EditorGUI.EndChangeCheck())
            {
                if (newPort != Port)
                {
                    if (_activeHost != null && _activeHost != "")
                    {
                        ActiveHost = _activeHost.Replace(":" + Port.ToString(), ":" + newPort.ToString());
                    }
                    Port = newPort;
                    UpdateHosts();
                    //we need to start the server to see if it works with this port- regardless of whether it is turned on or not.
                    if (!EnableLocalAssetBundleServer)
                    {
                        UpdateServer(true);
                    }
                    else
                    {
                        UpdateServer();
                    }
                    if (serverException == false)
                    {
                        //We can use the set IP with this port so update it
                        if (EnableLocalAssetBundleServer)
                        {
                            SimpleWebServer.ServerURL = ActiveHost;
                        }
                    }
                    else
                    {
                        //We CANT use the set IP with this port so set the saved URL to "" and tell the user the Port is in use elsewhere
                        SimpleWebServer.ServerURL    = "";
                        EnableLocalAssetBundleServer = false;
                        portError = true;
                    }
                }
            }
            if (!EnableLocalAssetBundleServer)
            {
                if (portError)
                {
                    EditorGUILayout.HelpBox("There are no hosts available for that port. Its probably in use by another application. Try another.", MessageType.Warning);
                }
                else
                {
                    EditorGUILayout.HelpBox("When the local server is not running the game will play in Simulation Mode OR if you have set the 'RemoteServerURL' for each DynamicAssetLoader, bundles will be downloaded from that location.", MessageType.Warning);
                    if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.WebGL)
                    {
                        EditorGUILayout.HelpBox("WARNING: AssetBundles in WebGL builds that you run locally WILL NOT WORK unless the local server is turned on, and you build using the button below!", MessageType.Warning);
                    }
                }
            }

            EditorGUILayout.Space();

            if (_hosts != null && _hosts.Length > 0 && EnableLocalAssetBundleServer)
            {
                if (_activeHost == null || _activeHost == "")
                {
                    ActiveHost = _hosts[0];
                }
                int      activeHostInt = 0;
                string[] hostsStrings  = new string[_hosts.Length];
                for (int i = 0; i < _hosts.Length; i++)
                {
                    hostsStrings[i] = _hosts[i].Replace("http://", "").TrimEnd(new char[] { '/' });
                    if (_hosts[i] == _activeHost)
                    {
                        activeHostInt = i;
                    }
                }
                EditorGUI.BeginChangeCheck();
                int newActiveHostInt = EditorGUILayout.Popup("Host Address:  http://", activeHostInt, hostsStrings);
                if (EditorGUI.EndChangeCheck())
                {
                    if (newActiveHostInt != activeHostInt)
                    {
                        ActiveHost = _hosts[newActiveHostInt];
                        updateURL  = true;
                    }
                }
            }
            EditorGUILayout.Space();

            if (showClearCache)            //no point in showing a button for bundles that dont exist - or is there? The user might be using a remote url to download assetbundles without the localserver?
            {
                EditorGUILayout.HelpBox("You can clear the cache to force asset bundles to be redownloaded.", MessageType.Info);

                if (GUILayout.Button("Clean the Cache"))
                {
                    _statusMessage = Caching.CleanCache() ? "Cache Cleared." : "Error clearing cache.";
                }
                EditorGUILayout.Space();
            }

            EditorGUILayout.Space();
            GUILayout.Label("Server Status");
            if (_statusMessage != null)
            {
                EditorGUILayout.HelpBox(_statusMessage, MessageType.None);
            }

            if (SimpleWebServer.Instance != null)
            {
                //GUILayout.Label("Server Request Log");
                serverRequestLogOpen = EditorGUILayout.Foldout(serverRequestLogOpen, "Server Request Log");
                if (serverRequestLogOpen)
                {
                    EditorGUILayout.HelpBox(SimpleWebServer.Instance.GetLog(), MessageType.Info);
                }
            }
            if (updateURL)
            {
                SimpleWebServer.ServerURL = ActiveHost;
            }

            EndVerticalPadded(5);
            EditorGUILayout.Space();

            //Testing Build
            BeginVerticalPadded(5, new Color(0.75f, 0.875f, 1f));
            GUILayout.Label("Testing Build", EditorStyles.boldLabel);
            //if the bundles are build and the server is turned on then the user can use this option otherwise there is no point
            //But we will show them that this option is available even if this is not the case
            if (!showClearCache || !EnableLocalAssetBundleServer)
            {
                EditorGUI.BeginDisabledGroup(true);
            }
            EditorGUILayout.HelpBox("Make a testing Build that uses the Local Server using the button below.", MessageType.Info);
            developmentBuild = EditorGUILayout.Toggle("Development Build", developmentBuild);
            if (GUILayout.Button("Build and Run!"))
            {
                BuildScript.BuildAndRunPlayer(developmentBuild);
            }
            if (!showClearCache || !EnableLocalAssetBundleServer)            //
            {
                EditorGUI.EndDisabledGroup();
            }
            EditorGUILayout.Space();
            EndVerticalPadded(5);

            EditorGUILayout.Space();
            //END SCROLL VIEW
            EditorGUILayout.EndVertical();
            EditorGUILayout.EndScrollView();
        }
Beispiel #5
0
        public static void BuildAssetBundles()
        {
            var thisIndexAssetPath      = "";
            var thisEncryptionAssetPath = "";

            try {
                // Choose the output path according to the build target.
                string outputPath = CreateAssetBundleDirectory();

                var options = BuildAssetBundleOptions.None;

                bool shouldCheckODR = EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS;
#if UNITY_TVOS
                shouldCheckODR |= EditorUserBuildSettings.activeBuildTarget == BuildTarget.tvOS;
#endif
                if (shouldCheckODR)
                {
#if ENABLE_IOS_ON_DEMAND_RESOURCES
                    if (PlayerSettings.iOS.useOnDemandResources)
                    {
                        options |= BuildAssetBundleOptions.UncompressedAssetBundle;
                    }
                    else if (UMAABMSettings.GetEncryptionPassword() != "")
                    {
                        options |= BuildAssetBundleOptions.ChunkBasedCompression;
                    }
#endif
#if ENABLE_IOS_APP_SLICING
                    options |= BuildAssetBundleOptions.UncompressedAssetBundle;
#endif
                }
                if (UMAABMSettings.GetEncryptionPassword() != "")
                {
                    if (!shouldCheckODR)
                    {
                        options |= BuildAssetBundleOptions.ChunkBasedCompression;
                    }
                    options |= BuildAssetBundleOptions.ForceRebuildAssetBundle;
                }

                //AssetBundleIndex
                AssetBundleIndex thisIndex = ScriptableObject.CreateInstance <AssetBundleIndex>();

                string[] assetBundleNamesArray = AssetDatabase.GetAllAssetBundleNames();

                //Generate a buildmap as we go
                AssetBundleBuild[] buildMap = new AssetBundleBuild[assetBundleNamesArray.Length + 1];                //+1 for the index bundle
                for (int i = 0; i < assetBundleNamesArray.Length; i++)
                {
                    string bundleName = assetBundleNamesArray[i];

                    string[] assetBundleAssetsArray = AssetDatabase.GetAssetPathsFromAssetBundle(bundleName);
                    //If there are no assets added to this bundle continue because it wont be in the resulting assetBundleManifest
                    if (assetBundleAssetsArray == null)
                    {
                        continue;
                    }

                    thisIndex.bundlesIndex.Add(new AssetBundleIndex.AssetBundleIndexList(bundleName));

                    if (bundleName.IndexOf('.') > -1)
                    {
                        buildMap[i].assetBundleName    = bundleName.Split('.')[0];
                        buildMap[i].assetBundleVariant = bundleName.Split('.')[1];
                    }
                    else
                    {
                        buildMap[i].assetBundleName = bundleName;
                    }

                    buildMap[i].assetNames = assetBundleAssetsArray;

                    foreach (string path in assetBundleAssetsArray)
                    {
                        var sysPath  = Path.Combine(Application.dataPath, path);
                        var filename = Path.GetFileNameWithoutExtension(sysPath);
                        var tempObj  = AssetDatabase.LoadMainAssetAtPath(path);
                        thisIndex.bundlesIndex[i].AddItem(filename, tempObj);
                    }
                }

                thisIndexAssetPath = "Assets/" + Utility.GetPlatformName() + "Index.asset";
                thisIndex.name     = "AssetBundleIndex";
                AssetDatabase.CreateAsset(thisIndex, thisIndexAssetPath);
                AssetImporter thisIndexAsset = AssetImporter.GetAtPath(thisIndexAssetPath);
                thisIndexAsset.assetBundleName = Utility.GetPlatformName() + "index";
                buildMap[assetBundleNamesArray.Length].assetBundleName = Utility.GetPlatformName() + "index";
                buildMap[assetBundleNamesArray.Length].assetNames      = new string[1] {
                    "Assets/" + Utility.GetPlatformName() + "Index.asset"
                };

                //Build the current state so we can get the AssetBundleManifest object and add its values to OUR index
                var assetBundleManifest = BuildPipeline.BuildAssetBundles(outputPath, buildMap, options, EditorUserBuildSettings.activeBuildTarget);
                if (assetBundleManifest == null)
                {
                    throw new System.Exception("Your assetBundles did not build properly.");
                }
                //reload the saved index (TODO may not be necessary)
                thisIndex = AssetDatabase.LoadAssetAtPath <AssetBundleIndex>("Assets/" + Utility.GetPlatformName() + "Index.asset");
                //Get any bundles with variants
                string[] bundlesWithVariant = assetBundleManifest.GetAllAssetBundlesWithVariant();
                thisIndex.bundlesWithVariant = bundlesWithVariant;
                //then loop over each bundle in the bundle names and get the bundle specific data
                for (int i = 0; i < assetBundleNamesArray.Length; i++)
                {
                    string[] assetBundleAssetsArray = AssetDatabase.GetAssetPathsFromAssetBundle(assetBundleNamesArray[i]);
                    //If there are no assets added to this bundle continue because it wont be in the resulting assetBundleManifest
                    if (assetBundleAssetsArray == null)
                    {
                        continue;
                    }
                    string   assetBundleHash    = assetBundleManifest.GetAssetBundleHash(assetBundleNamesArray[i]).ToString();
                    string[] allDependencies    = assetBundleManifest.GetAllDependencies(assetBundleNamesArray[i]);
                    string[] directDependencies = assetBundleManifest.GetDirectDependencies(assetBundleNamesArray[i]);
                    thisIndex.bundlesIndex[i].assetBundleHash    = assetBundleHash;
                    thisIndex.bundlesIndex[i].allDependencies    = allDependencies;
                    thisIndex.bundlesIndex[i].directDependencies = directDependencies;
                    //Add suffixed names to the index if enabled and we are using encrption
                    //we cant append the suffix to the index file because when we are loading we dont know the set suffix or suffixed names until we have the index
                    //it also cant be the same as the unencrypted name because it needs a different memory address, so its going to have to be name + "encrypted"
                    if (UMAABMSettings.GetEncryptionEnabled())
                    {
                        var encryptedBundleName = assetBundleNamesArray[i] == Utility.GetPlatformName() + "index" ? assetBundleNamesArray[i] + "encrypted" : assetBundleNamesArray[i] + UMAABMSettings.GetEncryptionSuffix();
                        if (UMAABMSettings.GetEncodeNames() && assetBundleNamesArray[i] != Utility.GetPlatformName() + "index")
                        {
                            encryptedBundleName = EncryptionUtil.EncodeFileName(encryptedBundleName);
                        }
                        thisIndex.bundlesIndex[i].encryptedName = encryptedBundleName;
                    }
                }
                //TODO is this it for encrypted bundles?
                var relativeAssetBundlesOutputPathForPlatform = Path.Combine(Utility.AssetBundlesOutputPath, Utility.GetPlatformName());
                //Update and Save the index asset and build again. This will store the updated asset in the windowsindex asset bundle
                EditorUtility.SetDirty(thisIndex);
                AssetDatabase.SaveAssets();
                //Build the Index AssetBundle
                var indexBuildMap = new AssetBundleBuild[1];
                indexBuildMap[0] = buildMap[assetBundleNamesArray.Length];
                BuildPipeline.BuildAssetBundles(outputPath, indexBuildMap, options, EditorUserBuildSettings.activeBuildTarget);

                //Save a json version of the data- this can be used for uploading to a server to update a database or something
                string thisIndexJson     = JsonUtility.ToJson(thisIndex);
                var    thisIndexJsonPath = Path.Combine(relativeAssetBundlesOutputPathForPlatform, Utility.GetPlatformName().ToLower()) + "index.json";
                File.WriteAllText(thisIndexJsonPath, thisIndexJson);
                //Build Encrypted Bundles
                if (UMAABMSettings.GetEncryptionEnabled())
                {
                    var encryptedBuildMap = new AssetBundleBuild[1];
                    var EncryptionAsset   = ScriptableObject.CreateInstance <UMAEncryptedBundle>();
                    EncryptionAsset.name    = "EncryptedData";
                    thisEncryptionAssetPath = "Assets/EncryptedData.asset";
                    AssetDatabase.CreateAsset(EncryptionAsset, thisEncryptionAssetPath);
                    //var encryptedOutputPath = Path.Combine(outputPath, "Encrypted");
                    var encryptedOutputPath = Path.Combine(Utility.AssetBundlesOutputPath, Path.Combine("Encrypted", Utility.GetPlatformName()));
                    if (!Directory.Exists(encryptedOutputPath))
                    {
                        Directory.CreateDirectory(encryptedOutputPath);
                    }
                    for (int bmi = 0; bmi < buildMap.Length; bmi++)                    //-1 to not include the index bundle (or maybe we do encrypt the index bundle?)
                    {
                        var thisEncryptionAsset = AssetDatabase.LoadAssetAtPath <UMAEncryptedBundle>(thisEncryptionAssetPath);
                        //get the data from the unencrypted bundle and encrypt it into the EncryptedData asset
                        thisEncryptionAsset.GenerateData(buildMap[bmi].assetBundleName, Path.Combine(relativeAssetBundlesOutputPathForPlatform, buildMap[bmi].assetBundleName));
                        EditorUtility.SetDirty(thisEncryptionAsset);
                        AssetDatabase.SaveAssets();
                        //Sort out the name of this encrypted bundle
                        var encryptedBundleName = "";
                        if (buildMap[bmi].assetBundleName != Utility.GetPlatformName() + "index")
                        {
                            encryptedBundleName = buildMap[bmi].assetBundleName + UMAABMSettings.GetEncryptionSuffix();
                            if (UMAABMSettings.GetEncodeNames() && buildMap[bmi].assetBundleName != Utility.GetPlatformName() + "index")
                            {
                                encryptedBundleName = EncryptionUtil.EncodeFileName(encryptedBundleName);
                            }
                        }
                        else
                        {
                            encryptedBundleName = buildMap[bmi].assetBundleName + "encrypted";
                        }
                        //set the Build map value
                        encryptedBuildMap[0].assetBundleName = encryptedBundleName;
                        encryptedBuildMap[0].assetNames      = new string[1] {
                            "Assets/EncryptedData.asset"
                        };
                        //and build the bundle
                        BuildPipeline.BuildAssetBundles(encryptedOutputPath, encryptedBuildMap, BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget);
                    }
                    //save a json index in there too
                    var thisIndexJsonEncPath = Path.Combine(encryptedOutputPath, Utility.GetPlatformName().ToLower()) + "indexencrypted.json";
                    File.WriteAllText(thisIndexJsonEncPath, thisIndexJson);
                    AssetDatabase.DeleteAsset(thisEncryptionAssetPath);
                }
                //Now we can remove the temp Index item from the assetDatabase
                AssetDatabase.DeleteAsset(thisIndexAssetPath);
            }
            catch (System.Exception e)
            {
                if (thisIndexAssetPath != "")
                {
                    AssetDatabase.DeleteAsset(thisIndexAssetPath);
                }
                if (thisEncryptionAssetPath != "")
                {
                    AssetDatabase.DeleteAsset(thisEncryptionAssetPath);
                }
                Debug.LogError("Your AssetBundles did not build properly. Error Message: " + e.Message + " Error Exception: " + e.InnerException + " Error StackTrace: " + e.StackTrace);
            }
        }