unity3D热更新——(2)Assetbundle资源更新部分

///
///通过tomcat服务器进行下载ab包

///

using System;
using System. Collections;
using System. Collections. Generic;
using System. IO;
using UnityEngine;

public class UpdateAssetBundles : MonoBehaviour
{
/// < summary >
/// 配表路径
/// </ summary >
List< string> mainPath;
/// < summary >
/// 配表信息
/// </ summary >
Dictionary< string, List< string>> tablePath;
/// < summary >
/// 进入游戏进行资产更新
/// </ summary >
public void FirstUpdateAB()
{
StartCoroutine( IEFirstUpdateAB());
}
IEnumerator IEFirstUpdateAB()
{
//进入游戏先检测persistent目录下是否有文件,没有则表示为第一次进游戏,
//需要将streaming目录下的文件拷贝到该目录下。
if (! Directory. Exists( AssetPath. persistentPath))
{
Debug. Log( "解压本地文件!(该步骤不需要流量)");
//注意,在Android中,StreamingAssets中的文件包含在一个.jar压缩文件(基本上与标准的zip为统一格式)中,所以只能用
//WWW读取,否则要使用第三方软件来读取,不能用C#的文件读取方法。
List< string> streamList = new List< string>();
yield return StartCoroutine( IECStomcat( AssetPath. streamingPath + "/" + IP. preloadedPath, streamList));
string tableStr = "";
for ( int i = 0; i < streamList. Count; i++)
{
tableStr += streamList[ i];
tableStr += Environment. NewLine;
string relativePath = "/" + streamList[ i]. Split( ';')[ 0];
yield return StartCoroutine( IEUpdateAssetBundle( Application. streamingAssetsPath + relativePath. Replace( ' \\ ', '/'), Application. persistentDataPath + relativePath. Replace( ' \\ ', '/')));
}
Debug. Log( "解压完成!");
CreadTextFile( AssetPath. persistentPath + "/" + IP. preloadedPath, tableStr);
yield return new WaitForSeconds( 0);
}
//获取主配表
Debug. Log( "获取服务器列表!(建议在WiFi下更新)");
mainPath = new List< string>();
yield return StartCoroutine( IECStomcat( IP. ResoucelsIP + AssetPath. _Android + "/" + IP. ResoucelsTablePath, mainPath));
Debug. Log( "检测是否需要更新!");
if ( mainPath != null)
{
tablePath = new Dictionary< string, List< string>>();
for ( int i = 0; i < mainPath. Count; i++)
{
List< string> list = new List< string>();
tablePath. Add( mainPath[ i], list);
yield return StartCoroutine( IECStomcat( IP. ResoucelsIP + mainPath[ i], list));
}
}
else
{
Debug. Log( "服务器更新失败!找不到主配置文件!");
}
List< string> updateTable = ContrastDetection( tablePath);
Debug. Log( "检测到有" + updateTable. Count + "个文件需要更新!");
yield return new WaitForSeconds( 0.5f);
if ( updateTable. Count > 0)
{
Debug. Log( "开始更新资源文件!");
for ( int i = 0; i < updateTable. Count; i++)
{
string serverPathAB = IP. ResoucelsIP + updateTable[ i]. Split( ';')[ 0];
string localPathAB = Application. persistentDataPath + "/" + updateTable[ i]. Split( ';')[ 0];
yield return StartCoroutine( IEUpdateAssetBundle( serverPathAB. Replace( ' \\ ', '/'), localPathAB. Replace( ' \\ ', '/')));
}
Debug. Log( "资源文件已更新完毕!");
Debug. Log( "开始更新配置文件!");
readText( tablePath);
yield return new WaitForSeconds( 0.5f);
Debug. Log( "配置文件已更新完成!");
}
Debug. Log( "进入游戏!");
}




/// < summary >
/// 在安卓平台下判断该条路径是否为 "jar:file"开头(返回true为是)
/// </ summary >
/// < returns ></ returns >
public bool jarFilePath( string path)
{
if ( Application. platform == RuntimePlatform. Android && path. Substring( 0, AssetPath. jarHead. Length) == AssetPath. jarHead)
{
return true;
}
return false;
}
/// < summary >
/// 判断该条路径是否为"http"开头(返回true为是)
/// </ summary >
/// < param name = "path" ></ param >
/// < returns ></ returns >
public bool httpPath( string path)
{
if ( path. Substring( 0, AssetPath. httpHead. Length) == AssetPath. httpHead)
{
return true;
}
return false;
}


/// < summary >
/// 获取配表,并把每行的信息写入列表中
/// </ summary >
/// < param name = "path" ></ param >
/// < returns ></ returns >
IEnumerator IECStomcat( string path, List< string> mainPath)
{
string[] pathAll;
if ( jarFilePath( path) || httpPath( path))
{
//这里有个问题,加了时间戳只有第一个链接能访问到
//if (httpPath(path))
//{
// string nn = DateTime.Now.Ticks.ToString();
// path = path + "?a=" + nn.Substring(nn.ToString().Length - 6);
//}
WWW www = new WWW( path);
yield return www;
if ( www. error != null)
{
Debug. Log( www. error+ " "+ path);
yield break;
}
pathAll = www. text. Split( Environment. NewLine. ToCharArray());
}
else
{
pathAll= File. ReadAllText( path). Split( Environment. NewLine. ToCharArray());
}
for ( int i = 0; i < pathAll. Length; i++)
{
if ( pathAll[ i] != "")
{
mainPath. Add( pathAll[ i]);
}
}
}
/// < summary >
/// 服务器配表与本地配表进行检测比对
/// </ summary >
/// < param name = "d" ></ param >
public List< string> ContrastDetection( Dictionary< string, List< string>> d)
{
string path = "";
List< string> listPath = new List< string>();
if ( Application. platform == RuntimePlatform. WindowsEditor)
{
path = Application. dataPath + "/" + AssetPath. StreamingAssets;
}
else if ( Application. platform == RuntimePlatform. Android || Application. platform == RuntimePlatform. IPhonePlayer)
{
path = Application. persistentDataPath;
}
//遍历配表
foreach ( var item in d)
{
string file = "";
string localPath = path + "/" + item. Key;
//检测本地配表是否存在
if ( File. Exists( localPath))
{
//本地有该配表就将路径进行比对添加到列表中
file = File. ReadAllText( localPath);
}
for ( int i = 0; i < item. Value. Count; i++)
{
if (! file. Contains( item. Value[ i]))
{
listPath. Add( item. Value[ i]);
}
}
}
return listPath;
}
/// < summary >
/// 从服务器上下载ab包到本地,(注意斜杠,一定要把所有的反斜杠转成斜杠)
/// </ summary >
/// < param name = "path" > 服务器路径 </ param >
/// < param name = "localPath" > 本地路径 </ param >
/// < returns ></ returns >
IEnumerator IEUpdateAssetBundle( string path, string localPath)
{
if ( httpPath( path))
{
string nn = DateTime. Now. Ticks. ToString();
path = path + "?" + nn. Substring( nn. ToString(). Length - 6);
}
WWW www = new WWW( path);
yield return www;
if ( www. error != null)
{
Debug. Log( "错误信息:" + www. error);
yield break;
}
else
{
string headLocalPath = pathRoundOff( localPath);
if (! Directory. Exists( headLocalPath))
{
Directory. CreateDirectory( headLocalPath);
}
if ( File. Exists( localPath))
{
File. Delete( localPath);
}
FileStream steam = File. Create( localPath);
steam. Close();
File. WriteAllBytes( localPath, www. bytes);
}
}
/// < summary >
/// 更新配表
/// </ summary >
/// < param name = "dateList" ></ param >
public void readText( Dictionary< string, List< string>> dateList)
{

string directoryPath = Application. persistentDataPath + "/" + AssetPath. _Android + "/" + AssetPath. ConfigurationFilesName;
//清除所有配表
if ( Directory. Exists( directoryPath))
Directory. Delete( directoryPath, true);
Directory. CreateDirectory( directoryPath);
//创建新的配表
foreach ( var item in dateList)
{
string loaclPath = Application. persistentDataPath + "/" + item. Key;
string str = "";
for ( int i = 0; i < item. Value. Count; i++)
{
str += item. Value[ i];
str += Environment. NewLine;
}
CreadTextFile( loaclPath, str);
}
}
/// < summary >
/// 创建文档文件
/// </ summary >
/// < param name = "path" ></ param >
/// < param name = "str" ></ param >
public void CreadTextFile( string path, string str)
{
string headPath = pathRoundOff( path);
if (! Directory. Exists( headPath))
Directory. CreateDirectory( headPath);
File. WriteAllText( path, str);
}

/// < summary >
/// 截取文件的文件夹路径
/// </ summary >
/// < param name = "path" ></ param >
/// < returns ></ returns >
public string pathRoundOff( string path)
{
string[] newPath = path. Split( ' \\ ');
if ( newPath. Length <= 1)
{
newPath = path. Split( '/');
}
return path. Substring( 0, path. Length - newPath[ newPath. Length - 1]. Length - 1);
}
}

