我在Unity中创建了一个菜单,该菜单由SQLite DB的结果填充。但是当我创建菜单时,整个游戏会在查询数据库时冻结片刻。
为了解决这个问题,我试图将菜单的创建与数据填充分开(即菜单只会说"加载"直到查询完成)。
我一直试图使用收益回报协同程序来做到这一点,但游戏仍在冻结。下面我有一些伪代码说明我在做什么......
void createMenu () {
// code to create menu...
StartCoroutine(getData());
}
IEnumerator getData () {
List<string> sqlResults = Database.query("SELECT * FROM table");
yield return null;
updateMenu();
}
void updateMenu() {
// replaces "loading" strings with sql data results
}
我是以错误的方式解决这个问题,还是我错误地使用了协程?
答案 0 :(得分:4)
看起来数据库操作阻塞了主线程。使用ThreadPool.QueueUserWorkItem
函数在新线程中运行它。完成后,使用this帖子中的UnityThread.executeInUpdate
功能调用updateMenu()
功能。您需要从this发布UnityThread
课程才能使用此解决方案。
void Awake()
{
UnityThread.initUnityThread();
}
void runQuery(string query)
{
ThreadPool.QueueUserWorkItem(RunInNewThread, query);
}
private void RunInNewThread(object a)
{
string query = (string)a;
List<string> sqlResults = Database.query(query);
//We are in another Thread. Use executeInUpdate to run in Unity main Thread
UnityThread.executeInUpdate(() =>
{
updateMenu();
});
}
<强> USAGE 强>:
runQuery("SELECT * FROM table");
答案 1 :(得分:1)
是的,将此代码放在协程中,因为您不会更改任何内容。 Unity是单线程的,但是你可以启动一个单独的线程来完成一些工作,只要它们不调用在该线程中执行的任何Unity函数。
试试这个:
IEnumerator getData () {
List<string> sqlResults;
var thread = new System.Threading.Thread(() => {
sqlResults = Database.query("SELECT * FROM table");
};
thread.Start();
while(thread.IsAlive){
yield return null;
}
updateMenu();
}
答案 2 :(得分:0)
所以这里的问题是你正在与服务器同步而不是异步,这将使你等待连接或查询(如果它给你一些错误或它的错误查询你将等到超时httprequest或db请求)。 尝试使用异步函数而不是枚举器,或者使用async fucntion调用的enumator,它可以让你在检索信息时进入菜单。