C# 在Unity中使用协程更新进度条时读取文件
我试图在更新进度条时逐行读取文件(两个GUI纹理,其中一个宽度(maxWidth*currentPercentage)带有浮点扩展) 我有两个实现:C# 在Unity中使用协程更新进度条时读取文件,c#,unity3d,stream,coroutine,C#,Unity3d,Stream,Coroutine,我试图在更新进度条时逐行读取文件(两个GUI纹理,其中一个宽度(maxWidth*currentPercentage)带有浮点扩展) 我有两个实现: public static string ThreadedFileRead(string path, Action<float> percAction) { FileInfo fileInfo = new FileInfo(path); StringBuilder sb = new Str
public static string ThreadedFileRead(string path, Action<float> percAction)
{
FileInfo fileInfo = new FileInfo(path);
StringBuilder sb = new StringBuilder();
float length = fileInfo.Length;
int currentLength = 0;
using (StreamReader sr = new StreamReader(path))
{
while (!sr.EndOfStream)
{
string str = sr.ReadLine();
sb.AppendLine(str);
// yield return str;
percAction(currentLength / length);
currentLength += str.Length;
Interlocked.Add(ref currentLength, str.Length);
}
percAction(1f);
return sb.ToString();
}
}
publicstaticstringthreadedfileread(字符串路径,Action peraction)
{
FileInfo FileInfo=新的FileInfo(路径);
StringBuilder sb=新的StringBuilder();
float length=fileInfo.length;
int currentLength=0;
使用(StreamReader sr=新StreamReader(路径))
{
而(!sr.EndOfStream)
{
字符串str=sr.ReadLine();
附肢线(str);
//收益率;
PERACTION(当前长度/长度);
当前长度+=长度;
联锁。添加(参考当前长度、str.Length);
}
peraction(1f);
使某人返回字符串();
}
}
使用以下实现:
// Inside a MonoBehaviour
public void Start()
{
string fileContents = "";
StartCoroutine(LoadFileAsync(Application.dataPath + "/Data/file.txt", (s) => fileContents = s));
}
public IEnumerator LoadFileAsync(string path, Action<string> fin)
{
string contents = "";
lock (contents)
{
var task = Task.Factory.StartNew(() =>
{
contents = F.ThreadedFileRead(path, (f) => currentLoadProgress = f);
});
while (!task.IsCompleted)
yield return new WaitForEndOfFrame();
fin?.Invoke(contents);
}
}
public IEnumerator LoadFileAsync(string path, Action<string> fin)
{
yield return F.LoadFileAsync(path, (f) => currentLoadProgress = f, fin);
}
//在一个单一行为中
公开作废开始()
{
字符串fileContents=“”;
start例程(LoadFileAsync(Application.dataPath+“/Data/file.txt”,(s)=>fileContents=s));
}
公共IEnumerator LoadFileAsync(字符串路径,操作fin)
{
字符串内容=”;
锁(内容)
{
var task=task.Factory.StartNew(()=>
{
contents=F.ThreadedFileRead(路径,(F)=>currentLoadProgress=F);
});
而(!task.IsCompleted)
返回新的WaitForEndOfFrame();
fin?调用(内容);
}
}
但是这会阻塞当前的GUI(我不知道为什么)
我也用了这个:
// Thanks to: https://stackoverflow.com/questions/41296957/wait-while-file-load-in-unity
// Thanks to: https://stackoverflow.com/a/34378847/3286975
[MustBeReviewed]
public static IEnumerator LoadFileAsync(string pathOrUrl, Action<float> updatePerc, Action<string> finishedReading)
{
FileInfo fileInfo = new FileInfo(pathOrUrl);
float length = fileInfo.Length;
// Application.isEditor && ??? // Must review
if (Path.IsPathRooted(pathOrUrl))
pathOrUrl = "file:///" + pathOrUrl;
/*
using (var www = new UnityWebRequest(pathOrUrl))
{
www.downloadHandler = new DownloadHandlerBuffer();
CityBenchmarkData.StartBenchmark(CityBenchmark.SendWebRequest);
yield return www.SendWebRequest();
CityBenchmarkData.StopBenchmark(CityBenchmark.SendWebRequest);
while (!www.isDone)
{
// www.downloadProgress
updatePerc?.Invoke(www.downloadedBytes / length); // currentLength / length
yield return new WaitForEndOfFrame();
}
finishedReading?.Invoke(www.downloadHandler.text);
}
*/
using (var www = new WWW(pathOrUrl))
{
while (!www.isDone)
{
// www.downloadProgress
updatePerc?.Invoke(www.bytesDownloaded / length); // currentLength / length
yield return new WaitForEndOfFrame();
}
finishedReading?.Invoke(www.text);
}
}
//多亏了:https://stackoverflow.com/questions/41296957/wait-while-file-load-in-unity
//感谢:https://stackoverflow.com/a/34378847/3286975
[必须查看]
公共静态IEnumerator LoadFileAsync(字符串pathrUrl、操作updatePerc、操作finisheFearding)
{
FileInfo FileInfo=新的FileInfo(pathrurl);
float length=fileInfo.length;
//Application.isEditor&&???//必须审核
if(Path.IsPathRooted(pathrurl))
pathrurl=“文件://”+pathrurl;
/*
使用(var www=new UnityWebRequest(pathrurl))
{
www.downloadHandler=new DownloadHandlerBuffer();
CityBenchmarkData.StartBenchmark(CityBenchmark.SendWebRequest);
返回www.SendWebRequest();
CityBenchmarkData.StopBenchmark(CityBenchmark.SendWebRequest);
而(!www.isDone)
{
//www.downloadProgress
updatePerc?.Invoke(www.downloaddedbytes/length);//currentLength/length
返回新的WaitForEndOfFrame();
}
FinisheFearding?.Invoke(www.downloadHandler.text);
}
*/
使用(var www=new www(pathrurl))
{
而(!www.isDone)
{
//www.downloadProgress
updatePerc?.Invoke(www.bytesloadded/length);//currentLength/length
返回新的WaitForEndOfFrame();
}
完成恐惧?.Invoke(www.text);
}
}
通过以下实施:
// Inside a MonoBehaviour
public void Start()
{
string fileContents = "";
StartCoroutine(LoadFileAsync(Application.dataPath + "/Data/file.txt", (s) => fileContents = s));
}
public IEnumerator LoadFileAsync(string path, Action<string> fin)
{
string contents = "";
lock (contents)
{
var task = Task.Factory.StartNew(() =>
{
contents = F.ThreadedFileRead(path, (f) => currentLoadProgress = f);
});
while (!task.IsCompleted)
yield return new WaitForEndOfFrame();
fin?.Invoke(contents);
}
}
public IEnumerator LoadFileAsync(string path, Action<string> fin)
{
yield return F.LoadFileAsync(path, (f) => currentLoadProgress = f, fin);
}
公共IEnumerator LoadFileAsync(字符串路径,操作fin)
{
产生返回F.LoadFileAsync(路径,(F)=>currentLoadProgress=F,fin);
}
我共享的最后一段代码有两部分:
- 注释部分也会阻塞主线程
- 我使用的WWW类(将来会被弃用)不会阻止主线程,但它只在进度条上显示两个步骤(比如25%和70%)
www.SendWebRequest()
完成,而在等待过程中,项目中的其他脚本仍在正常运行,并且每一帧都在运行
问题是,有些人不知道如何使用www.isDone以及何时使用它。一个例子是post,当人们发现这样的代码时,就会遇到问题
使用UnityWebRequest的两种方法:
ThreadedFileRead(path, (percent) =>
{
Debug.Log("Update: " + percent);
}, (result) =>
{
Debug.Log("Done: " + result);
});
1。下载或提出请求,然后忘记它,直到它完成。当您不需要知道下载的状态时,可以执行此操作,例如UnityWebRequest.downloadedBytes
,UnityWebRequest.uploadedBytes
和UnityWebRequest.DownloadeProgress
和UnityWebRequest.UploadeProgress
值
为此,您可以使用yield return
关键字生成UnityWebRequest.SendWebRequest()
函数。它将等待UnityWebRequest.SendWebRequest()
函数,直到下载完成,但不会阻止您的程序。Update
函数和其他脚本中的代码应仍在运行。该等待仅在LoadFileAsync
coroutine函数中完成
示例(请注意使用yield return www.SendWebRequest()
和noUnityWebRequest.isDone
):
2。下载或发出请求,然后等待每一帧,直到UnityWebRequest.isDone
为true
。当您需要了解下载的状态时,如UnityWebRequest.downloadedBytes
,UnityWebRequest.uploadedBytes
和UnityWebRequest.DownloadeProgress
和UnityWebRequest.UploadeProgress
v
ThreadedFileRead(path, (percent) =>
{
Debug.Log("Update: " + percent);
}, (result) =>
{
Debug.Log("Done: " + result);
});