Packaging up an Editor Plugin

Now that beta 2 is here I was hoping to package up my experimental editor plugin for others to try and dissect it from my game module. Mike Fricker mentioned there would be some semblance of the plugin system in this build so I was hoping to find out the steps I should take in packaging up my editor plugin so that it’s loadable by others.

  • Build Configurations, do I say it’s a Module vs. Game Module in the code?
  • Essential files and directory structure?
  • UBT changes for tool plugins?
  • Is there a config file my plugin needs?
  • If I made an installer, where do I install it?

Thanks!

Hey Nick! OK, we have a version of this that you can try out. Let me know how it goes.

I attached an example of a plugin that basically does nothing. But it shows the format and directory layout.

  • Make a directory called “Plugins” under your project folder. It has to be called that.
  • Unzip RocketExamplePlugin.zip into that directory. You’ll end up with a folder called MyProject/Plugins/UObjectPlugin.
  • Regenerate your project files (run GenerateProjectFiles.bat). Now you can see the code for the plugin in your solution file!
  • Rebuild your game. It will detect the new plugin and compile it!
  • When you launch the Rocket editor, it will see your plugin and load it automatically at startup.
  • You can check the Modules developer UI to make sure that it was loaded correctly.

I don’t have documentation on .uplugin file format yet, but you can look at the example to see how it works. It’s pretty simple right now. We are planning lots of changes to this stuff, so it will evolve over the next few beta releases.

Plugins can actually contain Content files too. In fact, we intend to support “only content” plugins. (e.g. a plugin that is just some blueprints, and no C++ code at all.) That part of the system still needs a lot of work, so I don’t recommend that you use it yet.

Plugins can’t override config settings and we aren’t sure that we ever want to support that yet. We’ll see.

There are also some known issues. For example, Cleaning or Rebuilding your project won’t wipe the plugin binaries.

Awesome, thanks Mike!

To distribute the sample others without source, I’m guessing I can just give them,
UObjectPlugin\Binaries…
UObjectPlugin\UObjectPlugin.uplugin

The sample works just fine, with any luck you’ll be able to download my plugin on the forums soonish.

Hey Mike!

I’ve got a little demo video of the newest version and I’m ready to post this bad boy to the forums.

Small blocking problem,

If I create a copy of the plugin and insert into another project like ShooterGame with everything except the private source, UBT attempts to create a project to rebuild the plugin, instead of what I want is for it to just a dummy project, and not actually rebuild the plugin, just make sure ShooterGame loads it.

I tried ditching the uplugin file to prevent UBT from including it in the solution as a buildable project, and that works, but then ShooterGame doesn’t load the module.

Sorry Nick. I just ran into this myself yesterday too. This will be fixed in the next release – for the next Rocket beta, I decided to omit any plugins from the build (and generated project files) that don’t have a “Source” sub-folder. I think this should work pretty well.

For now I have a workaround for you! In the distributed version of your plugin, remove all source code but keep the “*.Build.cs” files. However, hollow them out by changing the module type to be an “external” module, like this:

namespace UnrealBuildTool.Rules
{
	public class UObjectPlugin : ModuleRules
	{
		public UObjectPlugin(TargetInfo Target)
		{
			Type = ModuleType.External;
		}
	}
}

That will allow the end-user’s build tool to locate the module file, but it won’t bother trying to compile it. Let me know how that goes for you.

Btw: Plugins really shouldn’t be distributed with only “Public” source. In the context of plugins, public source headers should only be visible to sibling modules within the same plugin. We are not currently planning to support plugins that are directly dependent on other plugins, for various reasons (including some philosophical ones.)

No problem, thanks for the workaround.

Yeah, I’m not a fan of plugins depending on others in a marketplace scenario, dependency nightmare. The reason I was planning to include public was for the game, not necessarily for other plugins. Does the game count as a sibling in your mind? Because I don’t know if I want to put out a plugin that I have to let games touch my private parts to use, unless the plugin is available with source. For binary plugins there might need to be a new scope, internal, siblings and games can see the interfaces, but they aren’t available for everyone.

Do you have any thoughts on how plugins can cooperate via reflection discoverability? It would be nice if plugins had a shared method of communication and extending (optionally). Say I release the gota’ have it plugin with extension points (in the general sense, not multibox) for game code, because it has a runtime element. Plugins others write may want to participate in those extensions in a safe non-directly dependent manner. Altgough maybe it’s not worth worrying about until there’s a concrete use case. I’ll think about it some more.

Yeah, I can see how a game might want to make use of a public header from a plugin. If it’s a pure interface class than it seems reasonable, I guess we need to test it out some more. But currently its not going to be practical to do that if your public API consists of UObject declarations (huge can of worms), without having your game depend on the plugin statically, which is super-sketchy to me. You’d have to ship the import library with your plugin binaries. >< I would love to avoid stuff like that. :slight_smile: I guess we’ll see though.

Nope, workaround failed me :frowning: Here’s the non-functioning plugin. See if you can make heads or tails of it. Does the uplugin file need to be configured differently? I didn’t include it, because if I do the UBT generated solution (even with the external marker) causes several linker errors in the ShooterGame project.

[Non-Functional Plugin1

Here is the uplugin contents, if you want to try with it, should Type change once you distribute it?

{
“PluginFileVersion” : 1,

"PluginVersion" : 1,
"MinEngineVersion" : 1579795,

"Modules" :
[
	{
		"Name" : "ProductivityPack",
		"Type" : "Developer"
	}
]

}

Hey Mike!

Looks like uplugins have a very frustrating bug. Plugins don’t load debug dlls and symbols when their corresponding game project loads as debug.

Thanks. We’re fixing this for the next release. It’s kind of tricky, because if you were using a version of the tools in “debug” mode, but wanted to use redistributed plugins that don’t have debug versions available, we still need to load those too. Anyway, we’ll figure something out soon.

We’re also looking at making a change such that you can still import (and statically link) to plugins that have public source distributed (as well as a *.Build.cs files, and an import library. This is more related to your original request, where you wanted to have your game be able to subclass types defined in your plugin, which after thinking about it more and chatting with folks here, seems totally legit.

I haven’t had a chance to check out your repro above for loading redistributed plugins, but I hope to sometime tomorrow. Thanks for all of the help testing this Nick. You are on the bleeding edge here because we are only still just writing our first engine plugins now, too. :slight_smile:

–Mike

Hey Mike! Any progress?

Yes – good news. The issue that you encountered above is fixed for the next beta release!