Announcement

Collapse

The Infinity Blade Forums Have Moved

We've launched brand new Infinity Blade forums with improved features and revamped layout. We've also included a complete archive of the previous posts. Come check out the new Infinity Blade forums.
See more
See less

Creating Save Games in UDK

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Creating Save Games in UDK

    Hi. I am trying to create a RPG using UDK, and there is one part I am having problems with. I need a way for the user to save their progress and then come back later. I have seen a method of creating save games using something called dll bind, but unfortunately while I am studying C++, I am still rather a C++ noob. Is this the only way to create save games from UDK? If it is (or even if it isn't) does anyone know of a really good tutorial that explains how the dll bind and C++ method works? I would not mind giving the time to learn this, but the couple tutorials I found just gave me a lot of C++ code without really explaining any of it. If this is the best method, I don't want to just copy someone else's code, I want to understand it. Any help would be greatly appreciated. Thank you.

    Raven

  • #2
    You can avoid C++ altogether and use BasicSaveObject()/BasicLoadObject() in Engine.uc:

    Code:
    /**
     * Serializes an object to a file (object pointers to non-always loaded objects are not supported)
     *
     * @param Obj The object to serialize
     * @param Pathname The path to the file to save
     * @param bIsSaveGame If TRUE, FILEWRITE_SaveGame will be used to create the file writer
     * @param Version A version number to save with the archive, so that we can safely fail when loading old versioned files
     *
     * @return TRUE if successful
     */
    native static final function bool BasicSaveObject(Object Obj, string Pathname, bool bIsSaveGame, int Version);
    
    /**
     * Loads an object from a file (saved with the BasicSaveObject function). It should already be
     * allocated just like the original object was allocated
     *
     * @param Obj The object to serialize
     * @param Pathname The path to the file to read and create the object from
     * @param bIsSaveGame If TRUE, FILEREAD_SaveGame will be used to create the file reader
     * @param Version A version number to match with the version saved in the archive, so that we can safely fail when loading old versioned files
     *
     * @return TRUE if successful
     */
    native static final function bool BasicLoadObject(Object Obj, string Pathname, bool bIsSaveGame, int Version);
    There's some documentation for it on the UnrealOnMobile page: http://udn.epicgames.com/Three/Unrea...veObject%28%29. Even though it's mentioned only on a mobile page, it works perfectly on the PC as well, giving you the added advantage of having a nice multiplatform way to save and load (and I'd presume that whenever Android and Mac OS X support comes out, these functions would work on them, whereas a DLL obviously won't). The default folder it saves to on the PC is the Binaries\Win32 folder, but you can specify an absolute path for Pathname.

    It's really simple to use, that bit of documentation is really all there is to it. The difficult part is deciding what you want to save, and what to do with the data you load in, but that's something that's really specific to you and your game.

    Comment


    • #3
      Thanks, Baldtoast! I'll check that out. ^_^

      Comment


      • #4
        Ah a nicer and quicker way to save things. Just wondering where this can be placed? Should the code be used in GamInfo or it doesnt matter.

        Comment


        • #5
          As far as I know it can be used anywhere, it's completely up to you where you want to call BasicSaveObject()/BasicLoadObject() from, or where to place the instance of the class you made to pass into them. A GameInfo subclass is a pretty logical place to put such an instance, in my opinion, assuming you intend for just the single player or server to use it. Personally I call BasicSaveObject()/BasicLoadObject() from inside my custom class that's to be saved/loaded, and just pass Self into each one.

          Comment


          • #6
            Originally posted by Baldtoast View Post
            As far as I know it can be used anywhere, it's completely up to you where you want to call BasicSaveObject()/BasicLoadObject() from, or where to place the instance of the class you made to pass into them. A GameInfo subclass is a pretty logical place to put such an instance, in my opinion, assuming you intend for just the single player or server to use it. Personally I call BasicSaveObject()/BasicLoadObject() from inside my custom class that's to be saved/loaded, and just pass Self into each one.
            you have used it ? because i have readed that this function are for saving on udk mobile, can we used it in the udk too ?

            Comment


            • #7
              Originally posted by daimaku View Post
              you have used it ? because i have readed that this function are for saving on udk mobile, can we used it in the udk too ?
              Yes, I use it with UDK for the PC and it works perfectly.

              Comment


              • #8
                thanks for the info ....

                Comment


                • #9
                  I'm having a bit of trouble with the BasicSave and BasicLoad.

                  What I did was create a class that only has a list of variables (for now 3 floats) and when I want to save I do something like this:

                  Code:
                  gameState = new class'DH_GameState';
                  gameState.VOne = 10;
                  gameState.VTwo = 10;
                  gameState.VThree = 10;
                  
                  //Then I call this:
                  class'Engine'.static.BasicSaveObject(gameState, "state.bin", true, 0);
                  I load it in a similar way but the problem is it saves and loads 0s.
                  I'm sure there is something that I don't understand. Can someone help point it out?

                  Comment


                  • #10
                    Can you post the exact code you use for saving and loading, and DH_GameState's code? Because I don't see anything wrong with that snippet that would cause it to not save or load those values.

                    Also, you're not using the 'transient' modifier for those float variables (doing so would cause those values to not be saved or loaded), are you?

                    Comment


                    • #11
                      here it is

                      Code:
                      class DH_GameState extends Object;
                      
                      var float VOne;
                      var float VTwo;
                      var float VThree;
                      
                      DefaultProperties
                      {
                      VOne = -1
                      VTwo = -1
                      VThree = -1
                      }
                      Code:
                      gameState = new class'DH_GameState';
                      if(class'Engine'.static.BasicLoadObject(gameState, "state.bin", true, 0))
                      {
                      currentVOne = gameState.VOne
                      currentVTwo = gameState.VTwo
                      currentVThree = gameState.VThree
                      }
                      I'm including only the sections in question because they are part of my large PC

                      basically the PC has 3 floats currentVOne... CurrentVThree

                      I want to save these values for now so I made 2 functions

                      One has the load and one has the save

                      Then I wrote a SeqAct which only calls the functions and in my level I set it up so that I load whenever the game starts
                      and before something happens I save

                      Edit: I also noticed that no matter what (even if I give a bogus file name) the BasicLoadObject function returns true

                      Comment


                      • #12
                        Alright I put together some code I'm using to test this:
                        Code:
                        var float currentVOne, currentVTwo, currentVThree;
                        
                        //...
                        
                        exec function TestSaveGame()
                        {
                        	local DH_GameState GameState;
                        	GameState = new class'DH_GameState';
                        	`log("GameState's initial values:"@GameState.VOne@GameState.VOne@GameState.VOne);
                        	`log("PlayerController's values:"@currentVOne@currentVOne@currentVOne);
                        	GameState.VOne = currentVOne;
                        	GameState.VTwo = currentVTwo;
                        	GameState.VThree = currentVThree;
                        	`log("Saving GameState's values:"@GameState.VOne@GameState.VOne@GameState.VOne);
                        	class'Engine'.static.BasicSaveObject(GameState, "state.bin", true, 0);
                        }
                        
                        exec function TestLoadGame()
                        {
                        	local DH_GameState GameState;
                        	GameState = new class'DH_GameState';
                        	`log("GameState's initial values:"@GameState.VOne@GameState.VOne@GameState.VOne);
                        	if(class'Engine'.static.BasicLoadObject(gameState, "state.bin", true, 0))
                        	{
                        		`log("Load successful, old values:"@currentVOne@currentVTwo@currentVThree);
                        		currentVOne = gameState.VOne;
                        		currentVTwo = gameState.VTwo;
                        		currentVThree = gameState.VThree;
                        		`log("New values:"@currentVOne@currentVTwo@currentVThree);
                        	}
                        	else
                        	{
                        		`log("Load failed, values anyway:"@GameState.VOne@GameState.VOne@GameState.VOne);
                        	}
                        }
                        I assumed from your previous post when you said "to save I do something like this" that that wasn't your exact saving code, but what you assumed currentV*'s values would be like when saving. Am I correct in assuming that your save function does indeed set GameState's variables to the PlayerController's CurrentV* values? lf so, do you give currentVOne, currentVTwo, and currentVThree any default values? Considering you mentioned that it saved and loaded 0s, and in the DefaultProperties of DH_GameState you have its default values as -1, it would seem to me the variables you're saving must actually have values of 0. Are you sure the values you're saving aren't 0? I'd put some `log() statements in there and check the values when you save it like I do in my code. If they do turn out to be 0, then the problem would seem to be that currentV* simply aren't being modified as you expect them to be.

                        I say this because, not changing the values for currentV* at all, calling TestLoadGame(); TestSaveGame(); TestLoadGame(); from the console produces:
                        Code:
                        [0008.74] ScriptLog: GameState's initial values: -1.0000 -1.0000 -1.0000
                        [0008.74] ScriptLog: Load failed, values anyway: -1.0000 -1.0000 -1.0000
                        
                        [0009.38] ScriptLog: GameState's initial values: -1.0000 -1.0000 -1.0000
                        [0009.38] ScriptLog: PlayerController's values: 0.0000 0.0000 0.0000
                        [0009.39] ScriptLog: Saving GameState's values: 0.0000 0.0000 0.0000
                        
                        [0010.08] ScriptLog: GameState's initial values: -1.0000 -1.0000 -1.0000
                        [0010.08] ScriptLog: Load successful, old values: 0.0000 0.0000 0.0000
                        [0010.08] ScriptLog: New values: 0.0000 0.0000 0.0000
                        Clearly saving and loading 0s as you described. So one way or another, I believe you are actually saving the floats with values of 0, and BasicSaveObject/BasicLoadObject is actually working correctly.
                        Edit: I also noticed that no matter what (even if I give a bogus file name) the BasicLoadObject function returns true
                        This I've never had happen. You can see in the log I posted that it does return false for me when a file doesn't exist, so I'm not sure what to say about that.

                        Comment


                        • #13
                          Would it make sense if I said that in my version gameState was a global and not local to the functions?

                          That seems to be the only difference between the 2 of us, yes I apply default values that are not 0 to all the parameters and I wasn't joking about the fact that Load would return true even if the file doesnt exist.

                          However, when I copied your functions and tested them into my code they worked well.

                          In either case thanks for all the help this was pretty much bugging me.

                          Comment


                          • #14
                            Originally posted by DanielH View Post
                            Would it make sense if I said that in my version gameState was a global and not local to the functions?
                            In this case I don't believe it would make a difference. I tried making it global in my code and the results were identical.
                            I wasn't joking about the fact that Load would return true even if the file doesnt exist.
                            I believe you, it's just that it doesn't happen to me so I can't really imagine why it happens for you or how to solve it. I guess to work around it you could store a bool in DH_GameState that defaults to false, set it to true whenever you save it, and then set it to false right after you use it with BasicSaveObject(). That way if the load does fail but returns true, you can check that bool's value to determine if it actually was loaded.
                            However, when I copied your functions and tested them into my code they worked well.

                            In either case thanks for all the help this was pretty much bugging me.
                            Glad I could help!

                            Comment


                            • #15
                              Just so that everyone is aware, this function will create directories when requested and it will also use relative directory commands. Aka, you can use...

                              Code:
                              ..\..\MySaveDirectory\MySaveGame.USX
                              And it will save to that file relative to the working directory.

                              However, be careful as it can override files!

                              Comment

                              Working...
                              X