我有一个函数从文件夹中获取图像并在RawImage上显示5秒,然后重新开始。
当looper()函数调用medialogic()函数时,显示第一个图像后出现此问题。它给出了标题中的错误。
我怎么能解决这个问题或为什么会这样?我是团结和C#的新人。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
using System.IO;
using System.Linq;
using System.Text;
public class Test2 : MonoBehaviour {
// Use this for initialization
//Publics
private string path = "file:///";
public string folder = "C:/medias/";
int interval = 7000;
int arrLength;
int i = 0;
string source;
string str;
WWW www;
string[] extensions = new[] { ".jpg", ".JPG", ".jpeg", ".JPEG", ".png", ".PNG", ".ogg", ".OGG" };
FileInfo[] info;
DirectoryInfo dir;
void Start() {
dir = new DirectoryInfo(@folder);
info = dir.GetFiles().Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
arrLength = info.Length;
looper ();
}
// Update is called once per frame
void Update () {
}
void looper() {
medialogic ();
EasyTimer.SetInterval(() =>
{
if (i == arrLength-1) {
info = dir.GetFiles().Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
arrLength = info.Length;
i = 0;
} else {
i++;
}
medialogic();
}, interval);
}
void medialogic() {
source = info [i].ToString();
str = path + source;
www = new WWW(str);
string[] extType = source.Split('.');
int pos = Array.IndexOf(extensions, "."+extType[1]);
if (pos > -1) {
GetComponent<RawImage> ().texture = www.texture;
Debug.Log (extType[1]);
} else {
//videos here
Debug.Log (extType[1]);
}
}
public static class EasyTimer
{
public static IDisposable SetInterval(Action method, int delayInMilliseconds)
{
System.Timers.Timer timer = new System.Timers.Timer(delayInMilliseconds);
timer.Elapsed += (source, e) =>
{
method();
};
timer.Enabled = true;
timer.Start();
// Returns a stop handle which can be used for stopping
// the timer, if required
return timer as IDisposable;
}
public static IDisposable SetTimeout(Action method, int delayInMilliseconds)
{
System.Timers.Timer timer = new System.Timers.Timer(delayInMilliseconds);
timer.Elapsed += (source, e) =>
{
method();
};
timer.AutoReset = false;
timer.Enabled = true;
timer.Start();
// Returns a stop handle which can be used for stopping
// the timer, if required
return timer as IDisposable;
}
}
}
编辑:下面的用户程序员有正确的答案。
答案 0 :(得分:3)
正如@Programmer回答的那样,我的帖子并不是处理Unity3D中WWW
交互的正确方法。 InvokeRepeating()
是您学习简单性的第一个。请仔细阅读他的答案,了解我的例子错误是什么。 #CleanerCoding
此外,根据此网站上的用户InvokeRepeating()
正在使用反射,这会产生更大的开销。
查看MonoBehaviour.InvokeRepeating()
它应该在您的代码中起作用:
void Start()
{
dir = new DirectoryInfo(@folder);
info = dir.GetFiles().Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
arrLength = info.Length;
// Starting in 0.1 seconds.
// and will be launched every 5 seconds
InvokeRepeating("medialogic", 0.1f, 5f);
}
摆脱这个丑陋的looper()
功能。
答案 1 :(得分:3)
即使已经标记为已解决,我也认为您的代码中存在许多其他问题,您现在可能不会注意到这些问题,但稍后会出现。
使用需要屈服的InvokeRepeating
调用API(WWW
)是完全错误的。
主要问题是来自SetInterval
类的Timer
函数正在另一个Thread
中调用,但您无法使用其他线程中的Unity API 。
您可以使用此class在主线程中运行medialogic()
函数:
void Awake()
{
UnityThread.initUnityThread();
}
void looper()
{
medialogic();
EasyTimer.SetInterval(() =>
{
if (i == arrLength - 1)
{
info = dir.GetFiles().Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
arrLength = info.Length;
i = 0;
}
else
{
i++;
}
UnityThread.executeInUpdate(() =>
{
medialogic();
});
}, interval);
}
这不是代码中的唯一问题:
您未正确使用WWW
API。它需要用于协程功能。在与GetComponent<RawImage>().texture = www.texture;
一起使用之前,您目前还没有等待它完成下载图像。
由于WWW
需要协同程序,协同程序也可用于计时器,删除Timer
类并使用WaitForSeconds
在协同程序函数中等待5秒。
这是这样做的正确方法:
public class Test2 : MonoBehaviour
{
// Use this for initialization
//Publics
private string path = "file:///";
public string folder = "C:/medias/";
int interval = 7000;
int arrLength;
int i = 0;
string source;
string str;
WWW www;
string[] extensions = new[] { ".jpg", ".JPG", ".jpeg", ".JPEG", ".png", ".PNG", ".ogg", ".OGG" };
FileInfo[] info;
DirectoryInfo dir;
void Start()
{
dir = new DirectoryInfo(@folder);
info = dir.GetFiles().Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
arrLength = info.Length;
StartCoroutine(looper());
}
IEnumerator looper()
{
yield return StartCoroutine(medialogic());
WaitForSeconds waitTime = new WaitForSeconds(5);
//Run forever
while (true)
{
if (i == arrLength - 1)
{
info = dir.GetFiles().Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
arrLength = info.Length;
i = 0;
}
else
{
i++;
}
yield return StartCoroutine(medialogic());
//Wait for 5 seconds
yield return waitTime;
}
}
IEnumerator medialogic()
{
source = info[i].ToString();
str = path + source;
www = new WWW(str);
//Wait for download to finish
yield return www;
string[] extType = source.Split('.');
int pos = Array.IndexOf(extensions, "." + extType[1]);
if (pos > -1)
{
GetComponent<RawImage>().texture = www.texture;
Debug.Log(extType[1]);
}
else
{
//videos here
Debug.Log(extType[1]);
}
}
}