How exactly do GAME plugins work?

I understand that the plugin system is WIP, but in the context of how it is currently I’d just like to clarify a few things:

How do we use plugin functions in our game code?

So I have a plugin in my MyProject\Plugins folder that is self-contained and compiles correctly. How do I then call a function that is defined in, for example, MyProject\Plugins\MyPlugin\Source\MyPlugin\Classes\RandomFile.h from my project’s normal game code?

My first inclination was that this has something to do with modules. I have exposed a module FMyPlugin with alias MyPlugin that I then added to the PublicDependencyModuleNames of my own project’s build file. This does not, however, cause any header files from the plugin to be loaded as dependencies for my game.

I suppose what I’m really asking is how to statically link the plugin to the code, just as stated in the documentation:

If you’re creating a game plugin (not
engine plugin), and you want to allow
the game to statically link against
one of your plugin modules

Yeah, how is that done?

Are Runtime modules also loaded into the editor plugin browser?

I have the following in my .uplugin file:

"Modules" :
[
	{
		"Name" : "MyPlugin",
		"Type" : "Runtime"
	}
]

Yet my plugin does not show up in the browser, and the module defined in the plugin is not shown to be loaded in the Modules Developer Tools window. Of course, my plugin is really for the game only so it’s not essential to see it in the editor (except to know that it is being loaded), but the documentation states that a Runtime module is always loaded.

Hey William,
It should be loaded, if you are seeing it in the modules, it may be an issue that it’s just not auto loading it, which can happen, if you press the load button it should remember and stay loaded each time you open the editor. If it’s not actually appearing in that list, check the binaries folder of your plugin for the generated DLL file. Let me know if that is not there.

Best Regards,

Ryan

Hi, thank you for the response. It’s not showing in either the plugin list or the modules list. I have the following DLL: RocketEditor-MyPlugin-Win64-Debug.dll at the path Plugins\MyPlugin\Binaries\Win64.

We are still making a lot of changes to this system so there may be some parts that aren’t working. An upcoming sample will also include a game-specific plugin that will demonstrate how this works.

For now, I can try to help you get this working. It looks like you have your directories setup correctly. If I understand, you can see your plugin’s code in Visual Studio after generating projects, and it is compiling fine when you build your game. It’s just not showing up in the Plugins Editor window right?

As for your question about Runtime plugins, yes, runtime plugins are always loaded, in both the editor and game, and even in “commandlets” by defau.t

Concerning the question about static linking to plugin modules, you should only need to add your plugin’s module name as a PrivateDependencyModuleName in the game module that needs to depend on that plugin module. This will cause the game to statically link against the plugin, allowing you to access publicly-exposed classes that are exported using either “API”-style exports (MYMODULE_API, MinimalAPI, etc) or an interface wrapper class (IMyModule.h).

–Mike

@Mike: Actually, the problem of seeing my plugin in both windows resolved itself last night somehow. I wish I knew why; but at least that part is working like it should now and it appears to always be loaded like a runtime plugin should.

Alright so I had my plugin in PublicDependencyModuleNames instead of PrivateDependencyModuleNames, I suppose private makes more sense in this case since most of my plugin code is in the private folder. Is there any other difference between these two arrays I should be aware of?

And the way I have it currently working is, I add MinimalAPI to my UCLASS() specifier in any class I want to expose as public to my game, and then tag every function I want to be callable from my game with MYMODULE_API. This works, but the problem in my other question (about the missing DLL) still exists. Is there a step missing here? Specifically, I’m interested in the interface wrapper class. It looks like that’s how you guys do OnlineSubsystem.h, which wraps not only the online subsystem classes but the module, and then those classes don’t need API specifiers…?

Sorry for all the questions, but I’m really liking this plugin system and I just want to understand it better. Thanks!

Right, the idea with interface classes is that you don’t need any API specifiers. Instead, you create an abstract class with all of the functions that you’ll need marked as virtual. Often that class will inherit from IModuleInterface, so that it can easily be exposed through the ModuleManager. You inherit that class somewhere in your plugin module’s private implementation. The consumer of your plugin can get access to that implementation through the interface when calling LoadModule(). When a module is setup this way, we call it a “dynamically loaded module”. There is no link-time dependency, because nothing was exported using MYMODULE_API (also known as __declspec(dllexport)).

You can see dozens of examples of modules setup this way in the various public headers for the editor and engine modules.

Here is the catch. There is not a good way to expose UObjects defined in your plugin to game code to use directly through an abstract interface. If your game needs to be able to instantiate, cast to, and serialize a UObject that you’ve defined in a plugin, often there is no choice but to use an API-style interface and statically link it to your game module as a PrivateDependencyModule.

–Mike

Ah I see I get it now, thank you for the detailed response!

Unfortunately yes in this case I have some custom UObjects I’d like to expose, so it seems that the API way is the way to go.

That’s totally fine. We use UObjects in plugins this same way.

–Mike