Hey guys, I wanted to share with you what I’ve been working on recently: as some of you have already noticed, I did a few check-ins into the master branch with plugins that should make life easier for anyone who wants to add their own scripting language integration to the engine. There’s even experimental Lua support as an example how to use/extend those plugins.
The main goal behind this is to provide a common entry point for anyone who wants to add scripting support to UE4 without having to modify the engine itself. It also shows how to use UE4 reflection system to automatically generate C++ glue code.
The basic principles how it all works are quite simple:
There’s 3 plugins:
**ScriptGeneratorPlugin **(SGP) - this is used to extend UnrealHeaderTool (UHT) functionality and generate scripting language C++ glue code using classes already generated by UHT.
**ScriptPlugin **(SP) - this is the main Engine-side plugin. This is where the glue generated by SGP is going to be compiled. Cool thing about this is that you don’t really need to include any generated code there, it’s automatically picked up by UBT! All you need to do there is to link it with the scripting language library you want to use and provide functions you might have used in SGP-generated code + maybe some additional script-specific code with helper functions etc.
It also defines:
*UScriptComponent *- contains the main entry point of execution for the scripts. More about that later.
*UScriptAsset *- this where the script source/byte code goes and is read/compiled from
**ScriptEditorPlugin **(SEP) - editor-side plugin, it’s very simple and it’s main purpose is to provide editor factories for importing scripts into UScriptAssets.
When writing this, I used Lua as proof-of-concept integration. If you want to test how it works, the only thing you need to do is to download Lua source code and copy the entire lua-5.2.3 folder (except luac.c) into Engine/Plugins/Script/ScriptPlugin/Source/ScriptPlugin, then re-generate projects and compile the engine. UBT should automatically pick this up and enable Lua integration. Note that I’m not a Lua expert and I used it because it was free/cross-platform/open and quite easy to get started with. I bet there’s people with more Lua knowledge in the community who can point out all the mistakes I did, please do!
So the idea behind UScriptComponent is that you can add it any actor and assign a UScriptAsset to it in the editor. It then initializes scripting in UScriptComponent::OnRegister(), ‘ticks’ scripts in UScriptComponent::Tick() and calls destroys script objects inside UScriptComponent::OnUnregister(). It assumes there’s pre-defined functions declared in script: Tick() and Destroy() which are called in UScriptComponent::Tick() and ::OnUnregister() respectively. For Lua integration the global scope script is called when the script is loaded in OnRegister. At that point the script context class determines if Tick() is actually defined and if not it’s not going to bother calling it. Here’s an example how Lua script would look like (sorry it’s so brief but I didn’t have time yet to come up with more elaborate examples):
print("Lua in UE4!") TickCounter = 0 Mesh = UE.LoadObject(StaticMesh.Class(), "/Engine/EngineMeshes/ParticleCube.ParticleCube"); function Tick() TickCounter = TickCounter + 1 end function Destroy() print("Destroy Lua script") StaticMesh.Destroy(Mesh); end
In the default case where Lua is not enabled, SGP uses a generic script generator which exports simple wrapper functions around public class members.
We’re probably going to be polishing this in the next two weeks a little bit, we’re also working on simplifying UHT a lot so stay tuned for more updates. I’ll probably do a blog post about this in the near future too.