您的位置:首页 > 其它

【UGF】(三)Resource模块的使用及资源热更新

2018-02-05 14:46 585 查看
ResourceComponent有两种Resource Mode: Package(单机模式),Updatable(可更新模式)

一.Resource Mode: Package(单机模式)

单机模式:资源打包后将AssetBundle Builder生成的Package下对应平台文件夹下的资源直接复制到StreamingAssets,资源随游戏一起打包
举个栗子:①设置ResourceComponent的Resource Mode为Package(单机模式)
②将AssetBundle Builder生成的Package下对应平台的文件复制到StreamingAssets
③使用UGF.Resource.InitResources()初始化资源,在ResourceInitComplete时就可以使用资源了。
using GameFramework;
using GameFramework.Fsm;
using GameFramework.Procedure;
using UnityGameFramework.Runtime;
using GameFramework.Event;
public class LaunchProcedure : ProcedureBase
{
private bool isLoadSceneSuccess = false;
protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
{
base.OnEnter(procedureOwner);
Log.Info("LaunchProcedure Enter...");
UGF.Event.Subscribe(LoadSceneSuccessEventArgs.EventId, OnLoadSceneSuccess);
UGF.Event.Subscribe(ResourceInitCompleteEventArgs.EventId, OnResourceInitComplete);
UGF.Resource.InitResources();
}

protected override void OnUpdate(IFsm<IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
if (isLoadSceneSuccess)
ChangeState<MainMenuProcedure>(procedureOwner);//场景加载成功,切换流程
}
protected override void OnLeave(IFsm<IProcedureManager> procedureOwner, bool isShutdown)
{
base.OnLeave(procedureOwner, isShutdown);
UGF.Event.Unsubscribe(LoadSceneSuccessEventArgs.EventId, OnLoadSceneSuccess);
UGF.Event.Unsubscribe(ResourceInitCompleteEventArgs.EventId, OnResourceInitComplete);
}

private void OnLoadSceneSuccess(object sender, GameEventArgs e)
{
var ne = (LoadSceneSuccessEventArgs)e;
Log.Info("场景{0}加载成功", ne.SceneAssetName);
isLoadSceneSuccess = true;
}
private void OnResourceInitComplete(object sender, GameEventArgs e)
{
//AssetBundle资源初始化完成,从AssetBundle中加载场景
Log.Info("OnResourceInitComplete...");
UGF.Scene.LoadScene("Assets/GameMain/Scenes/MainMenu.unity");
}
}

二.Resource Mode:Updatable(可更新模式)

资源热更流程图:



AssetBundle Tools的使用中介绍过,Output FullPath是可更新模式生成的完整文件包的目录,需要将此目录放到服务器供客户端资源更新。

1.向服务端发送WebRequest请求获取最新的版本数据:

需要将最新游戏版本号、最新资源版本号/下载地址/资源大小/HashCode等信息,例如:
{
"LatestGameVersion": "1.2",//最新游戏版本号
"ApplicableGameVersion": [ "1.0", "1.1", "1.2" ],//最新资源适用的游戏版本号
"LatestInternalResourceVersion": 1,//最新资源版本号,数值由AB Builder生成,在GameResourceVersion.xml中
"ResourceUpdateUrl": "http://localhost/Full",//资源地址
"ResourceLength": 331,
"ResourceHashCode": -2073543694,
"ResourceZipLength": 211,
"ResourceZipHashCode": 371407597
}AssetBundle Builder打包资源后会在用户设置的Output Directory下生成GameResourceVersion.xml文件,此文件中记录了版本文件的校验码(HashCode),在做资源更新服务的时候会用到这些值。将对应数据写入文件,然后将文件放到服务器,由客户端通过WebRequest获取最新app版本信息及资源信息。

需要订阅WebRequestSuccessEventArgs事件,在WebRequest成功后再调用CheckVersionList进行版本资源列表检查

2.CheckVersionList检查版本资源列表(version.dat)是否有更新

该函数需要传入LatestInternalResourceVersion值,跟当前本地资源版本进行比较判断是否需要更新

3.UpdateVersionList更新资源列表

此过程更新的是version.dat文件,打开Full文件夹下的资源可以看到资源名后面都接了校验码,该函数需要传入ResourceLength,ResourceHashCode, ResourceZipLength, ResourceZipHashCode,其中HashCode用来产生对应的文件名。如果HashCode填错就会因服务端没有对应文件而导致请求超时。该函数需要订阅VersionListUpdateSuccessEventArgs事件,更新资源列表成功后调用CheckResources检测资源

4.CheckResources检查是否有资源需要更新

根据version.dat检查是否有可更新资源,ResourceCheckCompleteEventArgs.UpdateCount表示需要更新的资源个数,大于0表示需要更新。该函数需要订阅ResourceCheckCompleteEventArgs事件,资源检测完成后根据是否有可更新资源决定是否调用UpdateResources下载资源

5.UpdateResources从服务器更新资源

CheckResources成功后,开始从服务器下载需要更新的资源。该函数可以注册的回调事件:
ResourceUpdateStartEventArgs:开始下载文件时调用,每个文件调用一次
ResourceUpdateFailureEventArgs:文件下载失败时调用
ResourceUpdateSuccessEventArgs:文件下载完成时调用
ResourceUpdateAllCompleteEventArgs:所有文件下载完成时调用
ResourceUpdateChangedEventArgs:下载进度改变时调用, 可以获取当前已下载的大小