public class AssetPath
{
/// < summary >
/// 需要打包的文件夹路径
/// </ summary >
public static string OriginalPath = Application. dataPath + "/AssetBundleResources/Resources";
/// < summary >
/// 打包出来的文件夹路径
/// </ summary >
public const string StreamingAssetsPath = @"Assets/StreamingAssets";
/// < summary >
/// 配置文件夹
/// </ summary >
public const string ConfigurationFilesName = "configuration";
/// < summary >
/// 资源文件夹
/// </ summary >
public const string ResourcesFilesName = "resources";
/// < summary >
/// 资源文件后缀名
/// </ summary >
public const string unity3dSuffix = ".unity3d";
/// < summary >
/// .meta后缀名
/// </ summary >
public const string metaSuffix = ".meta";
/// < summary >
/// 打包目录
/// </ summary >
public const string StreamingAssets = "StreamingAssets";
/// < summary >
/// Android
/// </ summary >
public const string _Android = "Android";
/// < summary >
/// IPhonePlayer
/// </ summary >
public const string _IPhonePlayer = "IPhonePlayer";
/// < summary >
/// 移动端本地压缩包路径
/// </ summary >
public static string streamingPath = Application. streamingAssetsPath + "/" + Application. platform;
/// < summary >
/// 移动端资产放置路径
/// </ summary >
public static string persistentPath = Application. persistentDataPath + "/" + Application. platform;
/// < summary >
/// 预留物配表相对路径
/// </ summary >
public const string scheduledFileName = "/"+ ConfigurationFilesName+ "/prefad/scheduled.txt";
/// < summary >
/// "jar:file"
/// </ summary >
public const string jarHead = "jar:file";
/// < summary >
/// "http"
/// </ summary >
public const string httpHead = "http";

/// < summary >
/// 配置物
/// </ summary >
public const string source = "source";

}


猜你喜欢

转载自blog.csdn.net/qq_36512517/article/details/80777014