首先了解一下Unity在进行AssetBundle打包时的几种构建方式:
- BuildAssetBundleOptions.None:默认构建AssetBundle的方式。使用LZMA算法压缩,此算法压缩包小,但是加载时间长,而且使用之前必须要整体解压。解压以后,这个包又会使用LZ4算法重新压缩,这样这种包就不要对其整体解压了。(也就是第一次解压很慢,之后就变快了。
- BuildAssetBundleOptions.UncompressedAssetBundle:不压缩数据,包大,但是加载很快。
- BuildAssetBundleOptions.ChunkBaseCompression:使用LZ4算法压缩,压缩率没有LZMA高,但是加载资源不必整体解压。
而在安卓手机上加载AssetBundle中的视频资源时的报错就是由于unity在打包AssetBundle时对视频资源进行了压缩。
AndroidVideoMedia::OpenExtractor could not translate archive:/CAB-78qwdyh8739dh8uf02332dd686137/CAB-5b4cd5489dv87h2s93r7de1548fr7.resource to local file. Make sure file exists, is on disk (not in memory) and not compressed.
AndroidVideoMedia: Error opening extractor: -10004
解决方案一:对视频资源打包时不进行压缩,采用
BuildPipeline.BuildAssetBundles(…, BuildAssetBundleOptions. UncompressedAssetBundle,.. );
假如视频资源较大会导致游戏热更时需要下载的资源包体积也较大。
解决方案二:视频资源放服务器,在游戏中用代码动态下载视频到本地播放。
UIPlayVideo.lua.txt
local Parent = require("Manager/XYObj")
local CLASSNAME = "UIPlayVideo"
local CurObj = class(CLASSNAME,Parent)
local UiLayerConf = require "Manager/UiLayerConf"
local LoadVideoTool = require "Tool/LoadVideoTool"
function CurObj:ctor(CLASSNAME,CSharpObj)
CurObj.super.ctor(self,CLASSNAME,CSharpObj)
self.m_bUiLayerType = UiLayerConf.ui_type_dlg
end
--初始化
function CurObj:OnInit()
btnClose.onClick:AddListener(function ()
self:playVideoFun(videoConst.stop)
ObjMgr:CloseUI("UIPlayVideo")
end)
end
--每次展示执行一次
function CurObj:OnShow()
print("播放界面展示---")
self:playVideoFun(videoConst.play)
btnClose.gameObject:SetActive(false)
self:invoke(function ()
btnClose.gameObject:SetActive(true)
end , 5)
self:invoke(function ()
ObjMgr:CloseUI("UIPlayVideo")
end , 23)
end
function CurObj:playVideoFun(state)
if state == videoConst.play then
local url = "video_url_temp"
objVideoCom.url = url
local succCallback = function(args)
objVideoCom.url = args
objVideoCom:Play()
end
local failCallback = function(...)
ObjMgr:ShowTips("播放失败")
end
LoadVideoTool:LoadVideoUrl(url,succCallback,failCallback)
else
objVideoCom:Stop()
end
end
videoConst = {
play = 1,
stop = 2
}
LoadVideoTool.lua.txt
local LoadVideoTool={}
local cs_coroutine = require "XLua/Common/cs_coroutine"
local crypt = require "crypt"
local UnityWebRequest = CS.UnityEngine.Networking.UnityWebRequest
local File=CS.System.IO.File
local FuncEncodeURI
local FuncGetPlatformPath
local path
function LoadVideoTool:LoadVideoUrl(url,succCallback,failCallback)
if not url or url == "" then
print("error:输入的URL错误!")
LoadFailCall(failCallback)
return
end
if not path then
path = FuncGetPlatformPath()
end
local urlEncode = FuncEncodeURI(url)
urlEncode = path .. "/" .. urlEncode..".mp4"
if File.Exists(urlEncode) then
-- 从本地加载
--print("----------本地加载------------",url,urlEncode)
if succCallback then
succCallback(urlEncode)
end
else
--按网址下载
--print("----------网上加载------------")
cs_coroutine.start(function ()
local webRequest = UnityWebRequest.Get(url)
webRequest.method = UnityWebRequest.kHttpVerbGET
coroutine.yield(webRequest:SendWebRequest())
if (not webRequest.isNetworkError and webRequest.responseCode == 200) then
File.WriteAllBytes(urlEncode,webRequest.downloadHandler.data)
if succCallback then
succCallback(urlEncode)
end
else
print("errorVideo : ",webRequest.error)
LoadFailCall(failCallback)
end
end)
end
end
-- 加载失败设置
LoadFailCall = function(failCallback)
if failCallback then
failCallback()
end
end
--- 根据平台 获取 路径
FuncGetPlatformPath = function()
return CS.UnityEngine.Application.temporaryCachePath
end
--- 网址中的特殊字符转换
FuncEncodeURI = function (s)
return crypt.base64encode(s)
end
return LoadVideoTool