点关注不迷路,持续输出Unity
干货文章。
嗨,大家好,我是新发。
最近项目上架Google Play
,因为Google
限制上传的APK
不得超过150M
,而实际项目APK
有300M+
,这个时候,就需要用到Unity
的Split Application Binary
功能了。
为了演示,我弄个Demo
工程,如下:
Resources
目录和StreamingAssets
目录分别放一张图片。
场景如下,Canvas
节点挂Main.cs
脚本,image
节点显示图片。
场景中的image
节点不要引用图片资源,而是在Main.cs
脚本中动态赋值。
Main.cs
脚本代码如下:
using UnityEngine;
using UnityEngine.UI;
public class Main : MonoBehaviour {
public Image img;
void Start() {
img.sprite = Resources.Load<Sprite>("bg");
}
}
运行效果如下,可以看到动态加载了图片。
此时我们打包apk
,如果我们不开启Split Application Binary
,显然,Resources
和StreamingAssets
目录都会打进包内。
关于
Resources
和StreamingAssets
两个目录的区别,可以参见我之前写的这篇文章:《学Unity的猫》——第五章:规范Unity的工程目录结构
在Player Settings
的Publishing Settings
中开启Split Application Binary
。
执行Build
打包,如下,保存为test.apk
。
最终生成的文件如下,可以看到有一个apk
和一个obb
文件。
obb
全称是Opaque Binary Blob
,它是apk
的扩展文件,它是压缩文件的格式,以zip格式居多,所以我们可以直接用7z
打开它,我们看看里面有什么。
进去里面是一个assets
文件夹,从这里看,我们就可以知道obb
主要是存放apk
的资源和数据类文件了。
往里进,看到了pic2.png
,这个就是Unity
中StreamingAssets
目录中的pic2.png
,也就是说,StreamingAssets
目录中的文件,会被丢到obb
文件中。
那Resources
目录的资源,也是在obb
中 吗?我们往里进,可以看到在assets\bin\Data
目录中有个data.unity3d
文件,我猜,我们Resources
目录中的那张bg.png
就在这里面。
我用AssetStudioGUI.exe
无法反出这个data.unity3d
文件,那么,我们就用反证法来证明Resources
目录文件会在obb
文件中吧。
我们把apk
安装到安卓模拟器中,运行如下,可以看到,不能动态加载出图片来,说明,Resources
目录的bg.png
并不在apk
中。
现在,另一个问题来了,这个obb
文件,如何使用,放在安卓中的哪个目录呢?
要使用这个obb
文件,需要先重命名一下这个obb
文件,命名规则如下:main.
我打包apk
时,包名是com.linxinfa.obbtest
,Bundle Version Code
是2
。
所以最终obb
重命名如下:main.2.com.linxinfa.obbtest.obb
把它拷贝到Android/obb/包名
目录下,如下:
接着,我们运行apk
,发现闪退了,为什么?
用adb
调试一下,日志如下:
D/Activity( 6326): on create, cpu abi: armeabi-v7a, brand: Android
D/updatePackage( 905): version com.linxinfa.obbtest 2
I/Launcher( 905): Deferring update until onResume
V/libnb ( 6326): enter native_bridge2_isSupported /data/app/com.linxinfa.obbtest-1/lib/arm/libmain.so
D/libnb ( 6326): enter native_bridge2_loadLibrary /data/app/com.linxinfa.obbtest-1/lib/arm/libmain.so
D/com.netease.nemu_vapi_android.thread.HttpServer( 842): http server response data: {"errcode":0,"message":"OK"}
D/houdini ( 6326): [6326] Added shared library /system/lib/arm/libaudio_rawdata.so for ClassLoader by Native Bridge.
D/houdini ( 6326): [6326] Added shared library /data/app/com.linxinfa.obbtest-1/lib/arm/libmain.so for ClassLoader by Native Bridge.
V/libnb ( 6326): enter native_bridge2_getTrampoline JNI_OnLoad
D/com.netease.nemu_vapi_android.thread.HttpServer( 842): http server response data: {"errcode":0,"message":"OK"}
I/Mono ( 6326): JNI_OnLoad called
D/com.netease.nemu_android_watchdog_lib.core.Watchdog( 842): upload server response: {"errcode": 100, "errmsg": "ok"}
D/com.netease.nemu_android_watchdog_lib.core.Watchdog( 842): upload result: true
D/ ( 6326): QemuPipeStream get vt: 1
D/ ( 6326): QemuPipeStream use_vt: 1
D/ ( 6326): HostConnection::get() New Host Connection established 0xbf269540, tid 6326 host arch 0
I/ActivityManager( 523): Displayed com.linxinfa.obbtest/com.unity3d.player.UnityPlayerActivity: +285ms
W/InputMethodManagerService( 523): Starting input on non-focused client com.android.internal.view.IInputMethodClient$Stub$Proxy@17cc531 (uid=10015 pid=3699)
I/Unity ( 6326): MemoryManager: Using 'Dynamic Heap' Allocator.
I/Unity ( 6326): check apk path fail, reported:/storage/emulated/0/Android/obb/com.linxinfa.obbtest/main.2.com.linxinfa.obbtest.obb, actual:/data/app/com.linxinfa.obbtest-1/base.apk
I/Unity ( 6326):
I/Unity ( 6326): Illegal usage of unity detected, shutdown unity.
I/Unity ( 6326):
I/Process ( 6326): Sending signal. PID: 6326 SIG: 9
W/InputDispatcher( 523): channel 'aede570 com.linxinfa.obbtest/com.unity3d.player.UnityPlayerActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x9
E/InputDispatcher( 523): channel 'aede570 com.linxinfa.obbtest/com.unity3d.player.UnityPlayerActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
I/WindowState( 523): WIN DEATH: Window{aede570 u0 com.linxinfa.obbtest/com.unity3d.player.UnityPlayerActivity}
W/InputDispatcher( 523): Attempted to unregister already unregistered input channel 'aede570 com.linxinfa.obbtest/com.unity3d.player.UnityPlayerActivity (server)'
W/WindowManager( 523): Force-removing child win Window{8bc567a u0 SurfaceView} from container Window{aede570 u0 com.linxinfa.obbtest/com.unity3d.player.UnityPlayerActivity}
I/ActivityManager( 523): Process com.linxinfa.obbtest (pid 6326) has died
D/ActivityManager( 523): cleanUpApplicationRecord -- 6326
W/ActivityManager( 523): Force removing ActivityRecord{50e4779 u0 com.linxinfa.obbtest/com.unity3d.player.UnityPlayerActivity t547}: app died, no saved state
W/WindowManager( 523): Failed looking up window
W/WindowManager( 523): java.lang.IllegalArgumentException: Requested window android.os.BinderProxy@7d300e9 does not exist
W/WindowManager( 523): at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:8881)
W/WindowManager( 523): at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:8872)
W/WindowManager( 523): at com.android.server.wm.WindowState$DeathRecipient.binderDied(WindowState.java:1216)
W/WindowManager( 523): at android.os.BinderProxy.sendDeathNotice(Binder.java:558)
I/WindowState( 523): WIN DEATH: null
I/com.android.server.tabs.TabManagerService( 523): notifyClosing:741: notify tab closed in android as it's closed task com.linxinfa.obbtest, taskId: 547, elapseTime: 372
D/Interception( 523): result: allow, reason: calleePkg is system app, rule: runType===broadcast|||callerPkg===android|||calleePkg===com.mumu.acc|||calleeClass===com.mumu.acc.AccMsgReceiver|||action===uu.intent.action.STOP_ACCELERATE
在同事的提醒下,看到有一句关键的日志:
Illegal usage of unity detected, shutdown unity.
搜索了一下,原来如此:
我们在国内下载Unity
一般是在 https://unity.cn/ 下载,这里下的,都是中国版的。
那么,在哪里下载国际版的Unity
呢?
国际版Unity
官网:https://unity.com/ (需要科学上网)
最终,使用国际版打出了apk+obb
包,
按照同样的规则放好obb
包,
运行apk
,可以看到运行正常了。
由此,我们得出结论,Resources
目录的资源也是在obb
文件中。
完毕。
喜欢Unity
的同学,不要忘记点击关注,如果有什么Unity
相关的技术难题,也欢迎留言或私信~