资源热更新示例代码:

CheckVersionProcedure:
using System;
using UnityEngine;
using GameFramework;
using GameFramework.Fsm;
using GameFramework.Procedure;
using GameFramework.Event;
using UnityGameFramework.Runtime;
namespace ShadowTank
{
[Serializable]
public class VersionInfo
{
public string LatestGameVersion;
public string[] ApplicableGameVersion;
public int LatestInternalResourceVersion;
public string ResourceUpdateUrl;
public int ResourceLength;
public int ResourceHashCode;
public int ResourceZipLength;
public int ResourceZipHashCode;
}
public class CheckVersioProcedure : ProcedureBase
{
private bool mUpdateVerListCompleted = false;
private VersionInfo mVersionInfo = null;
protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
{
base.OnEnter(procedureOwner);
Log.Info("CheckVersionProcedure Enter...");
UGF.Event.Subscribe(WebRequestSuccessEventArgs.EventId, OnWebRequestSuccess);
UGF.Event.Subscribe(VersionListUpdateSuccessEventArgs.EventId, OnVersionListUpdateSuccess);
UGF.WebRequest.AddWebRequest("http://localhost/version.json");
}
protected override void OnUpdate(IFsm<IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
if (mUpdateVerListCompleted)
ChangeState<UpdateResourcesProcedure>(procedureOwner);
}
private void OnWebRequestSuccess(object sender, GameEventArgs eventArgs)
{
var e = (WebRequestSuccessEventArgs)eventArgs;
mVersionInfo = Utility.Json.ToObject<VersionInfo>(e.GetWebResponseBytes());
Log.Info("CurrentGameVersion:{0},LatestGameVersion:{1}", Application.version,mVersionInfo.LatestGameVersion);
Version currentVer = new Version(Application.version);
Version latestVer = new Version(mVersionInfo.LatestGameVersion);
if(latestVer.CompareTo(currentVer)>0)
{
Log.Info("游戏有新版本");
}
UGF.Resource.UpdatePrefixUri = Utility.Path.GetCombinePath(mVersionInfo.ResourceUpdateUrl, GetResourceVersion(),GetOSName());
Log.Info(UGF.Resource.UpdatePrefixUri);
if (UGF.Resource.CheckVersionList(mVersionInfo.LatestInternalResourceVersion)==GameFramework.Resource.CheckVersionListResult.Updated)
{
Log.Info("version.dat已是最新");
mUpdateVerListCompleted = true;
return;
}
//更新Version.dat
UGF.Resource.UpdateVersionList(mVersionInfo.ResourceLength, mVersionInfo.ResourceHashCode, mVersionInfo.ResourceZipLength, mVersionInfo.ResourceZipHashCode);
}
private void OnVersionListUpdateSuccess(object sender, GameEventArgs e)
{
Log.Info("version.dat更新完成!");
mUpdateVerListCompleted = true;
}

private string GetResourceVersion()
{
var versionStr = Application.version.Replace('.', '_');
return string.Format("{0}_{1}", versionStr, mVersionInfo.LatestInternalResourceVersion);
}
//获取操作系统名
private string GetOSName()
{
string platformName = string.Empty;
if (Application.platform == RuntimePlatform.Android)
platformName = "android";
else if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer)
platformName = "windows";
else if (Application.platform == RuntimePlatform.IPhonePlayer)
platformName = "ios";
else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer)
platformName = "osx";
return platformName;
}
}
}
UpdateResourceProcedure:
using GameFramework;
using GameFramework.Fsm;
using GameFramework.Procedure;
using GameFramework.Event;
using UnityGameFramework.Runtime;
namespace ShadowTank
{
public class UpdateResourcesProcedure : ProcedureBase
{
private bool mResourceUpdateAllComplete = false;
protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
{
base.OnEnter(procedureOwner);
Log.Info("UpdateResourcesProcedure Enter...");
UGF.Event.Subscribe(ResourceCheckCompleteEventArgs.EventId, OnResourceCheckComplete);
UGF.Event.Subscribe(ResourceUpdateSuccessEventArgs.EventId, OnResourceUpdateSuccess);
UGF.Event.Subscribe(ResourceUpdateAllCompleteEventArgs.EventId, OnResourceUpdateAllComplete);
UGF.Resource.CheckResources();
}
protected override void OnUpdate(IFsm<IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);

//更新完成,切换到MainMenu场景
if (mResourceUpdateAllComplete)
ChangeState<MainMenuProcedure>(procedureOwner);
}
private void OnResourceCheckComplete(object sender, GameEventArgs e)
{
var checkInfo = (ResourceCheckCompleteEventArgs)e;
Log.Info("OnResourceCheckComplete,需要更新{0}个资源...", checkInfo.UpdateCount);
if (checkInfo.UpdateCount <= 0)
{
//无可更新资源
mResourceUpdateAllComplete = true;
return;
}

//更新资源
UGF.Resource.UpdateResources();
}
private void OnResourceUpdateSuccess(object sender, GameEventArgs e)
{
var info = (ResourceUpdateSuccessEventArgs)e;
Log.Info("{0}下载完成...", info.Name);
}
private void OnResourceUpdateAllComplete(object sender, GameEventArgs e)
{
mResourceUpdateAllComplete = true;
Log.Info("资源全部更新完成!");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