写点什么

Unity 关于低版本是否可以引用高版本构建内容的可行性验证

作者:CoderZ
  • 2022 年 9 月 07 日
    江苏
  • 本文字数:5230 字

    阅读完需:约 17 分钟

Unity 关于低版本是否可以引用高版本构建内容的可行性验证

🎈 简介

本篇内容以 Unity 的一个相对较低的版本(2017.4.40)和一个相对较高的版本(2020.3.33),来验证在低版本中是否可以使用高版本中构建的内容,包括如下内容:


  • 在 Unity2017.4.40(使用 C#6)中是否可以引入 Unity2020.3.33(使用 C#8)构建的 dll 并正常使用;

  • 在 Unity2017.4.40 中是否可以加载在 Unity2020.3.33 中构建的 AssetsBundle 资源;

🎈 低版本是否可以引用高版本构建的 dll

在 Unity2020.3.33 中,我们开启一个携程,使用UnityWebRequest发起网络请求来获取百度知道网页(www.baidu.com)上的内容,代码示例如下:


using UnityEngine;using System.Collections;using UnityEngine.Networking;
namespace SKFramework.Test{ public class TEST : MonoBehaviour { private void Start() { StartCoroutine(TestCoroutine()); }
private IEnumerator TestCoroutine() { string url = "www.baidu.com"; using (UnityWebRequest request = UnityWebRequest.Get(url)) { yield return request.SendWebRequest(); Debug.Log(request.downloadHandler.text); } } }}
复制代码


运行结果如下:


Console Log


其中 using 语句在C# 8.0中有了新的写法(C# 8.0中的新增功能 - C#指南),如下图所示:


using 声明


我们在示例代码使用新的using声明


using UnityEngine;using System.Collections;using UnityEngine.Networking;
namespace SKFramework.Test{ public class TEST : MonoBehaviour { private void Start() { StartCoroutine(TestCoroutine()); }
private IEnumerator TestCoroutine() { string url = "www.baidu.com"; using UnityWebRequest request = UnityWebRequest.Get(url); yield return request.SendWebRequest(); Debug.Log(request.downloadHandler.text); } }}
复制代码


yield return request.SendWebRequest发起网络请求后,一般会先判断请求是否成功,在以往的 API 中会通过如下方式判断:


using UnityEngine;using System.Collections;using UnityEngine.Networking;
namespace SKFramework.Test{ public class TEST : MonoBehaviour { private void Start() { StartCoroutine(TestCoroutine()); }
private IEnumerator TestCoroutine() { string url = "www.baidu.com"; using UnityWebRequest request = UnityWebRequest.Get(url); yield return request.SendWebRequest(); if (request.isNetworkError || request.isHttpError) { Debug.Log(request.downloadHandler.text); } else { Debug.LogError(string.Format("发起网络请求失败:{0}", request.error)); } } }}
复制代码


但是当我们查看其定义可以发现它已经弃用(Obsolete)了:


//// 摘要://     Returns true after this UnityWebRequest encounters a system error. (Read Only)[Obsolete("UnityWebRequest.isNetworkError is deprecated. Use (UnityWebRequest.result == UnityWebRequest.Result.ConnectionError) instead.", false)]public bool isNetworkError => result == Result.ConnectionError;
//// 摘要:// Returns true after this UnityWebRequest receives an HTTP response code indicating// an error. (Read Only)[Obsolete("UnityWebRequest.isHttpError is deprecated. Use (UnityWebRequest.result == UnityWebRequest.Result.ProtocolError) instead.", false)]public bool isHttpError => result == Result.ProtocolError;
复制代码


因为在新版本使用新增属性result来判断请求是否成功:


using UnityEngine;using System.Collections;using UnityEngine.Networking;
namespace SKFramework.Test{ public class TEST : MonoBehaviour { private void Start() { StartCoroutine(TestCoroutine()); }
private IEnumerator TestCoroutine() { string url = "www.baidu.com"; using UnityWebRequest request = UnityWebRequest.Get(url); yield return request.SendWebRequest(); if (request.result == UnityWebRequest.Result.Success) { Debug.Log(request.downloadHandler.text); } else { Debug.LogError(string.Format("发起网络请求失败:{0}", request.error)); } } }}
复制代码


下面我们将其封装为一个接口并构建 dll 导入到 Unity2017.4.40 中去使用,接口代码如下:


using UnityEngine;using System.Collections;using UnityEngine.Networking;
namespace SKFramework.Test{ public class TEST { public void Execute(MonoBehaviour executer) { executer.StartCoroutine(TestCoroutine()); }
private IEnumerator TestCoroutine() { string url = "www.baidu.com"; using UnityWebRequest request = UnityWebRequest.Get(url); yield return request.SendWebRequest(); if (request.result == UnityWebRequest.Result.Success) { Debug.Log(request.downloadHandler.text); } else { Debug.LogError(string.Format("发起网络请求失败:{0}", request.error)); } } }}
复制代码

📍 如何构建 dll 动态库

打开Visual Studio创建新项目,模板选择如图所示:


创建新项目


C# 8.0对应框架.Net Framework 4.8(C#版本 与 .NET Framework 对应关系及各版本语法差异)


配置新项目


创建后将我们的示例代码拷入其中,发现 UnityEngine 的部分报错,因为我们还没有引用UnityEngine.dll


封装接口


UnityEngine.dll所在文件夹目录如下,需要到 Unity Editor 的安装目录下去找:


UnityEngine.dll


添加引用:


添加引用


引用添加完成,再次右键项目,点击生成,然后将生成的 dll 动态库导入到 Unity2017.4.40 创建的项目中。


生成dll动态库

📍 如何将 Unity 使用的 C#语言版本改为 6.0

参考文章:配置Unity2017和VS2015使用C# 6.0


  • Player Sttings中将Scripting Runtime Version修改为Experimental(.Net 4.6 Equivalent)

    Player Settings

  • Visual Studio中打开工具 - 选项 - 适用于 Unity 的工具 - 杂项,将访问项目属性修改为 true;

    访问项目属性

  • 重启再打开属性设置目标框架为.Net Framework 4.6.1,编写测试脚本:


using UnityEngine;using SKFramework.Test;
public class Example : MonoBehaviour { private void Start() { new TEST().Execute(this); }}
复制代码


运行结果:


运行结果

🎈 低版本是否可以加载高版本构建的 AssetsBundle

  • 在 Unity2020.3.33 中创建一个 Prefab 预制体:


Prefab


  • 新建Assets Bundle


Assets Bundle


  • 构建Assets Bundle,使用工具代码如下:


#if UNITY_EDITORusing System.IO;using UnityEditor;using UnityEngine;
namespace SK.Framework.Tools{public class SimpleAssetsBundle : EditorWindow{ [MenuItem("SKFramework/Tools/Simple AssetsBundle")] public static void Open() { var window = GetWindow<SimpleAssetsBundle>(); window.titleContent = new GUIContent("Simple AssetsBundle"); window.minSize = new Vector2(300f, 100f); window.maxSize = new Vector2(1080f, 100f); window.Show(); }
//打包路径 private string path; //打包选项 private BuildAssetBundleOptions options; //目标平台 private BuildTarget target;
private const float labelWidth = 80f;
private void OnEnable() { path = EditorPrefs.HasKey(EditorPrefsKeys.path) ? EditorPrefs.GetString(EditorPrefsKeys.path) : Application.streamingAssetsPath; options = EditorPrefs.HasKey(EditorPrefsKeys.options) ? (BuildAssetBundleOptions)EditorPrefs.GetInt(EditorPrefsKeys.options) : BuildAssetBundleOptions.None; target = EditorPrefs.HasKey(EditorPrefsKeys.target) ? (BuildTarget)EditorPrefs.GetInt(EditorPrefsKeys.target) : BuildTarget.StandaloneWindows; }
private void OnGUI() { //路径 GUILayout.BeginHorizontal(); GUILayout.Label("Path", GUILayout.Width(labelWidth)); string newPath = EditorGUILayout.TextField(path); if (newPath != path) { path = newPath; EditorPrefs.SetString(EditorPrefsKeys.path, path); } //浏览 选择路径 if (GUILayout.Button("Browse", GUILayout.Width(60f))) { newPath = EditorUtility.OpenFolderPanel("AssetsBundle构建路径", Application.dataPath, string.Empty); if (!string.IsNullOrEmpty(newPath) && newPath != path) { path = newPath; EditorPrefs.SetString(EditorPrefsKeys.path, path); } } GUILayout.EndHorizontal();
//选项 GUILayout.BeginHorizontal(); GUILayout.Label("Options", GUILayout.Width(labelWidth)); var newOptions = (BuildAssetBundleOptions)EditorGUILayout.EnumPopup(options); if (newOptions != options) { options = newOptions; EditorPrefs.SetInt(EditorPrefsKeys.options, (int)options); } GUILayout.EndHorizontal();
//平台 GUILayout.BeginHorizontal(); GUILayout.Label("Target", GUILayout.Width(labelWidth)); var newTarget = (BuildTarget)EditorGUILayout.EnumPopup(target); if (newTarget != target) { target = newTarget; EditorPrefs.SetInt(EditorPrefsKeys.target, (int)target); } GUILayout.EndHorizontal();
GUILayout.FlexibleSpace();
//构建按钮 if (GUILayout.Button("Build")) { //检查路径是否有效 if (!Directory.Exists(path)) { Debug.LogError(string.Format("无效路径 {0}", path)); return; } //提醒 if (EditorUtility.DisplayDialog("提醒", "构建AssetsBundle将花费一定时间,是否确定开始?", "确定", "取消")) { //开始构建 BuildPipeline.BuildAssetBundles(path, options, target); } } }
private class EditorPrefsKeys { public static string path = "SIMPLEASSETSBUNDLE_PATH"; public static string options = "SIMPLEASSETSBUNDLE_OPTIONS"; public static string target = "SIMPLEASSETSBUNDLE_TARGET"; }}}#endif
复制代码


  • 将构建出的 ab 包导入到 Unity2017.4.40 项目中的Streaming Assets文件夹中:

  • Streaming Assets


编写测试脚本:


using UnityEngine;using SKFramework.Test;using System.Collections;using UnityEngine.Networking;
public class Example : MonoBehaviour { private void Start() { //new TEST().Execute(this); StartCoroutine(ExampleCoroutine()); }
private IEnumerator ExampleCoroutine() { string url = Application.streamingAssetsPath + "/player";
WWW www = new WWW(url); yield return www; if (www.error == null) { var ab = www.assetBundle; Debug.Log(ab == null); } else { Debug.LogError(www.error); } }}
复制代码


运行结果:


Console Log

🎈 结论

以上述的结果来看,在相对较低的版本中,无论是引入相对较高的版本生成的 dll,还是加载相对较高版本构建的 ab 包,都会出现些许问题,是否有相应解决方案尚需确定。

发布于: 刚刚阅读数: 3
用户头像

CoderZ

关注

还未添加个人签名 2022.08.04 加入

一名Unity开发工程师,SKFramework开源框架作者,CSDN博客专家、Unity领域优质创作者,华为云云享专家,阿里云专家博主,从事于游戏、VRARMR、虚拟仿真、数字孪生、元宇宙等相关领域,微信公众号:当代野生程序猿。

评论

发布
暂无评论
Unity 关于低版本是否可以引用高版本构建内容的可行性验证_C#_CoderZ_InfoQ写作社区