Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question: Using the Update() function with a database? Is it a good idea?

Discussion in 'Scripting' started by heinickesg, Jun 10, 2014.

  1. heinickesg

    heinickesg

    Joined:
    Jan 25, 2013
    Posts:
    48
    So with my setup I am saving the player's X, Y and Z to a database, currently I have these values set to save using OnApplicationQuit().

    However this presents a problem, The application quits before it actually finishes sending the data, resulting in the data not being sent at all. So I thought of an alternative but im not sure if I want to do this,

    I was gonna use the Update() function to send these values to the database in real time, But is that a good idea? My thought is it could bog down things, such as spamming the database with information. What would be the best way to handle this? Should I use an update function or is there some code that can save it periodically, or can I slow down the application quitting? The other thought I had was doing something like having a "quit" button, Which would run the code, check if its done, then quit the game. Problem is, what if the game crashes? Or the user doesn't quit properly? (like alt+f4) the data would never be saved and the user would lose their position.

    Any help/thoughts would be very helpful.

    Thanks in advance!
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,738
    I certainly wouldn't recommend doing it every frame. I'm not a database guy, but I'm pretty sure that querying it 60 times a second is bad.

    You can put it in OnApplicationQuit, and in that function, use CancelQuit to hold off on quitting until you succeed with the database query.
     
  3. applejuices

    applejuices

    Joined:
    Nov 20, 2013
    Posts:
    80
    You can use a script to invokeRepeat every minute or so to write that.
     
  4. heinickesg

    heinickesg

    Joined:
    Jan 25, 2013
    Posts:
    48
    Both sound like good ideas, However for the CancelQuit,If I am understanding this it only delays it by a few seconds. But I want to wait until the data is actually saved. I might have to make a script that saves it periodically.
     
  5. IamGawd

    IamGawd

    Joined:
    Jun 7, 2014
    Posts:
    21
    You could use a while statement if you can set a count of how much info must be sent before closing. So it will continue to loop sending data until you have sent the required amount then below that statement you can place an application quit, and it will quit when finished.
     
  6. nailo2532

    nailo2532

    Joined:
    May 27, 2014
    Posts:
    4
    If it always takes the same amount of time to write the position you could use waitforseconds()
     
  7. heinickesg

    heinickesg

    Joined:
    Jan 25, 2013
    Posts:
    48
    If the player has a slower connection than mine, won't I still have the same problem of it quitting before the data is sent?
     
  8. nailo2532

    nailo2532

    Joined:
    May 27, 2014
    Posts:
    4
    hmm, good point, can you do a check while running to test how long it takes and then have the wait set to whatever the test returned? Just write a function that that checks the time before sending, the time after the data is written and return the difference?
     
  9. IamGawd

    IamGawd

    Joined:
    Jun 7, 2014
    Posts:
    21
    If you use a while statement if will not let your code continue until it has met the requirement stated by the while statement. It will loop until finished.
     
  10. heinickesg

    heinickesg

    Joined:
    Jan 25, 2013
    Posts:
    48
    Hmm so using the while statement idea, could i make a bool "datasent = false" then do something like

    Code (csharp):
    1. While(datasent == false)
    2. {
    3. Cancelquit(); //or whatever it was
    4. }
    Then simply set datasent = true at the end of my code? Would that work?
     
  11. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
  12. heinickesg

    heinickesg

    Joined:
    Jan 25, 2013
    Posts:
    48
    Good point, Think I will use that alternative and slightly alter it then. Thanks all :)
     
  13. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    You should also notice the information in the documentation about how it has limited use depending which platform you're on.

    Now you talk about doing it every update. Which compared to on quit... those are 2 different events. Update would be something that was like persistently updating the database, where as on quit is only updated... on quit.

    Those are two way different behaviors.

    What behavior do you want?



    Here's what I would do. I'd create a class, lets call it 'DBUpdateManager'. This will have a static interface that allows registering 'DBUpdatable' components to it.

    'DBUpdatable' is an abstract class that inherits from MonoBehaviour, and you'd implement special versions of it for the kind of updating that would need to be done.

    Implement the Awake/Start method in DBUpdatable, this way all concrete versions of it inherit this behavior. Making it protected virtual, so that way you can override the Awake/Start method with out overwriting it (it's just the way unity works with messages). In this Awake/Start method you'll register the component to the manager.

    Implement the OnDestroy method as well, where it will unregister itself from the manager.

    Also define an abstract method 'CommitToDB(db...)' that all DBUpdatables must update. Include any parameters needed to it (the db you'll be writing to? The serializer object you use to wrap the db? Whatever).

    The manager will have 4 static methods:

    RegisterUpdatable(DBUpdatable c)
    UnregisterUpdatable(DBUpdatable c)
    UpdateDB()
    UpdateDBAsync()

    Register and Unregister are used to add and remove the updatable objects to the manager.

    The other 2 can be used to update the database either blocking or async. Both will just loop over all the registered components, and call the CommitToDB(db...) method. Allowing each object to save itself.

    Then in each special version of DBUpdatable, you override the CommitToDB method and write whatever special data you need to write to the db for that object.


    NOW, you can call these methods whenever. Maybe set up a coroutine that runs it ever 5 minutes. Call it ALSO when the application quits. You could have special events when it happens... such as the end of a level, or after a boss battle, or some other event. All you do is just call the method and let it run in one easy line of code.


    You may want to add a 'DestroyOnDB' method to the manager and DBUpdatable classes. This would allow puring data from the db all together.
     
  14. heinickesg

    heinickesg

    Joined:
    Jan 25, 2013
    Posts:
    48
    Ok that makes some sense, The way I have my system running here, Is a script handles all the database connection. I'll give a rundown.

    The actual player has a script on him that broadcasts his position in an Update() Function
    This broadcast is sent to a static variable inside a script conveniently named, PlayerVariables.CS
    From here all I do is call

    Code (csharp):
    1. savePlayerPosition()
    the pass the X,Y and Z values as arguments.
    This call is sent to the actual database script and that script sends the information to the database.

    What I want is to be consistent, so no matter how or when the player logs off, he/she doesn't get back on and be like "What on earth? I didn't log off here...."