~ 3.5 Minute Read.

I re­cent­ly came across a use case for hav­ing a small lo­cal data­base to store some sta­tis­tics in an Un­re­al En­gine 4 project. I found CISQLite3, a plug­in by con­flict.in­dus­tries, who un­for­tu­nate­ly seem to have gone out of busi­ness. The plug­in was re­leased un­der MIT li­cense, though, which al­lows me to a. use and b. up­date the plug­in in any use case I may have. Many thanks go out to them for choos­ing this li­cense.

You can find my fork here.

Oth­er Im­prove­ments There were a cou­ple of mi­nor things that were easy to clean up, e.g. us­ing con­st FString& in­stead of con­st FString or FString for method pa­ram­e­ters, since this avoids copy­ing the string. Oth­er cleanups I made in­clude up­dat­ing use of now dep­re­cat­ed UE4 API, ex­pose some pri­vate meth­ods that turned out to be use­ful dur­ing de­vel­op­ment, some repos­i­to­ry main­ta­nence (adding a .git­ig­nore) and a per­for­mance op­ti­miza­tion that works by al­low­ing you to leave the sqlite3 data­base open in­stead of open­ing and clos­ing it for ev­ery op­er­a­tion. In sin­gle con­nec­tion use cas­es this works great.

In­stal­la­tion Ei­ther down­load a zip and ex­tract it in­to a sub­di­rec­to­ry of your Plug­ins dir in your Un­re­al En­gine project (e.g. <MyGame>/Plugins/unreal-sqlite3/ ) or—if you al­ready use git—add it as a sub­mod­ule: cd Plugins/ git submodule add https://github.com/Squareys/unreal-sqlite3 Then en­able it in the plug­in set­tings of your Un­re­al En­gine project.

Ba­sic Use While the plug­in can do some fan­cy stuff like pop­u­late prop­er­ties of an Ac­tor, the main thing you’ll need is to run some SQL. A sim­ple ex­am­ple for a high­scores ta­ble could look like this: const FString DB_NAME = "DB" ; /* Connect to the database */ bool connect () { const FString databaseFile = FPaths :: ConvertRelativePathToFull ( FPaths :: Combine ( FPaths :: ProjectSavedDir (), FString ( "my.db" ))); if ( ! USQLiteDatabase :: IsValidDatabase ( databaseFile , false )) { if ( ! USQLiteDatabase :: CreateDatabase ( databaseFile , false )) { UE_LOG ( LogTemp , Error , TEXT ( "Couldn't create database %s" ), * databaseFile ); return false ; } else { UE_LOG ( LogTemp , Log , TEXT ( "Created database %s" ), * databaseFile ); } /* Register database, cannot be registered yet, because file did not exist. */ bool success = USQLiteDatabase :: RegisterDatabase ( DB_NAME , databaseFile , false , true ); if ( ! success ) { UE_LOG ( LogTemp , Error , TEXT ( "Couldn't register database %s" ), * databaseFile ); return false ; } else { UE_LOG ( LogTemp , Log , TEXT ( "Registered database %s" ), * databaseFile ); } /* Run some SQL without return value! */ success = USQLiteDatabase :: ExecSql ( DB_NAME , TEXT ( "CREATE TABLE Highscores(" "id INTEGER PRIMARY KEY ASC," "score INTEGER," "player TEXT" ")" )); if ( ! success ) { UE_LOG ( LogTemp , Error , TEXT ( "Couldn't create table" )); return false ; } } return true ; } Where the fol­low­ing line is one of the more im­por­tant: bool success = USQLiteDatabase :: RegisterDatabase ( DB_NAME , databaseFile , false , true ); Which reg­is­ters (stores the file­name for giv­en data­base name and checks if the file can be opened) the data­base with giv­en file, false in­di­cat­ing that the path is not rel­a­tive to the project and true keep­ing it open for per­for­mance—which you may not need, though, es­pe­cial­ly in the case of high­scores. If you do keep the data­base open, you should close it some­time: USQLiteDatabase :: UnregisterDatabase ( DB_NAME );