我有一个功能可以从文件夹中获取图像并在 RawImage 上显示每个图像 5 秒钟,然后重新开始。
当 looper() 函数调用 medialogic() 函数时显示第一张图像后,我遇到了这个问题。它给出了标题错误。
我该如何解决这个问题或为什么会发生这种情况?我是 unity 和 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;
}
}
}
编辑:下面的用户程序员有正确的答案。
最佳答案
即使这被标记为已解决,但我确实认为您的代码中还有许多其他问题,您现在可能没有注意到但稍后会出现。
使用 InvokeRepeating
调用需要让出的 API( WWW
) 是完全错误的。
主要问题是 SetInterval
来自 Timer
的功能正在另一个中调用类 Thread
但您不能从另一个线程使用 Unity 的 API。
您可以制作 medialogic()
函数在主线程中运行 class :
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
应用程序接口(interface)。它需要在协程函数中使用。在将图像与 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]);
}
}
}
关于c# - 统一错误 : InitWWW can only be called from the main thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42646701/