在另一个线程(Unity3D)中从数据库中检索数据
本文关键字:数据库 检索 数据 另一个 线程 Unity3D | 更新日期: 2023-09-27 17:54:01
我目前有一个代码,从数据库中检索数据,并在unity3D中可视化。但是,每次它在fixeduupdate()函数中检索数据时,每隔1秒就会急剧增加一次。我正在考虑使用线程来做到这一点,但我不确定我做错了什么。
这是我在线程中调用的函数
public void retrievefromDB(){
if (timeStep - prevTimeStep > 99) {
timeStep -= 1; //special for this dataset
query = "SELECT * FROM GridData2 WHERE timestep=" + timeStep;
if (showParent)
query += " AND (Level != 10)";
else
query += " AND (Level == 10)";
query += " AND temperature >= " + minTemp + " AND temperature <= " + maxTemp;
dt.Rows.Clear ();
dt = sqlDB.ExecuteQuery (query);
prevTimeStep = timeStep;
}
}
这段代码每1秒延迟一次,因此我试图把它放到一个线程中。
void FixedUpdate()
{
Thread testthread = new Thread(new ThreadStart(retrievefromDB));
testthread.Start ();
}
将其放入线程后,它会在一段时间后继续崩溃场景。谁能告诉我我做错了什么吗?怎么解呢?
最初问题的原因比较明显:数据库访问速度慢。如果你在FixedUpdate
方法中嵌入数据库调用,你将在数据库访问发生时暂停游戏的移动(如果你必须初始化连接,这可能需要一秒钟)。
FixedUpdate
被称为。这意味着你每秒启动60个新线程(默认情况下),这将很快削弱你的游戏!虽然在Unity中使用c#线程来完成这类工作是很好的,但更好的方法是创建一个单个线程,并允许它来管理时间,而不是每次作业运行时创建一个新线程。这意味着在Awake()
或Start()
中创建线程,然后使用Thread.Sleep
或类似的方法来处理计时。
协程(正如Mihai在他的回答中建议的那样)非常适合修复事件的时间,但它们仍然在游戏线程上运行:如果你将DB代码放在协程中,你仍然会在运行时看到暂停。如果你必须每秒运行这个数据库访问,你需要在一个合适的线程中。
也就是说,您是否考虑过数据库访问可能是不必要的?性能更高的模型可能是预先缓存所有数据,并在需要时从内存中使用它。(如果数据是非常动态的,或者运行在像移动设备这样内存受限的环境中,这可能是不可能的…)
无论你做什么,你都需要停止每帧访问你的数据库。
你只需要每60或每帧一次的结果。您可以通过使用一个变量来轻松地实现这一点,在这个变量中,您可以将上次调用后经过的时间加起来。
关于Unity中的多线程,你有三个选择:
-
用于Unity的多线程框架,如
https://www.assetstore.unity3d.com/en/!/内容/7285 -
c#内置线程
你需要注意不要从次级线程中调用Unity特定的API。发送像Vector3, Color等数据结构是可以的,但不要调用像GameObjects或Components这样的引用对象。
https://msdn.microsoft.com/en-us/library/dd321439%28v=vs.110%29.aspx -
Unity 协程
协程是Unity模拟多线程的方式。它是一个非常强大的工具,可以在同一个线程中异步运行
http://docs.unity3d.com/Manual/Coroutines.html
using System.Threading.Tasks;
public class Example
{
void StartOnDifferentThread()
{
Task.Factory
.StartNew(() =>
{
FunctionToRun();
})
.ContinueWith(task =>
{
if (task.IsCompleted)
{
// handle result
}
else if (task.IsFaulted)
{
// handle error
}
});
}
void FunctionToRun()
{
// do stuff
}
}
现在终于可以工作了。只需要在retrievefromDB()
中添加这些public void retrievefromDB(){
while(true){
if (timeStep - prevTimeStep > 99) {
timeStep -= 1; //special for this dataset
query = "SELECT * FROM GridData2 WHERE timestep=" + timeStep;
if (showParent)
query += " AND (Level != 10)";
else
query += " AND (Level == 10)";
query += " AND temperature >= " + minTemp + " AND temperature <= " + maxTemp;
dt.Rows.Clear ();
dt = sqlDB.ExecuteQuery (query);
prevTimeStep = timeStep;
}
Thread.Sleep(1);
}
}
然后写入Start()函数
testThread = UnityThreadHelper.CreateThread (() =>
{
UnityThreadHelper.TaskDistributor.Dispatch (() => retrievefromDB ());
});
testThread.Start ();
我正在使用来自http://forum.unity3d.com/threads/unity-threading-helper.90128/所以你可以去看看。感谢所有帮助过我的人!:)