unity3d 打包包名错误_unity3d打不开unity3d文件 - CSDN
  • Unity打安卓包 Android 所有错误解决方案大全(几乎囊括所有打包错误 ) Unity打包出错解决方案,本文提供全流程,中文翻译。 解决修复所有Unity报错教程 助力快速解决 Unity 打包中常见错误 1.未设置修改包 / ...

    Chinar blog www.chinar.xin

    Unity打包出错解决方案


    本文提供全流程,中文翻译

    Chinar 的初衷是将一种简单的生活方式带给世人

    使有限时间 具备无限可能

    Chinar —— 心分享、心创新!

    助力快速解决 Unity 打包中常见错误

    给新手节省宝贵的时间,避免采坑!


    1

    Name not set —— 未设置修改包名 / 公司名 / 项目名


    错误发生场景

    由于未设置修改 包名 / 公司名 / 项目名

    导致报错,最为简单

    具体报错信息:
    UnityException: Package Name has not been set up correctly
    Please set the Package Name in the Player Settings. The value must follow the convention 'com.YourCompanyName.YourProductName' and can contain alphanumeric characters and underscore.
    Each segment must not start with a numeric character or underscore.
    
    Error building Player: 2 errors
    
    UnityEditor.BuildPlayerWindow+BuildMethodException: 3 errors
      at UnityEditor.BuildPlayerWindow+DefaultBuildMethods.BuildPlayer (BuildPlayerOptions options) [0x0020e] in
    
    Build completed with a result of 'Failed'
    UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
    

    这里写图片描述
    这里写图片描述

    解决方案:

    更改 公司名 / 包名 / 项目名

    举个例子
    这里写图片描述------这里写图片描述


    2

    SDK Tools —— Unity版本低,需要安卓工具版本也应低些


    错误发生场景

    一般高版本的 2017.2-2017.3 都不会报此错误

    常见于 5.X 版本


    具体报错信息:
    Error:Invalid command android<br>UnityEditor.HostView:OnGUI()
    
    CommandInvokationFailure: Unable to list target platforms. 
    Please make sure the android sdk path is correct. See the Console for more details. 
    
    Error building Player: CommandInvokationFailure: 
    Unable to list target platforms. 
    Please make sure the android sdk path is correct. See the Console for more details. 
    

    这里写图片描述
    这里写图片描述

    解决方案:

    更换安卓工具包,至较低的版本


    1. 点击下载 —— 安卓工具包 24 版本

    2. 解压后替换 安卓 SDK 中的 Tools 文件夹

    3. 然后重新打包,即可成功!!!

    反之:如果 Unity 版本高,同样需要换成高版本的 安卓 SDK Tools

    举个例子
    这里写图片描述


    3

    AR Vuforia Android TV —— Vuforia AR 发开中,打包安卓报错


    错误发生场景

    由于 Vuforia 不支持 Android TV ,导致报错

    具体报错信息:
    Vuforia does not support Android TV. Please disable the Android TV compatibility in the Player Settings.
    
    UnityEngine.Debug:LogError(Object)
    BuildObserver:OnPreprocessBuild(BuildTarget, String)
    UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
    
    
    Error building Player: Vuforia does not support Android TV. Please disable the Android TV compatibility in the Player Settings.
    
    Build completed with a result of 'Failed'
    UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
    
    
    UnityEditor.BuildPlayerWindow+BuildMethodException: 2 errors
      at UnityEditor.BuildPlayerWindow+DefaultBuildMethods.BuildPlayer (BuildPlayerOptions options) [0x0020e] in C:\buildslave\unity\build\Editor\Mono\BuildPlayerWindowBuildMethods.cs:181 
      at UnityEditor.BuildPlayerWindow.CallBuildMethods (Boolean askForBuildLocation, BuildOptions defaultBuildOptions) [0x00065] in C:\buildslave\unity\build\Editor\Mono\BuildPlayerWindowBuildMethods.cs:88 
    UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
    
    

    这里写图片描述

    解决方案:

    所以需要在 Player Setting 中关闭该选项


    即可成功打包工程

    举个例子
    这里写图片描述


    4

    Quote UnityEditor —— 脚本引用 UnityEditor,导致无法打包


    错误发生场景

    打包项目/工程时报错

    Unity Asset 目录中,如果脚本中引用了 UnityEditor

    那么该脚本就应该放在 Editor 文件夹下 ( 如果没有,就新建一个名为 Editor 的文件夹)

    具体报错信息:
    Assets/CreateGuanJians.cs(4,7): error CS0246: The type or namespace name `UnityEditor' could not be found. Are you missing an assembly reference?
    
    Error building Player because scripts had compiler errors
    
    Build completed with a result of 'Failed'
    UnityEditor.BuildPlayerWindow:BuildPlayerAndRun()
    
    UnityEditor.BuildPlayerWindow+BuildMethodException: 2 errors
      at UnityEditor.BuildPlayerWindow+DefaultBuildMethods.BuildPlayer (BuildPlayerOptions options) [0x0020e] in C:\buildslave\unity\build\Editor\Mono\BuildPlayerWindowBuildMethods.cs:181 
      at UnityEditor.BuildPlayerWindow.CallBuildMethods (Boolean askForBuildLocation, BuildOptions defaultBuildOptions) [0x00065] in C:\buildslave\unity\build\Editor\Mono\BuildPlayerWindowBuildMethods.cs:88 
    UnityEditor.BuildPlayerWindow:BuildPlayerAndRun()
    
    

    这里写图片描述

    解决方案:

    将引用有 UnityEditor 的脚本放在 Editor 文件夹下


    ( 如果没有,就新建一个名为 Editor 的文件夹)


    即可成功打包工程

    举个例子
    这里写图片描述


    5

    Socket: bind failed, error: —— 套接字绑定失败


    错误发生场景

    打开/新建 Unity 项目时报错

    这是由于权限不够,或者网络端口被占用造成的

    具体报错信息:
    Socket: bind failed, error: 以一种访问权限不允许的方式做了一个访问套接字的尝试。
    (0)
    
    
    Unable to join player connection multicast group.
    

    切

    解决方案:

    1. 直接 Clear 清空控制台,不用理它

    2. 用管理员权限打开 Unity (可选)


    5

    In continuous update —— 持续更新中…


    错误发生场景

    错误不断更新中…最后汇集所有报错指南

    请您惠存,支持 Chinar


    支持

    May Be —— 开发者,总有一天要做的事!


    拥有自己的服务器,无需再找攻略

    Chinar 提供一站式《零》基础教程

    使有限时间 具备无限可能!

    Chinar 知你所想,予你所求!( Chinar Blog )


    Chinar

    END

    本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

    对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

    对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

    展开全文
  • E:\software\Java\jdk8\bin\java.exe -Xmx2048M -Dcom.android.sdkmanager.toolsdir="E:\software\Android\AndroidSDK\tools" -Dfile.encoding=UTF8 -jar "E:\software\Unity5_5\Editor\Data\PlaybackEngines\Androi

    报错1
    Failed to compile resources with the following parameters:
    -bootclasspath "E:\software\Android\AndroidSDK_ForUnity5\platforms\android-24\android.jar" -d "D:\h5\UnityProjects\IceClimber\Temp\StagingArea\bin\classes" -source 1.6 -target 1.6 -encoding UTF-8 "android\support\customtabs\R.java" "android\support\graphics\drawable\R.java" "android\support\graphics\drawable\animated\R.java" "android\support\v4\R.java" "android\support\v7\appcompat\R.java" "android\support\v7\cardview\R.java" "com\facebook\R.java" "com\facebook\android\R.java" "com\herofun\iceclimber\R.java"
    解决方案:
    可能是jdk版本低了,使用jdk8解决。


    报错2
    IOException: Failed to Move File / Directory from 'Temp/StagingArea\android-libraries\app-debug\classes.jar' to 'Temp/StagingArea\android-libraries\app-debug\libs\classes.jar'.
    UnityEditor.Android.PostProcessor.Tasks.ProcessAAR.Execute (UnityEditor.Android.PostProcessor.PostProcessorContext context)
    UnityEditor.Android.PostProcessor.PostProcessRunner.RunAllTasks (UnityEditor.Android.PostProcessor.PostProcessorContext context)
    UnityEditor.Android.PostProcessAndroidPlayer.PostProcess (BuildTarget target, System.String stagingAreaData, System.String stagingArea, System.String playerPackage, System.String installPath, System.String companyName, System.String productName, BuildOptions options, UnityEditor.RuntimeClassRegistry usedClassRegistry)
    UnityEditor.Android.AndroidBuildPostprocessor.PostProcess (BuildPostProcessArgs args)
    UnityEditor.PostprocessBuildPlayer.Postprocess (BuildTarget target, System.String installPath, System.String companyName, System.String productName, Int32 width, Int32 height, System.String downloadWebplayerUrl, System.String manualDownloadWebplayerUrl, BuildOptions options, UnityEditor.RuntimeClassRegistry usedClassRegistry, UnityEditor.BuildReporting.BuildReport report) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/PostprocessBuildPlayer.cs:186)
    UnityEditor.HostView:OnGUI()
    解决方案
    删除aar中的libs/classes.jar

    报错3
    Error: [Temp\StagingArea\AndroidManifest-main.xml:12, 
    D:\h5\UnityProjects\Test\AARTest\Temp\StagingArea\android-libraries\app-debug\AndroidManifest.xml:3] 
    Main manifest has <uses-sdk android:minSdkVersion='9'> but library uses minSdkVersion='15'
    UnityEditor.HostView:OnGUI()
    解决方案
    在Unity的PlayerSetting中把minSdkVersion设成与第三方库中的minSdkVersion一致

    报错4
    CommandInvokationFailure: Failed to re-package resources.
    E:\software\Android\AndroidSDK_ForUnity5\build-tools\24.0.1\aapt.exe package
     --auto-add-overlay -v -f -m -J "gen" -M "AndroidManifest.xml" -S "res" -I 
     "E:\software\Android\AndroidSDK_ForUnity5\platforms\android-25\android.jar" 
     -F bin/resources.ap_ --extra-packages com.zwwx.game.gamesupport -S 
     "D:\h5\UnityProjects\Test\AARTest\Temp\StagingArea\android-libraries\app-debug\res"
    错误原因
    build-tools用的版本是24,platforms版本用的是android-25, 两个版本不一致导致报错。
    解决方案
    使用platforms/android-24打包

    报错5
    CommandInvokationFailure: Unable to merge android manifests. See the Console for more details. 
    E:\software\Java\jdk8\bin\java.exe -Xmx2048M -Dcom.android.sdkmanager.toolsdir="E:\software\Android\AndroidSDK_ForUnity5\tools" -Dfile.encoding=UTF8 -jar "E:\software\Unity5_5\Editor\Data\PlaybackEngines\AndroidPlayer/Tools\sdktools.jar" -
    stdout[
    Warning: [Temp\StagingArea\AndroidManifest-main.xml:12, 
    D:\h5\UnityProjects\Test\AARTest\Temp\StagingArea\android-libraries\app-debug\AndroidManifest.xml:3] 
    Main manifest has <uses-sdk android:targetSdkVersion='23'> but library uses targetSdkVersion='25'
    ]
    错误原因
    第三方库与Unity中用的SDK的targetSdkVersion版本不一致。
    解决方案
    Unity使用targetSdkVersion='25'打包。
    Android SDK升级到以下版本
    platforms/android-25、tools_r25.2.5-windows、build-tools_r25.0.2-windows
    注意:最新版本的tools下没有android.bat命令,打包会报Error:Invalid command android错误

    报错6
    CommandInvokationFailure: Unable to list target platforms.Please make sure the android sdk path is correct. See the Console for more details. 
    E:\software\Java\jdk8\bin\java.exe -Xmx2048M -Dcom.android.sdkmanager.toolsdir="E:\software\Android\AndroidSDK\tools" -Dfile.encoding=UTF8 -jar "E:\software\Unity5_5\Editor\Data\PlaybackEngines\AndroidPlayer/Tools\sdktools.jar" -
    stderr[
    Error:Invalid command android
    ]
    错误原因
    新版本的tools下没有android.bat命令,所以打包时报Error:Invalid command android
    解决方案
    下个旧版本的tools再打包。tools_r25.2.5-windows.zip

    报错7
    UnityException: Adding Android library projects failed!
    UnityEditor.Android.AndroidLibraries.AddLibraryProject (System.String projectPropertiesPath)
    UnityEditor.Android.AndroidLibraries.FindAndAddLibraryProjects (System.String searchPattern)
    UnityEditor.Android.PostProcessor.Tasks.AddAndroidLibraries.Execute (UnityEditor.Android.PostProcessor.PostProcessorContext context)
    UnityEditor.Android.PostProcessor.PostProcessRunner.RunAllTasks (UnityEditor.Android.PostProcessor.PostProcessorContext context)
    错误原因
    aar中的某些文件被删除了,比如aar中的AndroidManifest.xml被删除了。
    解决方案
    重新生成个aar

    报错8
    Error:Execution failed for task ':processReleaseGoogleServices'.
    > No matching client found for package name 'com.zwwx.game.WinterJump'
    原因:google-services.json中的包名与build.gradle中的包名不一致。
    解决方案:改成一致就行了。


    报错9
    用gradle build打包时报以下错
    To run dex in process, the Gradle daemon needs a larger heap.
    It currently has 1024 MB.
    For faster builds, increase the maximum heap size for the Gradle daemon to at le
    ast 1536 MB.
    To do this set org.gradle.jvmargs=-Xmx1536M in the project gradle.properties.
    For more information see https://docs.gradle.org/current/userguide/build_environ
    ment.html
    原因:gradle需要更大内存
    解决方案: 修改gradle-wrapper.properties文件。
    gradle-wrapper.properties文件中添加一条配置
    set  org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=2048m


    报错10
    Parsing json file: D:\xxx\google-services.json
    :processDebugGoogleServices FAILED
    FAILURE: Build failed with an exception.
    * What went wrong:
    Execution failed for task ':processDebugGoogleServices'.
    > No matching client found for package name 'com.xx.xxx.xxxxx'
    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
    原因:google-services.json中定义的包名与AndroidManifest.xml中定义的包名不一致。

    解决方案:包名改一致。


    报错11
    Rejecting re-init on previously-faile d class java.lang.Class<com.helpshift.support.adapters.QuestionListAdapter>: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v7/widget/RecyclerView$Adapter;
    解决方案: 删除libs下的android-support-v4.jar保留android-support-v7-appcompat.jar


    报错12

    CommandInvokationFailure: Unable to convert classes into dex format.
    E:/JavaJDK/jdk\bin\java.exe -Xmx2048M -Dcom.android.sdkmanager.toolsdir="E:/androidsdk\tools" -Dfile.encoding=UTF8 -jar "F:\unity\Editor\Data\PlaybackEngines\Player/Tools\sdktools.jar" -

    stderr[
    Exception in thread "main" java.lang.UnsupportedClassVersionError: com/android/dx/command/Main : Unsupported major.minor version 52.0
    我出现这个问题的时候下面的提示还没有看只看上面红字部分,说明jdk版本太低,我原来是1.7的换成1.8果断好使




    展开全文
  • unity 3D里有两种动态加载机制: 一是Resources.Load; 一是通过AssetBundle; 其实两者本质上没有什么区别。Resources.Load就是从一个缺省进程序包里的AssetBundle里加载资源,而一般AssetBundle文件需要你...

    unity 3D里有两种动态加载机制:

         一是Resources.Load

         一是通过AssetBundle

         其实两者本质上没有什么区别。Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载资源,而一般AssetBundle文件需要你自己创建,运行时动态加载,可以指定路径和来源的。其实场景里所有静态的对象也有这么一个加载过程,只是Unity后台替你自动完成了。

    1.    AssetBundles是什么?

         在一些大型的网络游戏,或者加载比较多的一些场景时,如果要等待所有模型,贴图等各种资源文件加载完毕才能执行游戏,对用户将会是一个很头大的事情。所以就需要用到动态加载,即AssetBundles。比如玩家在进入游戏时先加载一些周围的场景文件,这样不仅可以提高速度还可以减少内存资源的消耗。      

         AssetBundles是可以把unity3d中你所创建的文件或任何资源导出的一种文件格式,这些文件导出后使用的是一种特定的文件格式(.Unity3d),这些特定格式的文件能在需要的时候加载到场景中。而这些特定的文件格式可以是模型,贴图,声音文件甚至是场景文件,它们是先前就被设计好的文件,所以很容易就可以被下载到你所建立的游戏或场景中来

         AssetBundles 可以是任意类型的文件只要是unity3d能识别的资源文件格式,识别主要是以文件扩展名为准,比如.prefab等等。当然如果你想包含自定义的二进制文件,需要命名这些文件为以".bytes"为后缀,Unity将会把这些文件导成TextAssets。

    2.    Creating AssetBundles 创建资源包

    有三个类方法可以用来构建资源包:

    BuildPipeline.BuildAssetBundle,

    BuildPipeline.BuildStreamedSceneAssetBundle

    BuildPipeline.BuildAssetBundleExplicitAssetNames.

    • BuildPipeline.BuildAssetBundle allows you to build AssetBundles of any type of asset.
          可以构建任意类型资源的资源包。【创建一个压缩好的包含Assets下的所有资源文件.unity3d。可以包含是项目目录下的任意资源,而把所有的资源压缩成一个.unity3d的文件,这个文件包括所有的预置物体(prefabs),纹理贴图(textures),模型,动画。使用AssetBundle.mainAsset这个函数可以很方便的让你指定一个定义好的物体。被压缩的资源储存在pathName. Options,会自动的允许用户包含相关的或者需要用到的】
    • BuildPipeline.BuildStreamedSceneAssetBundle is used when you want to include only scenes to be streamed and loaded as the data becomes available.
           用来当你希望只包括流场景,使数据加载变为可用。【建立一个或多个场景,这些场景所需要的所有资源将被压缩入资源包,即asset bundle里面。资源包中的场景文件可以在任何平台上建立,而且这些文件往往是以一个单一的unity3d文件格式被用来创建。使用WWW类可以下载场景文件。当场景文件被下载好可以使用WWW.LoadFromCacheOrDownload来加载下载好的场景文件。】
    • BuildPipeline.BuildAssetBundleExplicitAssetNames is the same as BuildPipeline.BuildAssetBundle but has an extra parameter to specify a custom string identifier (name) for each object.
           和BuildPipeline.BuildAssetBundle类似,但是有额外的参数来指定每个物体的自定义的字符串(名字)。【建立一个自定义名字的资源包方法:创建一个包含所有资源的一个压缩好的unity3d文件。AssetBundle可以包括任何项目目录下的资源文件。在assetNames参数中提供一个与资源数目相同大小的字符串数组。在资源数组中存储的信息与资源文件名相同,可以传递AssetBundle.Load去加载一个指定的资源。使用BuildAssetBundle时,只需使用资源的路径名。压缩好的资源包文件将会被储存在pathName. Options,允许用户自动包含与之相关的或者总是包含完整的资源去代替确切的参照物体。】

              当使用上面的三个函数做完准备工作,我们现在就需要去下载这些资源然后加载它们。

    3.    Downloading AssetBundles 下载资源包

    推荐使用WWW.LoadFromCacheOrDownload方法用来下载资源。当下载完成你就可以重新得到该资源的相关属性,例如:

    1. function Start ()
    2. {
    3.      var www = WWW.LoadFromCacheOrDownload ("http://myserver.com/myassetBundle.unity3d", 
    4. 5);
    5. yield www;
    6. if (www.error != null)
    7. {
    8.      Debug.Log (www.error);
    9.      return;
    10. }
    11.     var myLoadedAssetBundle = www.assetBundle;
    12.     var asset = myLoadedAssetBundle.mainAsset;
    13. }

    复制代码

    4.   Loading and unloading objects from an AssetBundle从资源包加载和卸载对象

            下载完以后,等于把硬盘或者网络的一个文件读到内存一个区域,这时候只是个AssetBundle内存镜像数据块,还没有Assets的概念。就可以使用这三个不同的函数来加载物体了:

    AssetBundle.Load

    AssetBundle.LoadAsync

    AssetBundle.LoadAll

    • AssetBundle.Load会加载物体,使用该物体的名字作为识别的参数。名字可以在Unity3d中Project view看到。你可以自由选择去传递对象变量的类型来确认该加载对象是否是被指定的类型。
    • AssetBundle.LoadAsync 与AssetBundle.Load 函数相类似,但是当资源加载时它不会阻碍主线程。如果同时要加载比较大的资源或者很多资源时,这个函数会比较有用,它可以避免程序的暂停,因为它会同步加载。
    • AssetBundle.LoadAll 顾名思义这个函数是用来加载所有在你资源包中的对象。作为AssetBundle.Load这个函数,你可以随意用该对象的类型去过滤。

            使用AssetBundle.Unload这个函数可以卸载加载好的资源,这个函数有一个布尔值的参数是用来告诉Unity是否要卸载所有的数据(包含加载的资源对象)或者只是已经下载过的被压缩好的资源数据。如果要在资源包中从你的应用程序要使用一些对象或者你想释放一些内存,可以传递false这个值来卸载已经压缩好了的文件从你的内存中(即.unity3d文件)。如果要完全卸载所有的资源数据,需要传递true这个值,这将会销毁所有的资源包器中加载的资源。

            AssetBundle.Unload(flase)是释放AssetBundle文件的内存镜像,不包含Load创建的Asset内存对象。

            AssetBundle.Unload(true)是释放那个AssetBundle文件内存镜像和并销毁所有用Load创建的Asset内存对象。

    5. Instantiating objects from AssetBundles 从资源包实例化物体

           下载了资源,也加载好了,那么就该在场景中使用Instantiate函数去实例化它了。

            Instantiate一个Prefab,是一个对Assets进行Clone(复制)+引用结合的过程,GameObject transform 是Clone是新生成的。其他mesh / texture / material / shader 等,这其中些是纯引用的关系的,包括:Texture和TerrainData,还有引用和复制同时存在的,包括:Mesh/material/PhysicMaterial。引用的Asset对象不会被复制,只是一个简单的指针指向已经Load的Asset对象。

    Unity里每个Script都是一个封闭的Class定义而已,并没有写调用代码,光Class的定义脚本是不会工作的。其实Unity引擎就是那个调用代码,Clone一个script asset等于new一个class实例,实例才会完成工作。把他挂到Unity主线程的调用链里去,Class实例里的OnUpdate OnStart等才会被执行。多个物体挂同一个脚本,其实就是在多个物体上挂了那个脚本类的多个实例而已,这样就好理解了。在new class这个过程中,数据区是复制的,代码区是共享的,算是一种特殊的复制+引用关系。

            当你Destroy一个实例时,只是释放那些Clone对象,并不会释放引用对象和Clone的数据源对象,Destroy并不知道是否还有别的object在引用那些对象。等到没有任何游戏场景物体在用这些Assets以后,这些assets就成了没有引用的游离数据块了,是UnusedAssets了,这时候就可以通过Resources.UnloadUnusedAssets来释放,Destroy不能完成这个任务,AssetBundle.Unload(false)也不行,AssetBundle.Unload(true)可以但不安全,除非你很清楚没有任何对象在用这些Assets了。

    1. string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
    2. IEnumerator Start () {
    3. // Start a download of the given URL
    4. // 开始从指定路径下载
    5. WWW www = WWW.LoadFromCacheOrDownload (url, 1);
    6. // Wait for download to complete
    7. // 等待下载完成
    8. yield return www;
    9. // Load and retrieve the AssetBundle
    10. // 加载并取回资源包
    11. AssetBundle bundle = www.assetBundle;
    12. // Load the TextAsset object
    13. // 加载文本资源对象
    14. GameObject go = bundle.Load("myGameObject", typeof(GameObject)) as GameObject;
    15. // Instantiate the GameObject
    16. // 实例化该对象
    17. Instantiate(go);
    18. }

    复制代码


    Unity不提供自动的一个可以取回所有被下载资源的列表。所以需要我们在脚本中要建立这些资源对象的信息和它们的路径以便我们去查找。

    6. Including scripts in AssetBundles 在资源包中包含脚本

           资源包可以作为TextAssets包含脚本但是不会实际执行代码。如果想要在资源包包含用来执行应用程序的代码,需要预先编译,然后使用Mono Reflection class来加载(注意:Reflection在iOS平台不可用)。可以在任何版本的C#IDE编辑器(如:Monodevelop, Visual Studio)或者使用mono/.net 文档编辑器。

    1. string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
    2. IEnumerator Start () {
    3. // Start a download of the given URL
    4. WWW www = WWW.LoadFromCacheOrDownload (url, 1);
    5. // Wait for download to complete
    6. yield return www;
    7. // Load and retrieve the AssetBundle
    8. AssetBundle bundle = www.assetBundle;
    9. // Load the TextAsset object
    10. TextAsset txt = bundle.Load("myBinaryAsText", typeof(TextAsset)) as TextAsset;
    11. // Load the assembly and get a type (class) from it
    12. var assembly = System.Reflection.Assembly.Load(txt.bytes);
    13. var type = assembly.GetType("MyClassDerivedFromMonoBehaviour");
    14. // Instantiate a GameObject and add a component with the loaded class
    15. GameObject go = new GameObject();
    16. go.AddComponent(type);
    17. }

    复制代码

    一个常见的错误:

             从某个AssetBundle里Load了一个prefab并克隆之:obj = Instantiate (AssetBundle1.Load('MyPrefab”);

              这个prefab比如是个npc,然后你不需要他的时候你用了:Destroy(obj);你以为就释放干净了。其实这时候只是释放了Clone对象,通过Load加载的所有引用、非引用Assets对象全都静静静的躺在内存里。这种情况应该在Destroy以后用:AssetBundle1.Unload(true),彻底释放干净。如果这个AssetBundle1是要反复读取的 不方便Unload,那可以在Destroy以后用:Resources.UnloadUnusedAssets()把所有和这个npc有关的Asset都销毁。

              当然如果这个NPC也是要频繁创建 销毁的那就应该让那些Assets呆在内存里以加速游戏体验。由此可以解释另一个之前有人提过的话题:为什么第一次Instantiate一个Prefab的时候都会卡一下,因为在你第一次Instantiate之前,相应的Asset对象还没有被创建,要加载系统内置的AssetBundle并创建Assets,第一次以后你虽然Destroy了,但Prefab的Assets对象都还在内存里,所以就很快了。

     

    资源加载和释放例子:

    从磁盘读取一个1.unity3d文件到内存并建立一个AssetBundle1对象

    AssetBundle AssetBundle1 = AssetBundle.CreateFromFile("1.unity3d");

    从AssetBundle1里读取并创建一个Texture Asset,把obj1的主贴图指向它

    obj1.renderer.material.mainTexture = AssetBundle1.Load("wall") as Texture;

    把obj2的主贴图也指向同一个Texture Asset

    obj2.renderer.material.mainTexture =obj1.renderer.material.mainTexture;

    Texture是引用对象,永远不会有自动复制的情况出现(除非你真需要,用代码自己实现copy),只会是创建和添加引用

    继续:

    AssetBundle1.Unload(true) 那obj1和obj2都变成黑的了,因为指向的Texture Asset没了

    如果:

    AssetBundle1.Unload(false) 那obj1和obj2不变,只是AssetBundle1的内存镜像释放了

    继续:

    Destroy(obj1),//obj1被释放,但并不会释放刚才Load的Texture

    如果这时候:

    Resources.UnloadUnusedAssets();

    不会有任何内存释放 因为Texture asset还被obj2用着

    如果:

    Destroy(obj2)

    obj2被释放,但也不会释放刚才Load的Texture

    继续:

    Resources.UnloadUnusedAssets();

    这时候刚才load的Texture Asset释放了,因为没有任何引用了

    最后CG.Collect();

    强制立即释放内存。

     

    如何加载一堆大图片轮流显示又不爆掉?

    不考虑AssetBundle,直接用www读图片文件的话等于是直接创建了一个Texture Asset。

    1. TLlist<string> fileList;
    2. int n=0;
    3. IEnumerator OnClick()
    4. {
    5. WWW image = new www(fileList[n++]);
    6. yield return image;
    7. Texture tex = obj.mainTexture;
    8. obj.mainTexture = image.texture;
    9.  
    10. n = (n>=fileList.Length-1)?0:n;
    11. Resources.UnloadAsset(tex);
    12. }

    3D里有两种动态加载机制:

         一是Resources.Load

         一是通过AssetBundle

         其实两者本质上没有什么区别。Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载资源,而一般AssetBundle文件需要你自己创建,运行时动态加载,可以指定路径和来源的。其实场景里所有静态的对象也有这么一个加载过程,只是Unity后台替你自动完成了。

    1.    AssetBundles是什么?

         在一些大型的网络游戏,或者加载比较多的一些场景时,如果要等待所有模型,贴图等各种资源文件加载完毕才能执行游戏,对用户将会是一个很头大的事情。所以就需要用到动态加载,即AssetBundles。比如玩家在进入游戏时先加载一些周围的场景文件,这样不仅可以提高速度还可以减少内存资源的消耗。      

         AssetBundles是可以把unity3d中你所创建的文件或任何资源导出的一种文件格式,这些文件导出后使用的是一种特定的文件格式(.Unity3d),这些特定格式的文件能在需要的时候加载到场景中。而这些特定的文件格式可以是模型,贴图,声音文件甚至是场景文件,它们是先前就被设计好的文件,所以很容易就可以被下载到你所建立的游戏或场景中来

         AssetBundles 可以是任意类型的文件只要是unity3d能识别的资源文件格式,识别主要是以文件扩展名为准,比如.prefab等等。当然如果你想包含自定义的二进制文件,需要命名这些文件为以".bytes"为后缀,Unity将会把这些文件导成TextAssets。

    2.    Creating AssetBundles 创建资源包

    有三个类方法可以用来构建资源包:

    BuildPipeline.BuildAssetBundle,

    BuildPipeline.BuildStreamedSceneAssetBundle

    BuildPipeline.BuildAssetBundleExplicitAssetNames.

    • BuildPipeline.BuildAssetBundle allows you to build AssetBundles of any type of asset.
          可以构建任意类型资源的资源包。【创建一个压缩好的包含Assets下的所有资源文件.unity3d。可以包含是项目目录下的任意资源,而把所有的资源压缩成一个.unity3d的文件,这个文件包括所有的预置物体(prefabs),纹理贴图(textures),模型,动画。使用AssetBundle.mainAsset这个函数可以很方便的让你指定一个定义好的物体。被压缩的资源储存在pathName. Options,会自动的允许用户包含相关的或者需要用到的】
    • BuildPipeline.BuildStreamedSceneAssetBundle is used when you want to include only scenes to be streamed and loaded as the data becomes available.
           用来当你希望只包括流场景,使数据加载变为可用。【建立一个或多个场景,这些场景所需要的所有资源将被压缩入资源包,即asset bundle里面。资源包中的场景文件可以在任何平台上建立,而且这些文件往往是以一个单一的unity3d文件格式被用来创建。使用WWW类可以下载场景文件。当场景文件被下载好可以使用WWW.LoadFromCacheOrDownload来加载下载好的场景文件。】
    • BuildPipeline.BuildAssetBundleExplicitAssetNames is the same as BuildPipeline.BuildAssetBundle but has an extra parameter to specify a custom string identifier (name) for each object.
           和BuildPipeline.BuildAssetBundle类似,但是有额外的参数来指定每个物体的自定义的字符串(名字)。【建立一个自定义名字的资源包方法:创建一个包含所有资源的一个压缩好的unity3d文件。AssetBundle可以包括任何项目目录下的资源文件。在assetNames参数中提供一个与资源数目相同大小的字符串数组。在资源数组中存储的信息与资源文件名相同,可以传递AssetBundle.Load去加载一个指定的资源。使用BuildAssetBundle时,只需使用资源的路径名。压缩好的资源包文件将会被储存在pathName. Options,允许用户自动包含与之相关的或者总是包含完整的资源去代替确切的参照物体。】

              当使用上面的三个函数做完准备工作,我们现在就需要去下载这些资源然后加载它们。

    3.    Downloading AssetBundles 下载资源包

    推荐使用WWW.LoadFromCacheOrDownload方法用来下载资源。当下载完成你就可以重新得到该资源的相关属性,例如:

     

    1. function Start ()
    2. {
    3.      var www = WWW.LoadFromCacheOrDownload ("http://myserver.com/myassetBundle.unity3d", 
    4. 5);
    5. yield www;
    6. if (www.error != null)
    7. {
    8.      Debug.Log (www.error);
    9.      return;
    10. }
    11.     var myLoadedAssetBundle = www.assetBundle;
    12.     var asset = myLoadedAssetBundle.mainAsset;
    13. }

    复制代码

    4.   Loading and unloading objects from an AssetBundle从资源包加载和卸载对象

            下载完以后,等于把硬盘或者网络的一个文件读到内存一个区域,这时候只是个AssetBundle内存镜像数据块,还没有Assets的概念。就可以使用这三个不同的函数来加载物体了:

     

    AssetBundle.Load

     

    AssetBundle.LoadAsync

     

    AssetBundle.LoadAll

     

    • AssetBundle.Load会加载物体,使用该物体的名字作为识别的参数。名字可以在Unity3d中Project view看到。你可以自由选择去传递对象变量的类型来确认该加载对象是否是被指定的类型。
    • AssetBundle.LoadAsync 与AssetBundle.Load 函数相类似,但是当资源加载时它不会阻碍主线程。如果同时要加载比较大的资源或者很多资源时,这个函数会比较有用,它可以避免程序的暂停,因为它会同步加载。
    • AssetBundle.LoadAll 顾名思义这个函数是用来加载所有在你资源包中的对象。作为AssetBundle.Load这个函数,你可以随意用该对象的类型去过滤。

     

            使用AssetBundle.Unload这个函数可以卸载加载好的资源,这个函数有一个布尔值的参数是用来告诉Unity是否要卸载所有的数据(包含加载的资源对象)或者只是已经下载过的被压缩好的资源数据。如果要在资源包中从你的应用程序要使用一些对象或者你想释放一些内存,可以传递false这个值来卸载已经压缩好了的文件从你的内存中(即.unity3d文件)。如果要完全卸载所有的资源数据,需要传递true这个值,这将会销毁所有的资源包器中加载的资源。

     

            AssetBundle.Unload(flase)是释放AssetBundle文件的内存镜像,不包含Load创建的Asset内存对象。

     

            AssetBundle.Unload(true)是释放那个AssetBundle文件内存镜像和并销毁所有用Load创建的Asset内存对象。

    5. Instantiating objects from AssetBundles 从资源包实例化物体

           下载了资源,也加载好了,那么就该在场景中使用Instantiate函数去实例化它了。

     

            Instantiate一个Prefab,是一个对Assets进行Clone(复制)+引用结合的过程,GameObject transform 是Clone是新生成的。其他mesh / texture / material / shader 等,这其中些是纯引用的关系的,包括:Texture和TerrainData,还有引用和复制同时存在的,包括:Mesh/material/PhysicMaterial。引用的Asset对象不会被复制,只是一个简单的指针指向已经Load的Asset对象。

     

    Unity里每个Script都是一个封闭的Class定义而已,并没有写调用代码,光Class的定义脚本是不会工作的。其实Unity引擎就是那个调用代码,Clone一个script asset等于new一个class实例,实例才会完成工作。把他挂到Unity主线程的调用链里去,Class实例里的OnUpdate OnStart等才会被执行。多个物体挂同一个脚本,其实就是在多个物体上挂了那个脚本类的多个实例而已,这样就好理解了。在new class这个过程中,数据区是复制的,代码区是共享的,算是一种特殊的复制+引用关系。

     

            当你Destroy一个实例时,只是释放那些Clone对象,并不会释放引用对象和Clone的数据源对象,Destroy并不知道是否还有别的object在引用那些对象。等到没有任何游戏场景物体在用这些Assets以后,这些assets就成了没有引用的游离数据块了,是UnusedAssets了,这时候就可以通过Resources.UnloadUnusedAssets来释放,Destroy不能完成这个任务,AssetBundle.Unload(false)也不行,AssetBundle.Unload(true)可以但不安全,除非你很清楚没有任何对象在用这些Assets了。

     

    1. string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
    2. IEnumerator Start () {
    3. // Start a download of the given URL
    4. // 开始从指定路径下载
    5. WWW www = WWW.LoadFromCacheOrDownload (url, 1);
    6. // Wait for download to complete
    7. // 等待下载完成
    8. yield return www;
    9. // Load and retrieve the AssetBundle
    10. // 加载并取回资源包
    11. AssetBundle bundle = www.assetBundle;
    12. // Load the TextAsset object
    13. // 加载文本资源对象
    14. GameObject go = bundle.Load("myGameObject", typeof(GameObject)) as GameObject;
    15. // Instantiate the GameObject
    16. // 实例化该对象
    17. Instantiate(go);
    18. }

    复制代码

     


    Unity不提供自动的一个可以取回所有被下载资源的列表。所以需要我们在脚本中要建立这些资源对象的信息和它们的路径以便我们去查找。

    6. Including scripts in AssetBundles 在资源包中包含脚本

           资源包可以作为TextAssets包含脚本但是不会实际执行代码。如果想要在资源包包含用来执行应用程序的代码,需要预先编译,然后使用Mono Reflection class来加载(注意:Reflection在iOS平台不可用)。可以在任何版本的C#IDE编辑器(如:Monodevelop, Visual Studio)或者使用mono/.net 文档编辑器。

     

    1. string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
    2. IEnumerator Start () {
    3. // Start a download of the given URL
    4. WWW www = WWW.LoadFromCacheOrDownload (url, 1);
    5. // Wait for download to complete
    6. yield return www;
    7. // Load and retrieve the AssetBundle
    8. AssetBundle bundle = www.assetBundle;
    9. // Load the TextAsset object
    10. TextAsset txt = bundle.Load("myBinaryAsText", typeof(TextAsset)) as TextAsset;
    11. // Load the assembly and get a type (class) from it
    12. var assembly = System.Reflection.Assembly.Load(txt.bytes);
    13. var type = assembly.GetType("MyClassDerivedFromMonoBehaviour");
    14. // Instantiate a GameObject and add a component with the loaded class
    15. GameObject go = new GameObject();
    16. go.AddComponent(type);
    17. }

    复制代码

     

    一个常见的错误:

     

             从某个AssetBundle里Load了一个prefab并克隆之:obj = Instantiate (AssetBundle1.Load('MyPrefab”);

     

              这个prefab比如是个npc,然后你不需要他的时候你用了:Destroy(obj);你以为就释放干净了。其实这时候只是释放了Clone对象,通过Load加载的所有引用、非引用Assets对象全都静静静的躺在内存里。这种情况应该在Destroy以后用:AssetBundle1.Unload(true),彻底释放干净。如果这个AssetBundle1是要反复读取的 不方便Unload,那可以在Destroy以后用:Resources.UnloadUnusedAssets()把所有和这个npc有关的Asset都销毁。

     

              当然如果这个NPC也是要频繁创建 销毁的那就应该让那些Assets呆在内存里以加速游戏体验。由此可以解释另一个之前有人提过的话题:为什么第一次Instantiate一个Prefab的时候都会卡一下,因为在你第一次Instantiate之前,相应的Asset对象还没有被创建,要加载系统内置的AssetBundle并创建Assets,第一次以后你虽然Destroy了,但Prefab的Assets对象都还在内存里,所以就很快了。

     

     

     

    资源加载和释放例子:

     

    从磁盘读取一个1.unity3d文件到内存并建立一个AssetBundle1对象

     

    AssetBundle AssetBundle1 = AssetBundle.CreateFromFile("1.unity3d");

     

    从AssetBundle1里读取并创建一个Texture Asset,把obj1的主贴图指向它

     

    obj1.renderer.material.mainTexture = AssetBundle1.Load("wall") as Texture;

     

    把obj2的主贴图也指向同一个Texture Asset

     

    obj2.renderer.material.mainTexture =obj1.renderer.material.mainTexture;

     

    Texture是引用对象,永远不会有自动复制的情况出现(除非你真需要,用代码自己实现copy),只会是创建和添加引用

     

    继续:

     

    AssetBundle1.Unload(true) 那obj1和obj2都变成黑的了,因为指向的Texture Asset没了

     

    如果:

     

    AssetBundle1.Unload(false) 那obj1和obj2不变,只是AssetBundle1的内存镜像释放了

     

    继续:

     

    Destroy(obj1),//obj1被释放,但并不会释放刚才Load的Texture

     

    如果这时候:

     

    Resources.UnloadUnusedAssets();

     

    不会有任何内存释放 因为Texture asset还被obj2用着

     

    如果:

     

    Destroy(obj2)

     

    obj2被释放,但也不会释放刚才Load的Texture

     

    继续:

     

    Resources.UnloadUnusedAssets();

     

    这时候刚才load的Texture Asset释放了,因为没有任何引用了

     

    最后CG.Collect();

     

    强制立即释放内存。

     

     

     

    如何加载一堆大图片轮流显示又不爆掉?

     

    不考虑AssetBundle,直接用www读图片文件的话等于是直接创建了一个Texture Asset。

    展开全文
  • Unity3D加载外部资源

    2015-06-26 10:42:28
    Unity 3D里有两种动态加载机制:  一是Resources.Load;  一是通过AssetBundle;  其实两者本质上没有什么区别。Resources.Load就是从一个缺省进程序包里的AssetBundle里加载资源,而一般AssetBundle文件...

    Unity 3D里有两种动态加载机制

         一是Resources.Load

         一是通过AssetBundle

         其实两者本质上没有什么区别。Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载资源,而一般AssetBundle文件需要你自己创建,运行时动态加载,可以指定路径和来源的。其实场景里所有静态的对象也有这么一个加载过程,只是Unity后台替你自动完成了。

    1.    AssetBundles是什么?

         在一些大型的网络游戏,或者加载比较多的一些场景时,如果要等待所有模型,贴图等各种资源文件加载完毕才能执行游戏,对用户将会是一个很头大的事情。所以就需要用到动态加载,即AssetBundles。比如玩家在进入游戏时先加载一些周围的场景文件,这样不仅可以提高速度还可以减少内存资源的消耗。       

         AssetBundles是可以把unity3d中你所创建的文件或任何资源导出的一种文件格式,这些文件导出后使用的是一种特定的文件格式(.Unity3d),这些特定格式的文件能在需要的时候加载到场景中。而这些特定的文件格式可以是模型,贴图,声音文件甚至是场景文件,它们是先前就被设计好的文件,所以很容易就可以被下载到你所建立的游戏或场景中来

         AssetBundles 可以是任意类型的文件只要是unity3d能识别的资源文件格式,识别主要是以文件扩展名为准,比如.prefab等等。当然如果你想包含自定义的二进制文件,需要命名这些文件为以".bytes"为后缀,Unity将会把这些文件导成TextAssets

    2.    Creating AssetBundles 创建资源包

    有三个类方法可以用来构建资源包:

    BuildPipeline.BuildAssetBundle,

    BuildPipeline.BuildStreamedSceneAssetBundle 

    BuildPipeline.BuildAssetBundleExplicitAssetNames.

    • BuildPipeline.BuildAssetBundle allows you to build AssetBundles of any type of asset.
          可以构建任意类型资源的资源包。【创建一个压缩好的包含Assets下的所有资源文件.unity3d。可以包含是项目目录下的任意资源,而把所有的资源压缩成一个.unity3d的文件,这个文件包括所有的预置物体(prefabs),纹理贴图(textures),模型,动画。使用AssetBundle.mainAsset这个函数可以很方便的让你指定一个定义好的物体。被压缩的资源储存在pathName. Options,会自动的允许用户包含相关的或者需要用到的】
    • BuildPipeline.BuildStreamedSceneAssetBundle is used when you want to include only scenes to be streamed and loaded as the data becomes available.
           用来当你希望只包括流场景,使数据加载变为可用。【建立一个或多个场景,这些场景所需要的所有资源将被压缩入资源包,即asset bundle里面。资源包中的场景文件可以在任何平台上建立,而且这些文件往往是以一个单一的unity3d文件格式被用来创建。使用WWW类可以下载场景文件。当场景文件被下载好可以使用WWW.LoadFromCacheOrDownload来加载下载好的场景文件。】
    • BuildPipeline.BuildAssetBundleExplicitAssetNames is the same as BuildPipeline.BuildAssetBundle but has an extra parameter to specify a custom string identifier (name) for each object.
           BuildPipeline.BuildAssetBundle类似,但是有额外的参数来指定每个物体的自定义的字符串(名字)。【建立一个自定义名字的资源包方法:创建一个包含所有资源的一个压缩好的unity3d文件。AssetBundle可以包括任何项目目录下的资源文件。在assetNames参数中提供一个与资源数目相同大小的字符串数组。在资源数组中存储的信息与资源文件名相同,可以传递AssetBundle.Load去加载一个指定的资源。使用BuildAssetBundle时,只需使用资源的路径名。压缩好的资源包文件将会被储存在pathName. Options,允许用户自动包含与之相关的或者总是包含完整的资源去代替确切的参照物体。】

              当使用上面的三个函数做完准备工作,我们现在就需要去下载这些资源然后加载它们。

    3.    Downloading AssetBundles 下载资源包

    推荐使用WWW.LoadFromCacheOrDownload方法用来下载资源。当下载完成你就可以重新得到该资源的相关属性,例如:

    1. function Start ()  
    2. {  
    3.      var www = WWW.LoadFromCacheOrDownload ("http://myserver.com/myassetBundle.unity3d",   
    4. 5);  
    5. yield www;  
    6. if (www.error != null)  
    7. {  
    8.      Debug.Log (www.error);  
    9.      return;  
    10. }  
    11.     var myLoadedAssetBundle = www.assetBundle;  
    12.     var asset = myLoadedAssetBundle.mainAsset;  
    13. }  


     

    4.   Loading and unloading objects from an AssetBundle从资源包加载和卸载对象

            下载完以后,等于把硬盘或者网络的一个文件读到内存一个区域,这时候只是个AssetBundle内存镜像数据块,还没有Assets的概念。就可以使用这三个不同的函数来加载物体了:

     AssetBundle.Load

    AssetBundle.LoadAsync

     AssetBundle.LoadAll

    • AssetBundle.Load会加载物体,使用该物体的名字作为识别的参数。名字可以在Unity3d中Project view看到。你可以自由选择去传递对象变量的类型来确认该加载对象是否是被指定的类型。
    • AssetBundle.LoadAsync 与AssetBundle.Load 函数相类似,但是当资源加载时它不会阻碍主线程。如果同时要加载比较大的资源或者很多资源时,这个函数会比较有用,它可以避免程序的暂停,因为它会同步加载。
    • AssetBundle.LoadAll 顾名思义这个函数是用来加载所有在你资源包中的对象。作为AssetBundle.Load这个函数,你可以随意用该对象的类型去过滤。

            使用AssetBundle.Unload这个函数可以卸载加载好的资源,这个函数有一个布尔值的参数是用来告诉Unity是否要卸载所有的数据(包含加载的资源对象)或者只是已经下载过的被压缩好的资源数据。如果要在资源包中从你的应用程序要使用一些对象或者你想释放一些内存,可以传递false这个值来卸载已经压缩好了的文件从你的内存中(即.unity3d文件)。如果要完全卸载所有的资源数据,需要传递true这个值,这将会销毁所有的资源包器中加载的资源。

            AssetBundle.Unload(flase)是释放AssetBundle文件的内存镜像,不包含Load创建的Asset内存对象。

            AssetBundle.Unload(true)是释放那个AssetBundle文件内存镜像和并销毁所有用Load创建的Asset内存对象。

    5. Instantiating objects from AssetBundles 从资源包实例化物体

           下载了资源,也加载好了,那么就该在场景中使用Instantiate函数去实例化它了。

            Instantiate一个Prefab,是一个对Assets进行Clone(复制)+引用结合的过程,GameObject transform 是Clone是新生成的。其他mesh / texture / material / shader 等,这其中些是纯引用的关系的,包括:Texture和TerrainData,还有引用和复制同时存在的,包括:Mesh/material/PhysicMaterial。引用的Asset对象不会被复制,只是一个简单的指针指向已经Load的Asset对象。

    Unity里每个Script都是一个封闭的Class定义而已,并没有写调用代码,光Class的定义脚本是不会工作的。其实Unity引擎就是那个调用代码,Clone一个script asset等于new一个class实例,实例才会完成工作。把他挂到Unity主线程的调用链里去,Class实例里的OnUpdate OnStart等才会被执行。多个物体挂同一个脚本,其实就是在多个物体上挂了那个脚本类的多个实例而已,这样就好理解了。在new class这个过程中,数据区是复制的,代码区是共享的,算是一种特殊的复制+引用关系。

            当你Destroy一个实例时,只是释放那些Clone对象,并不会释放引用对象和Clone的数据源对象,Destroy并不知道是否还有别的object在引用那些对象。等到没有任何游戏场景物体在用这些Assets以后,这些assets就成了没有引用的游离数据块了,是UnusedAssets了,这时候就可以通过Resources.UnloadUnusedAssets来释放,Destroy不能完成这个任务,AssetBundle.Unload(false)也不行,AssetBundle.Unload(true)可以但不安全,除非你很清楚没有任何对象在用这些Assets了。

    1. string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";  
    2. IEnumerator Start () {  
    3.     // Start a download of the given URL  
    4.     // 开始从指定路径下载  
    5.     WWW www = WWW.LoadFromCacheOrDownload (url, 1);  
    6.     // Wait for download to complete  
    7.     // 等待下载完成  
    8.     yield return www;  
    9.     // Load and retrieve the AssetBundle  
    10.     // 加载并取回资源包  
    11.     AssetBundle bundle = www.assetBundle;  
    12.     // Load the TextAsset object  
    13.     // 加载文本资源对象  
    14.     GameObject go = bundle.Load("myGameObject", typeof(GameObject)) as GameObject;  
    15.     // Instantiate the GameObject  
    16.     // 实例化该对象  
    17.     Instantiate(go);  
    18. }  

            Unity不提供自动的一个可以取回所有被下载资源的列表。所以需要我们在脚本中要建立这些资源对象的信息和它们的路径以便我们去查找。

    6. Including scripts in AssetBundles 在资源包中包含脚本

           资源包可以作为TextAssets包含脚本但是不会实际执行代码。如果想要在资源包包含用来执行应用程序的代码,需要预先编译,然后使用Mono Reflection class来加载(注意:Reflection在iOS平台不可用)。可以在任何版本的C#IDE编辑器(如:Monodevelop, Visual Studio)或者使用mono/.net 文档编辑器。

    1. string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";  
    2. IEnumerator Start () {  
    3.     // Start a download of the given URL  
    4.     WWW www = WWW.LoadFromCacheOrDownload (url, 1);  
    5.     // Wait for download to complete  
    6.     yield return www;  
    7.     // Load and retrieve the AssetBundle  
    8.     AssetBundle bundle = www.assetBundle;  
    9.     // Load the TextAsset object  
    10.     TextAsset txt = bundle.Load("myBinaryAsText", typeof(TextAsset)) as TextAsset;  
    11.     // Load the assembly and get a type (class) from it  
    12.     var assembly = System.Reflection.Assembly.Load(txt.bytes);  
    13.     var type = assembly.GetType("MyClassDerivedFromMonoBehaviour");  
    14.     // Instantiate a GameObject and add a component with the loaded class  
    15.     GameObject go = new GameObject();  
    16.     go.AddComponent(type);  
    17. }  

    一个常见的错误:

             从某个AssetBundle里Load了一个prefab并克隆之:obj = Instantiate (AssetBundle1.Load('MyPrefab”);

              这个prefab比如是个npc,然后你不需要他的时候你用了:Destroy(obj);你以为就释放干净了。其实这时候只是释放了Clone对象,通过Load加载的所有引用、非引用Assets对象全都静静静的躺在内存里。这种情况应该在Destroy以后用:AssetBundle1.Unload(true),彻底释放干净。如果这个AssetBundle1是要反复读取的 不方便Unload,那可以在Destroy以后用:Resources.UnloadUnusedAssets()把所有和这个npc有关的Asset都销毁。

              当然如果这个NPC也是要频繁创建 销毁的那就应该让那些Assets呆在内存里以加速游戏体验。由此可以解释另一个之前有人提过的话题:为什么第一次Instantiate一个Prefab的时候都会卡一下,因为在你第一次Instantiate之前,相应的Asset对象还没有被创建,要加载系统内置的AssetBundle并创建Assets,第一次以后你虽然Destroy了,但Prefab的Assets对象都还在内存里,所以就很快了。

     

    资源加载和释放例子:

    从磁盘读取一个1.unity3d文件到内存并建立一个AssetBundle1对象

    AssetBundle AssetBundle1 = AssetBundle.CreateFromFile("1.unity3d");

    从AssetBundle1里读取并创建一个Texture Asset,把obj1的主贴图指向它

    obj1.renderer.material.mainTexture = AssetBundle1.Load("wall") as Texture;

    把obj2的主贴图也指向同一个Texture Asset

    obj2.renderer.material.mainTexture =obj1.renderer.material.mainTexture;

    Texture是引用对象,永远不会有自动复制的情况出现(除非你真需要,用代码自己实现copy),只会是创建和添加引用

    继续:

    AssetBundle1.Unload(true) 那obj1和obj2都变成黑的了,因为指向的Texture Asset没了

    如果:

    AssetBundle1.Unload(false) 那obj1和obj2不变,只是AssetBundle1的内存镜像释放

    继续:

    Destroy(obj1),//obj1被释放,但并不会释放刚才Load的Texture

    如果这时候:

    Resources.UnloadUnusedAssets();

    不会有任何内存释放 因为Texture asset还被obj2用着

    如果:

    Destroy(obj2)

    obj2被释放,但也不会释放刚才Load的Texture

    继续:

    Resources.UnloadUnusedAssets();

    这时候刚才load的Texture Asset释放了,因为没有任何引用了

    最后CG.Collect();

    强制立即释放内存。

     

    如何加载一堆大图片轮流显示又不爆掉?

    不考虑AssetBundle,直接用www读图片文件的话等于是直接创建了一个Texture Asset。

    1. TLlist<string> fileList;  
    2. int n=0;  
    3. IEnumerator OnClick()  
    4. {  
    5. WWW image = new www(fileList[n++]);  
    6. yield return image;  
    7. Texture tex = obj.mainTexture;  
    8. obj.mainTexture = image.texture;  
    9.    
    10. n = (n>=fileList.Length-1)?0:n;  
    11. Resources.UnloadAsset(tex);  
    12. }  


    文档下载地址:http://download.csdn.net/detail/tanmengwen/5262100

    展开全文
  • Unity 3D加载外部资源

    2014-09-28 12:33:14
    Unity 3D里有两种动态加载机制:  一是Resources.Load;  一是通过AssetBundle;  其实两者本质上没有什么区别。Resources.Load就是从一个缺省进程序包里的AssetBundle里加载资源,而一般AssetBundle文件...

    Unity 3D里有两种动态加载机制

         一是Resources.Load

         一是通过AssetBundle

         其实两者本质上没有什么区别。Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载资源,而一般AssetBundle文件需要你自己创建,运行时动态加载,可以指定路径和来源的。其实场景里所有静态的对象也有这么一个加载过程,只是Unity后台替你自动完成了。

    1.    AssetBundles是什么?

         在一些大型的网络游戏,或者加载比较多的一些场景时,如果要等待所有模型,贴图等各种资源文件加载完毕才能执行游戏,对用户将会是一个很头大的事情。所以就需要用到动态加载,即AssetBundles。比如玩家在进入游戏时先加载一些周围的场景文件,这样不仅可以提高速度还可以减少内存资源的消耗。       

         AssetBundles是可以把unity3d中你所创建的文件或任何资源导出的一种文件格式,这些文件导出后使用的是一种特定的文件格式(.Unity3d),这些特定格式的文件能在需要的时候加载到场景中。而这些特定的文件格式可以是模型,贴图,声音文件甚至是场景文件,它们是先前就被设计好的文件,所以很容易就可以被下载到你所建立的游戏或场景中来

         AssetBundles 可以是任意类型的文件只要是unity3d能识别的资源文件格式,识别主要是以文件扩展名为准,比如.prefab等等。当然如果你想包含自定义的二进制文件,需要命名这些文件为以".bytes"为后缀,Unity将会把这些文件导成TextAssets

    2.    Creating AssetBundles 创建资源包

    有三个类方法可以用来构建资源包:

    BuildPipeline.BuildAssetBundle,

    BuildPipeline.BuildStreamedSceneAssetBundle 

    BuildPipeline.BuildAssetBundleExplicitAssetNames.

    • BuildPipeline.BuildAssetBundle allows you to build AssetBundles of any type of asset.
          可以构建任意类型资源的资源包。【创建一个压缩好的包含Assets下的所有资源文件.unity3d。可以包含是项目目录下的任意资源,而把所有的资源压缩成一个.unity3d的文件,这个文件包括所有的预置物体(prefabs),纹理贴图(textures),模型,动画。使用AssetBundle.mainAsset这个函数可以很方便的让你指定一个定义好的物体。被压缩的资源储存在pathName. Options,会自动的允许用户包含相关的或者需要用到的】
    • BuildPipeline.BuildStreamedSceneAssetBundle is used when you want to include only scenes to be streamed and loaded as the data becomes available.
           用来当你希望只包括流场景,使数据加载变为可用。【建立一个或多个场景,这些场景所需要的所有资源将被压缩入资源包,即asset bundle里面。资源包中的场景文件可以在任何平台上建立,而且这些文件往往是以一个单一的unity3d文件格式被用来创建。使用WWW类可以下载场景文件。当场景文件被下载好可以使用WWW.LoadFromCacheOrDownload来加载下载好的场景文件。】
    • BuildPipeline.BuildAssetBundleExplicitAssetNames is the same as BuildPipeline.BuildAssetBundle but has an extra parameter to specify a custom string identifier (name) for each object.
           BuildPipeline.BuildAssetBundle类似,但是有额外的参数来指定每个物体的自定义的字符串(名字)。【建立一个自定义名字的资源包方法:创建一个包含所有资源的一个压缩好的unity3d文件。AssetBundle可以包括任何项目目录下的资源文件。在assetNames参数中提供一个与资源数目相同大小的字符串数组。在资源数组中存储的信息与资源文件名相同,可以传递AssetBundle.Load去加载一个指定的资源。使用BuildAssetBundle时,只需使用资源的路径名。压缩好的资源包文件将会被储存在pathName. Options,允许用户自动包含与之相关的或者总是包含完整的资源去代替确切的参照物体。】

              当使用上面的三个函数做完准备工作,我们现在就需要去下载这些资源然后加载它们。

    3.    Downloading AssetBundles 下载资源包

    推荐使用WWW.LoadFromCacheOrDownload方法用来下载资源。当下载完成你就可以重新得到该资源的相关属性,例如:

    1. function Start ()  
    2. {  
    3.      var www = WWW.LoadFromCacheOrDownload ("http://myserver.com/myassetBundle.unity3d",   
    4. 5);  
    5. yield www;  
    6. if (www.error != null)  
    7. {  
    8.      Debug.Log (www.error);  
    9.      return;  
    10. }  
    11.     var myLoadedAssetBundle = www.assetBundle;  
    12.     var asset = myLoadedAssetBundle.mainAsset;  
    13. }  


     

    4.   Loading and unloading objects from an AssetBundle从资源包加载和卸载对象

            下载完以后,等于把硬盘或者网络的一个文件读到内存一个区域,这时候只是个AssetBundle内存镜像数据块,还没有Assets的概念。就可以使用这三个不同的函数来加载物体了:

     AssetBundle.Load

    AssetBundle.LoadAsync

     AssetBundle.LoadAll

    • AssetBundle.Load会加载物体,使用该物体的名字作为识别的参数。名字可以在Unity3d中Project view看到。你可以自由选择去传递对象变量的类型来确认该加载对象是否是被指定的类型。
    • AssetBundle.LoadAsync 与AssetBundle.Load 函数相类似,但是当资源加载时它不会阻碍主线程。如果同时要加载比较大的资源或者很多资源时,这个函数会比较有用,它可以避免程序的暂停,因为它会同步加载。
    • AssetBundle.LoadAll 顾名思义这个函数是用来加载所有在你资源包中的对象。作为AssetBundle.Load这个函数,你可以随意用该对象的类型去过滤。

            使用AssetBundle.Unload这个函数可以卸载加载好的资源,这个函数有一个布尔值的参数是用来告诉Unity是否要卸载所有的数据(包含加载的资源对象)或者只是已经下载过的被压缩好的资源数据。如果要在资源包中从你的应用程序要使用一些对象或者你想释放一些内存,可以传递false这个值来卸载已经压缩好了的文件从你的内存中(即.unity3d文件)。如果要完全卸载所有的资源数据,需要传递true这个值,这将会销毁所有的资源包器中加载的资源。

            AssetBundle.Unload(flase)是释放AssetBundle文件的内存镜像,不包含Load创建的Asset内存对象。

            AssetBundle.Unload(true)是释放那个AssetBundle文件内存镜像和并销毁所有用Load创建的Asset内存对象。

    5. Instantiating objects from AssetBundles 从资源包实例化物体

           下载了资源,也加载好了,那么就该在场景中使用Instantiate函数去实例化它了。

            Instantiate一个Prefab,是一个对Assets进行Clone(复制)+引用结合的过程,GameObject transform 是Clone是新生成的。其他mesh / texture / material / shader 等,这其中些是纯引用的关系的,包括:Texture和TerrainData,还有引用和复制同时存在的,包括:Mesh/material/PhysicMaterial。引用的Asset对象不会被复制,只是一个简单的指针指向已经Load的Asset对象。

    Unity里每个Script都是一个封闭的Class定义而已,并没有写调用代码,光Class的定义脚本是不会工作的。其实Unity引擎就是那个调用代码,Clone一个script asset等于new一个class实例,实例才会完成工作。把他挂到Unity主线程的调用链里去,Class实例里的OnUpdate OnStart等才会被执行。多个物体挂同一个脚本,其实就是在多个物体上挂了那个脚本类的多个实例而已,这样就好理解了。在new class这个过程中,数据区是复制的,代码区是共享的,算是一种特殊的复制+引用关系。

            当你Destroy一个实例时,只是释放那些Clone对象,并不会释放引用对象和Clone的数据源对象,Destroy并不知道是否还有别的object在引用那些对象。等到没有任何游戏场景物体在用这些Assets以后,这些assets就成了没有引用的游离数据块了,是UnusedAssets了,这时候就可以通过Resources.UnloadUnusedAssets来释放,Destroy不能完成这个任务,AssetBundle.Unload(false)也不行,AssetBundle.Unload(true)可以但不安全,除非你很清楚没有任何对象在用这些Assets了。

    1. string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";  
    2. IEnumerator Start () {  
    3.     // Start a download of the given URL  
    4.     // 开始从指定路径下载  
    5.     WWW www = WWW.LoadFromCacheOrDownload (url, 1);  
    6.     // Wait for download to complete  
    7.     // 等待下载完成  
    8.     yield return www;  
    9.     // Load and retrieve the AssetBundle  
    10.     // 加载并取回资源包  
    11.     AssetBundle bundle = www.assetBundle;  
    12.     // Load the TextAsset object  
    13.     // 加载文本资源对象  
    14.     GameObject go = bundle.Load("myGameObject", typeof(GameObject)) as GameObject;  
    15.     // Instantiate the GameObject  
    16.     // 实例化该对象  
    17.     Instantiate(go);  
    18. }  

            Unity不提供自动的一个可以取回所有被下载资源的列表。所以需要我们在脚本中要建立这些资源对象的信息和它们的路径以便我们去查找。

    6. Including scripts in AssetBundles 在资源包中包含脚本

           资源包可以作为TextAssets包含脚本但是不会实际执行代码。如果想要在资源包包含用来执行应用程序的代码,需要预先编译,然后使用Mono Reflection class来加载(注意:Reflection在iOS平台不可用)。可以在任何版本的C#IDE编辑器(如:Monodevelop, Visual Studio)或者使用mono/.net 文档编辑器。

    1. string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";  
    2. IEnumerator Start () {  
    3.     // Start a download of the given URL  
    4.     WWW www = WWW.LoadFromCacheOrDownload (url, 1);  
    5.     // Wait for download to complete  
    6.     yield return www;  
    7.     // Load and retrieve the AssetBundle  
    8.     AssetBundle bundle = www.assetBundle;  
    9.     // Load the TextAsset object  
    10.     TextAsset txt = bundle.Load("myBinaryAsText", typeof(TextAsset)) as TextAsset;  
    11.     // Load the assembly and get a type (class) from it  
    12.     var assembly = System.Reflection.Assembly.Load(txt.bytes);  
    13.     var type = assembly.GetType("MyClassDerivedFromMonoBehaviour");  
    14.     // Instantiate a GameObject and add a component with the loaded class  
    15.     GameObject go = new GameObject();  
    16.     go.AddComponent(type);  
    17. }  

    一个常见的错误:

             从某个AssetBundle里Load了一个prefab并克隆之:obj = Instantiate (AssetBundle1.Load('MyPrefab”);

              这个prefab比如是个npc,然后你不需要他的时候你用了:Destroy(obj);你以为就释放干净了。其实这时候只是释放了Clone对象,通过Load加载的所有引用、非引用Assets对象全都静静静的躺在内存里。这种情况应该在Destroy以后用:AssetBundle1.Unload(true),彻底释放干净。如果这个AssetBundle1是要反复读取的 不方便Unload,那可以在Destroy以后用:Resources.UnloadUnusedAssets()把所有和这个npc有关的Asset都销毁。

              当然如果这个NPC也是要频繁创建 销毁的那就应该让那些Assets呆在内存里以加速游戏体验。由此可以解释另一个之前有人提过的话题:为什么第一次Instantiate一个Prefab的时候都会卡一下,因为在你第一次Instantiate之前,相应的Asset对象还没有被创建,要加载系统内置的AssetBundle并创建Assets,第一次以后你虽然Destroy了,但Prefab的Assets对象都还在内存里,所以就很快了。

     

    资源加载和释放例子:

    从磁盘读取一个1.unity3d文件到内存并建立一个AssetBundle1对象

    AssetBundle AssetBundle1 = AssetBundle.CreateFromFile("1.unity3d");

    从AssetBundle1里读取并创建一个Texture Asset,把obj1的主贴图指向它

    obj1.renderer.material.mainTexture = AssetBundle1.Load("wall") as Texture;

    把obj2的主贴图也指向同一个Texture Asset

    obj2.renderer.material.mainTexture =obj1.renderer.material.mainTexture;

    Texture是引用对象,永远不会有自动复制的情况出现(除非你真需要,用代码自己实现copy),只会是创建和添加引用

    继续:

    AssetBundle1.Unload(true) 那obj1和obj2都变成黑的了,因为指向的Texture Asset没了

    如果:

    AssetBundle1.Unload(false) 那obj1和obj2不变,只是AssetBundle1的内存镜像释放

    继续:

    Destroy(obj1),//obj1被释放,但并不会释放刚才Load的Texture

    如果这时候:

    Resources.UnloadUnusedAssets();

    不会有任何内存释放 因为Texture asset还被obj2用着

    如果:

    Destroy(obj2)

    obj2被释放,但也不会释放刚才Load的Texture

    继续:

    Resources.UnloadUnusedAssets();

    这时候刚才load的Texture Asset释放了,因为没有任何引用了

    最后CG.Collect();

    强制立即释放内存。

     

    如何加载一堆大图片轮流显示又不爆掉?

    不考虑AssetBundle,直接用www读图片文件的话等于是直接创建了一个Texture Asset。

    1. TLlist<string> fileList;  
    2. int n=0;  
    3. IEnumerator OnClick()  
    4. {  
    5. WWW image = new www(fileList[n++]);  
    6. yield return image;  
    7. Texture tex = obj.mainTexture;  
    8. obj.mainTexture = image.texture;  
    9.    
    10. n = (n>=fileList.Length-1)?0:n;  
    11. Resources.UnloadAsset(tex);  
    12. }  


    文档下载地址:http://download.csdn.net/detail/tanmengwen/5262100

    展开全文
  • Unity 3D里有两种动态加载机制:  一是Resources.Load;  一是通过AssetBundle;  其实两者本质上没有什么区别。Resources.Load就是从一个缺省进程序包里的AssetBundle里加载资源,而一般AssetBundle文件...
  • unity2018 package manager引入本地包Demo,通过修改配置文件即可完成对本地包的导入,详见demo
  • 项目需要实现第三方分享,于是选择了ShareSDK。下面总结一下从零到一的实现步骤,实现过程中也遇到了很多坑,用了一天终于把这些坑都填平了。...下载完了解压之后得到的资源如下:ShareSDK的导入在unity3D中新建
  • Unity 3D里有两种动态加载机制: 一是Resources.Load; 一是通过AssetBundle; 其实两者本质上没有什么区别。Resources.Load就是从一个缺省进程序包里的AssetBundle里加载资源,而一般AssetBundle文件需要你...
  • 新版下载地址:http://unity3d.com/unity/download Unity3.5是一次较大的更新.它包含的新功能和改进会让你爱不释手. Shuriken粒子系统 内建寻路系统 升级遮挡裁切和增加LOD系统 谷歌Chrome浏览器的Nat
  • 之前曾经写了一篇博客介绍Unity5的AssetBundle,结果似乎很受关注。不过似乎很多人看了之后都不懂,主要是因为不太明白AssetBundle是什么,它的依赖关系和结构是什么的,就直接想拿代码去用,而导致了很多人说看不懂...
  • Unity 3D里有两种动态加载机制:  一是Resources.Load;  一是通过AssetBundle;  其实两者本质上没有什么区别。Resources.Load就是从一个缺省进程序包里的AssetBundle里加载资源,而一般AssetBundle文件...
  • ====================...[脚本]制作unity3d动态加载资源文件*.unity3d   1、在unity3d项目(Project)面板的Editor目录下,新建C# script,取名为ExportAssetBundles,  2、复制unity3d的帮
  • Unity中进行调用 写在前面 前段时间在登录vivo开放平台时,看见官方发公告了,以后逐渐要禁止获取IMEI,使用OAID(匿名设备标识符)来替代IMEI在app的作用(另外我们也可以获取VAID和AAID,下文会提到),所以...
  • Unity Asset Bundle 基础

    2019-04-27 13:58:53
    一般标签创建规则为:文件名+unity3d/ab/assetbundle 后缀。资源有了标签之后,等会我们在代码中调用AB包的API时,unity就会在整个项目资源文件里面查找拥有标签需要打包的文件,并根据标签出ab包。注意:...
  • 【因为学习,所以翻译!】   1.介绍 LuaInterface 是 Lua 语言和 Microsoft.NET 平台公共语言运行时 (CLR) 之间的集成库。很多语言已经有面向 CLR 编译器和 CLR 实现,已经存在为微软windows、 BSD 操作系统和 ...
1 2
收藏数 33
精华内容 13
关键字:

unity3d 打包包名错误