1.前言
- 在Unity3D中,我们经常会需要在本地或者服务器上读取游戏数据,Unity中读取文件的方式有很多种,写下此文章以做总结。
2.读取类型
2.1 TextAsset
- TextAsset是Unity 提供的一个文本对象,它可以通过Resources.Load 或者 AssetBundle 来读取数据。
- 它支持读取的文本格式包括 .txt .html .htm .bytes .json .csv .yaml .fnt。
using UnityEngine; public class LoadTextAsset : MonoBehaviour { private void Start() { string mystr = Resources.Load<TextAsset>("Text/text").text; Debug.Log(mystr); } }
2.2 Resources
- Resources 类允许查找和访问包括资产在内的对象。
- 可以通过 Resources.Load 函数访问 Assets 文件夹中任何位置名为“Resources”的文件夹中的所有资源。可能存在多个“资源”文件夹,并且在加载对象时将检查每个文件夹。
- 注意事项:
- Resources类只能读取名为“Resources”的文件夹里的资源,注意是复数形式。
- Resources文件夹需要用户自己新建,可以放在Asset文件夹里任意层级的子目录中,若在不同目录下有多个“Resources”文件夹,加载某个指定资源时每一个“Resources”文件夹都会被检查。因此建议项目中只创建一个名为“Resources”的文件夹,且放在Asset文件夹的根目录下。
- Unity打包发布时,Resources文件夹里的资源会被打入包中。
- Resources类加载资源时,使用”Resources”文件夹开始的相对路径,且不包含资源的扩展名。如要加载Asset/Resources/Images/10.jpg资源,加载路径应该写”Images/10”。
using UnityEngine; using System.Collections; public class ExampleClass : MonoBehaviour { void Start() { GameObject go = GameObject.CreatePrimitive(PrimitiveType.Plane); Renderer rend = go.GetComponent<Renderer>(); rend.material.mainTexture = Resources.Load("glass") as Texture; } }
2.3 FileStream
- FileStream对象表示在磁盘或网络路径上指向文件的流。这个类提供了在文件中读写字节的方法,但经常使用StreamReader或 StreamWriter执行这些功能。这是因为FileStream类操作的是字节和字节数组,而Stream类操作的是字符数据。
- 如果你是准备读取byte数据的话,用StreamReader读取然后用 System.Text.Encoding.Default.GetBytes转化的话,如下,则可能出现数据丢失的情况,如byte数据的个数不对等。因此操作byte数据时要用FileStream。 string textContent = fileStream.ReadToEnd();byte[] bytes = System.Text.Encoding.Default.GetBytes(textContent);
字符数据易于使用, 但是有些操作,比如随机文件访问(访问文件中间某点的数据),就必须由FileStream对象执行.
using (FileStream fsRead = new FileStream(@"D:\1.txt", FileMode.Open)) { int fsLen = (int)fsRead.Length; byte[] heByte = new byte[fsLen]; int r = fsRead.Read(heByte, 0, heByte.Length); string myStr = System.Text.Encoding.UTF8.GetString(heByte); }
2.4 StreamReader
- C#中的StreamReader类用于从文本文件中读取字符流。它提供了一种方便的方法来按行读取文本文件的内容。StreamReader类位于System.IO命名空间下,可以通过使用using指令引入该命名空间来使用StreamReader类。以下是StreamReader类的一些常用方法和功能:
- ReadLine()方法:按行读取文件内容,每次读取一行。该方法返回一个字符串,表示读取的那一行内容。如果没有更多的行可读,则返回null。
using (StreamReader reader = new StreamReader("file.txt")) { string line; while ((line = reader.ReadLine()) != null) { Console.WriteLine(line); } }
- ReadToEnd()方法:读取整个文件的内容,并将其作为字符串返回。该方法会一次性读取整个文件,因此适用于较小的文件。
using (StreamReader reader = new StreamReader("file.txt")) { string content = reader.ReadToEnd(); Console.WriteLine(content); }
2.5 WWW(已过时)
- WWW类是一个用于进行HTTP请求的工具类,它基于HTTP协议,使用多种方式传输数据。WWW类在Unity中主要支持GET和POST方式。GET方式将请求附加在URL后面,而POST方式则是通过FORM的形式提交。从安全角度来看,POST方式比GET方式安全性更高,因此在实际使用中建议更多选择POST方式。然而,GET方式最多能传递1024个字节,而POST方式理论上没有限制。此外,Unity的WWW类还支持使用Get和Post方式进行表单的上传。在Unity中,使用WWW类可以方便地从网络上动态地下载图片、声音、视频资源等等。
public static IEnumerator Load() { yield return null; www = new WWW(xmlPath); while (!www.isDone) { yield return null; } string contentText = www.text; }
2.6 UnityWebRequest
- WWW和UnityWebRequest都用于处理Http请求,UnityWebRequest是后面出的用于替代WWW的模块。相比于WWW,UnityWebRequest支持设置timeout超时时间,支持断点续传,在一些复杂操作上也有更好的表现。
- 结构:
- UploadHandler: 处理数据到服务器的传输
- DownloadHandler: 处理从服务器接收的数据的接收、缓冲和后处理
- UnityWebRequest: 管理上面两个对象
- Get()
private IEnumerator Get() { var request = UnityWebRequest.Get("http://www.baidu.com"); yield return request.SendWebRequest(); if (request.isHttpError || request.isNetworkError) { Debug.LogError(request.error); } else { Debug.Log(request.downloadHandler.text); } }
- Post()
private IEnumerator Post() { //这里使用WWWForm来构建键值对。和WWW的使用是一致的 WWWForm form = new WWWForm(); form.AddField("key","value"); UnityWebRequest webRequest = UnityWebRequest.Post("http://www.baidu.com",form); yield return webRequest.SendWebRequest(); if (webRequest.isHttpError || webRequest.isNetworkError) { Debug.LogError(webRequest.error); } else { Debug.Log(webRequest.downloadHandler.text); } }
- 显示进度
private IEnumerator GetShowProgress() { UnityWebRequest request = UnityWebRequest.Get("www.baidu.com"); request.SendWebRequest(); while (!request.isDone) { Debug.Log($"{GetType()} progress:{request.downloadProgress}"); yield return null; } Debug.Log($"{GetType()} progress:{request.downloadProgress}"); if (request.isNetworkError || request.isHttpError) { Debug.LogError($"{GetType()} error:{request.error}"); } else { Debug.Log($"{GetType()} text:{request.downloadHandler.text}"); Debug.Log($"{GetType()} bytes.length:{request.downloadHandler.data.Length}"); } }
2.7 File
- File类提供了一些用于文件操作的功能,包括读取和写入文件。
- 读取文件:使用File.ReadAllText()方法可以读取文本文件的内容,该方法需要提供文件路径作为参数。例如,要读取名为"test.txt"的文本文件。
string filePath = "Assets/test.txt"; string fileContent = File.ReadAllText(filePath); Debug.Log(fileContent);
- 写入文件:使用File.WriteAllText()方法可以将文本内容写入到文件中,该方法需要提供文件路径和要写入的内容作为参数。例如,要将名为"test.txt"的文本文件中写入一些内容。
string filePath = "Assets/test.txt"; string contentToWrite = "Hello, world!"; File.WriteAllText(filePath, contentToWrite);
3.区别
3.1 FileStream和StreamReader区别
- 类型:FileStream 是字节流,而 StreamReader 是字符流。
- 读取方式:FileStream 读取文件内容时通常以字节为单位进行处理,而 StreamReader 则以字符为单位读取。
- 用途:FileStream 更适用于处理二进制文件或非文本文件,而 StreamReader 更适用于处理文本文件。
- 性能:对于大文件,使用 FileStream 逐个字节地读取文件可能会导致性能问题,而 StreamReader 可以更高效地读取文本文件。
- 总之,FileStream 和 StreamReader 都是用于处理流数据的类,但它们的使用方式和适用场景有所不同。如果您需要处理文本文件,使用 StreamReader 可能更合适。如果您需要处理二进制文件或需要更细粒度的控制,使用 FileStream 可能更适合。
3.2 WWW和UnityWebRequest区别
- 接口设计:
- WWW模块的接口设计较早,相对简单,主要基于Http协议进行封装。
- UnityWebRequest对WWW进行了改进和优化,提供了更强大和灵活的接口,可以更好地处理各种网络请求和数据传输。
- 功能特性:
- WWW模块主要支持GET和POST请求,对于PUT和DELETE等其他HTTP方法支持不够完善。
- UnityWebRequest支持多种HTTP方法,包括PUT、DELETE、HEAD等,还支持自定义HTTP方法。
- UnityWebRequest还提供了对HTTP头部的自定义设置,可以更好地控制请求和响应的头部信息。
- 数据处理:
- WWW模块对于下载的数据处理主要是以字符串形式进行,对于二进制数据需要额外转换。
- UnityWebRequest支持直接下载二进制数据,无需进行转换,同时也可以直接读取和处理JSON、XML等其他数据格式。
- 效率优化:
- UnityWebRequest在处理网络请求时,采用了更高效的异步方式,可以减少阻塞主线程的情况。
- UnityWebRequest还对数据缓存进行了优化,减少了不必要的网络请求和数据读取。
- 垃圾回收(GC)性能:
- WWW模块在处理网络请求时,会产生大量的临时对象,导致频繁的垃圾回收,可能会影响性能。
- UnityWebRequest通过优化内部实现,减少了临时对象的产生,降低了垃圾回收的频率,从而提高了性能。
- 综上所述,UnityWebRequest在功能特性、数据处理、效率优化和使用场景等方面都优于WWW模块。在选择使用WWW或UnityWebRequest时,建议考虑项目的需求和性能要求,选择最适合的模块。