Unity动态加载远程资源

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改为 *


<?xml version="1.0"?>
<cross-domain-policy>
   <allow-access-from domain="*.yoursite.com" />
</cross-domain-policy>

阅读更多

没有更多推荐了,返回首页