UH3L13——客户端热更新路径优化
UH3L13——客户端热更新路径优化
当前需要优化的问题
不同平台的特殊路径,读取表现是不同的:
Application.persistentDataPath |
Application.streamingAssetsPath |
|||
---|---|---|---|---|
UnityWebRequest 或者WWW 读取 |
C#文件流读取 | UnityWebRequest 或者WWW 读取 |
C#文件流读取 | |
PC | 加 file:/// |
无需处理 | 加 file:/// |
无需处理 |
Android | 加 file:/// |
无需处理 | 直接用 | 不可用 |
IOS | 加 file:/// |
无需处理 | 加 file:/// |
无需处理 |
如果我们不对不同平台加以判断,修改读取逻辑,可能就在不同平台上读取出现问题,因此我们需要优化热更新路径的逻辑
多路测试
通过预处理器指令#if ... #elif ... #else .... #endif
,可以选择性的编译C#部分代码
如果#if
和#elif
后边跟随的宏(或者说符号)被定义#define
过,其与#endif
包裹起来的代码就会被编译
如果#if
和#elif
后边跟随的宏(或者说符号)都没有被定义过#define
过,则#else
与#endif
包裹起来的代码就会被编译
1 | //#define必须放在文件最开头,所有关键词前面 |
平台测试符号
Unity 支持对脚本使用的平台 #define
指令如下:
Define | 功能 |
---|---|
UNITY_EDITOR | 用于从游戏代码中调用 Unity Editor 脚本的 #define 指令。 |
UNITY_EDITOR_WIN | 用于 Windows 上的 Editor 代码的 #define 指令。 |
UNITY_EDITOR_OSX | 用于 Mac OS X 上的 Editor 代码的 #define 指令。 |
UNITY_EDITOR_LINUX | 用于 Linux 上的 Editor 代码的 #define 指令。 |
UNITY_STANDALONE_OSX | 用于专门为 Mac OS X(包括 Universal、PPC 和 Intel 架构)编译或执行代码的 #define 指令。 |
UNITY_STANDALONE_WIN | 用于专门为 Windows 独立平台应用程序编译/执行代码的 #define 指令。 |
UNITY_STANDALONE_LINUX | 用于专门为 Linux 独立平台应用程序编译/执行代码的 #define 指令。 |
UNITY_STANDALONE | 用于为任何独立平台(Mac OS X、Windows 或 Linux)编译/执行代码的 #define 指令。 |
UNITY_WII | 用于为 Wii 游戏主机编译/执行代码的 #define 指令。 |
UNITY_IOS | 用于为 iOS 平台编译/执行代码的 #define 指令。 |
UNITY_IPHONE | 已弃用。改用 UNITY_IOS。 |
UNITY_ANDROID | 用于 Android 平台的 #define 指令。 |
UNITY_PS4 | 用于运行 PlayStation 4 代码的 #define 指令。 |
UNITY_XBOXONE | 用于执行 Xbox One 代码的 #define 指令。 |
UNITY_LUMIN | 用于 Magic Leap OS 平台的 #define 指令。也可以使用 PLATFORM_LUMIN。 |
UNITY_TIZEN | 用于 Tizen 平台的 #define 指令。 |
UNITY_TVOS | 用于 Apple TV 平台的 #define 指令。 |
UNITY_WSA | 用于通用 Windows 平台的 #define 指令。此外,根据 .NET Core 和使用 .NET 脚本后端来编译 C# 文件时会定义 NETFX_CORE。 |
UNITY_WSA_10_0 | 用于通用 Windows 平台的 #define 指令。此外,根据 .NET Core 来编译 C# 文件时会定义 WINDOWS_UWP。 |
UNITY_WINRT | 与 UNITY_WSA 相同。 |
UNITY_WINRT_10_0 | 等效于 UNITY_WSA_10_0 |
UNITY_WEBGL | 用于 WebGL 的 #define 指令。 |
UNITY_FACEBOOK | 用于 Facebook 平台(WebGL 或 Windows 独立平台)的 #define 指令。 |
UNITY_ADS | 用于从游戏代码中调用 Unity Ads 方法的 #define 指令。5.2 及更高版本。 |
UNITY_ANALYTICS | 用于从游戏代码中调用 Unity Analytics 方法的 #define 指令。5.2 及更高版本。 |
UNITY_ASSERTIONS | 用于断言控制过程的 #define 指令。 |
UNITY_64 | 用于 64 位平台的 #define 指令。 |
取自:平台相关的编译 - Unity 手册(2019.4版)
目标
在客户端热更新逻辑路径进行相关进行修改
- 下载AB包路径,按平台划分
- 加载文件时,路径前缀处理
代码的修改
我们需要修改以下几处地方
-
DownLoadFile
内:我们需要根据不同平台,修改下载资源的地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43public bool DownLoadFile(string fileName, string localPath)
{
try
{
string pInfo = "IOS";
string pInfo = "Android";
string pInfo = "PC";
//创建一个FTP连接 用于下载
FtpWebRequest request = FtpWebRequest.Create(new Uri($"{serverIP}/AB/{pInfo}/" + fileName)) as FtpWebRequest;
//设置通信凭证 这样才能下载(如果有匿名账号,可以不设置凭证,但是实际开发中建议不要设置匿名账号)
NetworkCredential credential = new NetworkCredential("MrTang", "MrTang123");
request.Credentials = credential;
//其他设置:代理设置为null,请求完毕后关闭控制连接,操作命令设置为下载,指定传输二进制类型数据
request.Proxy = null;
request.KeepAlive = false;
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.UseBinary = true;
FtpWebResponse response = request.GetResponse() as FtpWebResponse;
Stream downLoadStream = response.GetResponseStream();
using (FileStream file = File.Create(localPath))
{
byte[] bytes = new byte[2048];
int contentLength = downLoadStream.Read(bytes, 0, bytes.Length);
while (contentLength > 0)
{
file.Write(bytes, 0, contentLength);
contentLength = downLoadStream.Read(bytes, 0, bytes.Length);
}
file.Close();
downLoadStream.Close();
}
return true;
}
catch (Exception e)
{
Debug.Log($"{fileName}下载失败:{e.Message}");
return false;
}
} -
GetLocalABCompareFileInfo
内:由于
GetLocalABCompareFileInfo
协程方法内使用的是UnityWebRequest
读取的Application.streamingAssetsPath
因此我们需要对安卓平台的读取路径作特殊处理,也就是不加file:///
前缀,而其他平台就需要加上1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36public void GetLocalABCompareFileInfo(UnityAction<bool> overCallBack)
{
//如果可读可写文件夹内存在对比文件,说明之前我们已经下载过了
if (File.Exists("file:///" + Application.persistentDataPath + "/ABCompareInfo.txt"))
{
StartCoroutine(GetLocalABCompareFileInfo("file:///" + Application.persistentDataPath + "/ABCompareInfo.txt", overCal
}
//当可读可写文件夹内不存在对比文件时,才来加载默认的可读可写文件(第一次进游戏才会发生)
else if (File.Exists(Application.streamingAssetsPath + "/ABCompareInfo.txt"))
{
string path = Application.streamingAssetsPath;
string path = "file:///" + Application.streamingAssetsPath;
StartCoroutine(GetLocalABCompareFileInfo(path + "/ABCompareInfo.txt", overCallBack));
}
//如果两个都不进,证明第一次并且无默认资源
else
overCallBack(false);
}
//本地AB包加载并解析
private IEnumerator GetLocalABCompareFileInfo(string filePath, UnityAction<bool> overCallBack)
{
UnityWebRequest request = UnityWebRequest.Get(filePath);
yield return request.SendWebRequest();
//获取文件成功,解析本地的资源解析
if (request.result == UnityWebRequest.Result.Success)
{
GetRemoteABCompareFileInfo(request.downloadHandler.text, localABInfo);
overCallBack(true);
}
else
overCallBack(false);
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 文KRIFE齐的博客!