Fetching data from a database to another thread (Unity3D)

I currently have some code that fetches data from a database and renders it in unity3D. However, every time it fetches data in the FixedUpdate () function, it increases dramatically every 1 second. I'm thinking about using streams for this, but I'm not sure what I am doing wrong.

This is a function call I am on a thread.

 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;
                            }

            }

      

This code delays the scene every 1 second, so I tried to put it on the stream.

void FixedUpdate()
    {
    Thread testthread = new Thread(new ThreadStart(retrievefromDB));
        testthread.Start ();
}

      

After you put it on the stream, it continues to churn the scene after a while. Can anyone tell me what I did wrong? And how to solve this?

+3


source to share


3 answers


Finally it works. Just needed to add them to 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);
               }
            }

      

And put this in the Start () function



testThread = UnityThreadHelper.CreateThread (() =>
                                                     {
            UnityThreadHelper.TaskDistributor.Dispatch (() => retrievefromDB ());

        });

        testThread.Start ();

      

I am using threadhelper from http://forum.unity3d.com/threads/unity-threading-helper.90128/ so you can go and check it out. Thanks to everyone who helped! :)

0


source


The reason for the original problem is relatively obvious: database access is slow. If you put an inline database call in a method FixedUpdate

, you will essentially pause your game's movement while the database is accessed (which might require a second one if you need to initialize a connection, for example).

The main problem with your threading code is that you start a new thread every time it is called FixedUpdate

. This means you start 60 new threads per second (default) which cripple your game very quickly!

While it is very convenient to use C # threads in Unity for this kind of work, the best approach would be to create one thread and let it manage time rather than creating a new thread every time the job is done. This would mean creating a thread at Awake()

or Start()

instead, and then using Thread.Sleep

or similar to handle the time.



Coroutines (as suggested by Mihai in his answer) are great for timing events, but they still work in the game thread: if you put your DB code in a coroutine, you will still see pauses when they are executed, If you have to run this DB access every second, you need it in the appropriate thread.

However, did you think that database access might be unnecessary? A more efficient model might be to cache all data forward and use it from memory when you need it. (This may not be possible if the data is very dynamic, or if you are working in a memory-constrained environment such as a mobile device ...)

+4


source


Whatever you do, you need to stop accessing your database on every frame.

You only need the result once every 60 or frames. You can do this easily by using a variable where you add the time since the last call.

When it comes to multithreading in Unity, you have three options:

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
    }
}

      

+1


source







All Articles