unity动态加载远程资源的相关话题网上有一些,但都语焉不详,经过本人的摸索,终于找到门道,记录下来备忘,也分享给同好。
unity动态加载远程资源需要用到unity的一个runtime class,叫做WWW,可以在帮助里面的Scripting中找到。
WWW类有两个重要的方法用来加载远程站点上的资源。
一个是WWW,即直接访问远程文件。例如:
function Start(){
var www : WWW = new WWW("http://yoursite.com/test.jpg"); //开始读取资源,资源你自己改为自己的
yield www;//等待加载完成(不会阻塞其它程序运行)
guiTexture.texture = www.texture; //将加载的资源直接使用到对象上
}
见一个GUITexture对象,讲上面的代码复制到一个js脚本中,把这个脚本拖到对象上。点运行,即能看到效果。
还能用这种方法加载文本、二进制文件等。这时候要用到的是WWW的text和bytes变量,WWW还有一些其他的成员变量,可以参见C:\Program Files\Unity\Editor\Data\Documentation\Documentation\ScriptReference\WWW.html (假定你的unity安装在默认目录下,mac下类推。当然可以直接在unity的菜单中选help->scripting reference)
二是WWW.LoadFromCacheOrDownload
这是个静态函数,参数为一个url字符串和一个整数的版本号,功能是从url指定的位置下载(如果没有缓存到本地),如果第二次访问相同版本的该资源,则会从本地磁盘的缓存中加载(这对webgame来说是个好消息)。
下面是用法示例:
function Start(){
var www : WWW = WWW.LoadFromCacheOrDownload("http://yoursite.com/test.unity3d", 1); //加载
yield www; //等待加载完成
if(www.error != null){//如果出错,则在控制台打印错误
print(www.error);
return;
}
var myAssetBundle = www.assetBundle; //得到AssetBundle
if(myAssetBundle.Contains("New prefab")){//确认AssetBundle中有指定预置对象
print("ok!");
var ob = myAssetBundle.Load("New prefab");//加载指定预置对象
Instantiate(ob, transform.position, transform.rotation);//实例化该预置对象
}
else
print("failed.");
}
向项目中添加一个空对象,然后添加一个js脚本,把上面的内容复制到脚本中,再讲脚本拖到对象上,运行即能看到效果。
接下来问题来了,test.unity3d这个文件哪里来的呢?或者说我们怎么生成我们自己的.unity3d文件呢?这个问题折腾了我很久,现在总算搞明白了一点。
要生成.unity3d文件,需要在项目目录的Asset目录下添加一个Editor目录,然后在这个目录下建立一个js脚本,名字随便取,内容如下:
@MenuItem("Assets/Build AssetBundle From Selection - Track dependencies")
static function ExportResource () {
// Bring up save panel
var path = EditorUtility.SaveFilePanel ("Save Resource", "", "test", "unity3d");
if (path.Length != 0)
{
// Build the resource file from the active selection.
var selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets);
Selection.objects = selection;
}
}
@MenuItem("Assets/Build AssetBundle From Selection - No dependency tracking")
static function ExportResourceNoTrack () {
// Bring up save panel
var path = EditorUtility.SaveFilePanel ("Save Resource", "", "test", "unity3d");
if (path.Length != 0)
{
// Build the resource file from the active selection.
BuildPipeline.BuildAssetBundle(Selection.activeObject, Selection.objects, path);
}
}
保存后如果unity不报错,则在你选中project视图中的目录或者对象时,点右键,菜单中会多出两个选项
Build AssetBundle From Selection - Track dependencies
Build AssetBundle From Selection - No dependency tracking
当然unity主菜单的Assets中也会多出这两项,这就是上面Editor目录下那个脚本的效果。
选中你要的对象或者目录,点右键,选Build AssetBundle From Selection - Track dependencies
在弹出的文件对话框中设定文件名即可。
注意,上面提到了预置对象。这个方法能将预置对象导出到assetbundle中,这是我们最需要的功能。
但是有一个问题,就是assetbundle中不会保存脚本,要想让预置对象(Prefab)的功能完整,则引用这个预置对象的项目中必须有当初做预置对象(Prefab)时用到的脚本!简单点,把原来的脚本文件复制到现在项目中,呵呵……
另外还有一个问题,用LoadFromCacheOrDownload加载站点资源需要站点上有crossdomain.xml,这个类似flash的做法。
crossdomain.xml随便在网上找个就好了,找不到的话自己在站点上(我用xampp,存放在hotdocs目录下)自己建一个,内容如下,注意把其中的yoursite改成你的站点名,测试可以直接用ip地址。如果偷懒就直接把 *.yoursite.com改为 *