本章不介绍如何将游戏与 Apple 的 StoreKit API 进行集成。此处假设已经通过原生代码插件与 StoreKit 进行集成。
The Apple StoreKit documentation defines four kinds of products that can be sold via the In App Purchase process:
本章仅介绍第一种情况,主要侧重于可下载内容概念。建议使用 AssetBundles 在 Unity 中实现可下载内容,这里将介绍 AssetBundles 的创建和运行时使用。
为主应用程序和将使用的可下载 AssetBundles 维护单独的项目有时很有用。但是,应该注意,AssetBundle 中的对象引用的所有_脚本_必须存在于主游戏可执行文件中。用于创建 AssetBundle 的项目必须将 iOS 作为选定的构建目标,因为 AssetBundle 文件的内容在 iOS 和其他平台之间不兼容。
AssetBundles are created using editor scripts - a simple example is given below:-
// C#
using UnityEngine;
using UnityEditor;
public class ExportBundle : MonoBehaviour {
[MenuItem ("Assets/Build AssetBundle From Selection - Track dependencies")]
static void DoExport() {
string str = EditorUtility.SaveFilePanel("Save Bundle...", Application.dataPath, Selection.activeObject.name, "assetbundle");
if (str.Length != 0) {
BuildPipeline.BuildAssetBundle(Selection.activeObject, Selection.objects, str, BuildAssetBundleOptions.CompleteAssets, BuildTarget.iPhone);
}
}
}
// JS
@MenuItem ("Assets/Build AssetBundle From Selection - Track dependencies")
static function ExportBundle() {
var str : String = EditorUtility.SaveFilePanel("Save Bundle...", Application.dataPath, Selection.activeObject.name, "assetbundle");
if (str.Length != 0) {
BuildPipeline.BuildAssetBundle(Selection.activeObject, Selection.objects, str, BuildAssetBundleOptions.CompleteAssets, BuildTarget.iPhone);
}
}
You should save this code in a file called ExportBundle and place it inside a folder called Editor (you can just create this if it isn’t already present in the project). The script will add a menu item entitled “Build AssetBundle From Selection - Track dependencies” on the Assets menu in the editor.
The content you want to include in the bundle should be prepared in the form of prefabs. Select a prefab in the Project view and then select Assets > Build AssetBundle From Selection - Track dependencies (ie, the menu item added by the ExportBundle script). This command will bring up a save dialog where you can choose the name and location of your AssetBundle file.
Note: Apple may change the folder locations where you are permitted to write data. Always check the latest Apple documentation to be sure your application will be compliant. The following advice was correct as of early 2013.
AssetBundles can be downloaded using the WWW class and once transfer is complete, the enclosed assets can be accessed. The recommended way to download an AssetBundle is to use LoadFromCacheOrDownload as shown in the following sample:-
// C#
IEnumerator GetAssetBundle() {
WWW download;
string url = "http://somehost/somepath/someassetbundle.assetbundle";
while (!Caching.ready)
yield return null;
download = WWW.LoadFromCacheOrDownload(url, 0);
yield return download;
AssetBundle assetBundle = download.assetBundle;
if (assetBundle != null) {
// Alternatively you can also load an asset by name (assetBundle.Load("my asset name"))
Object go = assetBundle.mainAsset;
if (go != null)
Instantiate(go);
else
Debug.Log("Couldn't load resource");
} else {
Debug.Log("Couldn't load resource");
}
}
// JS
function GetAssetBundle() {
var download : WWW;
var url = "http://somehost/somepath/someassetbundle.assetbundle";
var download = WWW.LoadFromCacheOrDownload (url, 0);
yield download;
var assetBundle = download.assetBundle;
if (assetBundle != null) {
// Alternatively you can also load an asset by name (assetBundle.Load("my asset name"))
var go : Object = assetBundle.mainAsset;
if (go != null)
Instantiate(go);
else
Debug.Log("Couldn't load resource");
} else {
Debug.Log("Couldn't load resource");
}
}
The downloaded asset bundle files are stored in the Library
folder of the iOS application sandbox and have the No Backup flag set on them. This means the OS won’t delete these files accidentally and these files won’t be backed up to iCloud. It is good idea to keep the cache size limit low, to prevent your app from grabbing all the device’s disk space.
If you need to choose exactly where the AssetBundle file is stored, you can use a standard WWW download (ie, just use the constructor instead of LoadFromCacheOrDownload) and then save the downloaded data on disk using the .NET file API. You can save required files to the Application.temporaryCachePath folder (stored in Library/Caches which is regularly “cleaned out” by the OS) or the Application.persistentDataPath folder (stored in Documents which is not cleaned out by the OS). You should set the No Backup flag on these files with iOS.Device.SetNoBackupFlag to prevent them being backed up to iCloud.
注意:如果未设置 No Backup 标志,则在将应用程序提交到 App Store 时可能会遭到拒绝。
可以通过使用 file:///pathtoyourapplication/Library/savedassetbundle.assetbundle
形式的 URL 创建 WWW 对象来访问已保存的文件:
// C#
string cachedAssetBundle = Application.temporaryCachePath + "/savedassetbundle.assetbundle";
System.IO.FileStream cache = new System.IO.FileStream(cachedAssetBundle, System.IO.FileMode.Create);
cache.Write(download.bytes, 0, download.bytes.Length);
cache.Close();
iOS.Device.SetNoBackupFlag(cachedAssetBundle);
Debug.Log("Cache saved: " + cachedAssetBundle);
// JS
private var cachedAssetBundle : String = Application.temporaryCachePath + "/savedassetbundle.assetbundle";
var cache = new System.IO.FileStream(cachedAssetBundle, System.IO.FileMode.Create);
cache.Write(download.bytes, 0, download.bytes.Length);
cache.Close();
iOS.Device.SetNoBackupFlag(cachedAssetBundle);
Debug.Log("Cache saved: " + cachedAssetBundle);
Note: You can test the reading of stored files in the Documents folder if you enable file sharing (setting UIFileSharingEnabled
to true in your Info.plist
allows you to access the Documents folder from iTunes). Note that the contents of the Documents folder are cached to iCloud, so you should not use this location to store AssetBundles in the final build to be shipped. See File System Basics in the Apple iOS documentation for further details.