Creating Plugin-Based Game Code - Sept 6th - Live From Epic HQ

WHAT
and will be laying the groundwork for plugin-based game code! Game systems written as plugins can be ported easily from one project to another and are a good way to build game-agnostic systems. The plugin we’re going to build will be usable as a state machine, a valuable concept for many different types of games.

WHEN
Tuesday, September 6th @ 2:00PM ET Countdown]

WHERE

WHO

  • Sr Learning Resource Engineer
  • Senior Technical Writer -

Feel free to ask any questions on the topic in the thread below, and remember, while we try to give attention to all inquiries, it’s not always possible to answer’s questions as they come up. This is especially true for off-topic requests, as it’s rather likely that we don’t have the appropriate person around to answer. Thanks for understanding!

Assets: https://forums.unrealengine.com/showthread.php?122369

Archive:

1 Like

This one is going to be interesting, can’t wait :slight_smile:

much appreciated, this will be very helpful for a lot of people, including me.

PD: the countdown link seems broken to me

It seems like the timer is not working.

Will be interesting to see how you do it, considering that at the moment, a plugin can’t know anything about your game or vice versa.

And last time I’ve read the documentation, it said that it was extremely unrecommended to have plugins depend on each other.

So it’ll be interesting how you solve this.

I guess you can do a linear dependency, but that’s sort of cheating, because it only accommodates a particular case of game mechanics. When you start streaming, could you explain a bit about how you’re going to solve this issue in your plugin based game?

Thanks.

Upd: also, the countdown link doesn’t work.

The countdown link seems to be missing a letter (how did this happen?)

me too quite interested to know how it work.
will watch that one :slight_smile:

This is exactly what I’m trying to do with my project…any of content in plugins? :slight_smile:

Oh my area of interest; didn’t see this one :slight_smile:

Content in plugins is working, I know the docs still say it’s kind of unsupported but in practice it’s fine - there are plugins on the marketplace containing content.

Yes; I’ve been using Content folders in plugins for a while now.

I’m going to repeat my questions from the stream as they got misinterpreted. Hopefully someone can help out.

  1. Do engine plugins need to be explicitly disabled to not be linked?
    If someone uses one of my plugins in their project, most likely they will make use of it via types exposed to blueprint and not add any dependencies in their .build.cs files. Nonetheless, my plugin, assuming it’s enabled, will be packaged and linked into their game. So, since many engine plugins are enabled by default, does this mean that they are all getting linked to a project executable even if they are not being used? Most projects won’t use most plugins, so if this is the case it would be a pretty big unnecessary overhead.

  2. Are config files in plugins coming any time soon?
    Paper2D does not have any config files, contrary to what was stated. I’m referring to the ability to provide config values that will be processed as part of the config hierarchy in projects in which the plugin is used. So for example, we could add custom collision channels or configure things like the online subsystem in the plugin, and not have to give instructions to users to modify project config files themselves to make the plugin work as intended.

  3. Why are .lib files generated by the RunUAT BuildPlugin command so much bigger than those in Launcher engine plugins?
    When I package a plugin with the automation tool, I’m getting non-editor build .lib files in the region of 30MB+, whereas those that come with the engine are rarely above a couple of MB. Why is this, and is there some flag I can use to generate smaller .libs?

Thanks.

When you execute a packaged game of an empty project, the engine does this; so, yep. All the runtime engine plugins are all loaded by default:



LogPluginManager: Loaded Plugin SlateRemote, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Slate/SlateRemote/SlateRemote.uplugin
LogPluginManager: Loaded Plugin WindowsMoviePlayer, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Runtime/WindowsMoviePlayer/WindowsMoviePlayer.uplugin
LogPluginManager: Loaded Plugin SteamVR, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Runtime/Steam/SteamVR/SteamVR.uplugin
LogPluginManager: Loaded Plugin ProceduralMeshComponent, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Runtime/ProceduralMeshComponent/ProceduralMeshComponent.uplugin
LogPluginManager: Loaded Plugin OculusRift, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Runtime/OculusRift/OculusRift.uplugin
LogPluginManager: Loaded Plugin OculusLibrary, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Runtime/OculusLibrary/OculusLibrary.uplugin
LogPluginManager: Loaded Plugin OculusInput, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Runtime/OculusInput/OculusInput.uplugin
LogPluginManager: Loaded Plugin GearVR, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Runtime/GearVR/GearVR.uplugin
LogPluginManager: Loaded Plugin ExampleDeviceProfileSelector, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Runtime/ExampleDeviceProfileSelector/ExampleDeviceProfileSelector.uplugin
LogPluginManager: Loaded Plugin CustomMeshComponent, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Runtime/CustomMeshComponent/CustomMeshComponent.uplugin
LogPluginManager: Loaded Plugin CableComponent, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Runtime/CableComponent/CableComponent.uplugin
LogPluginManager: Loaded Plugin ArchVisCharacter, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Runtime/ArchVisCharacter/ArchVisCharacter.uplugin
LogPluginManager: Loaded Plugin OnlineSubsystemUtils, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Online/OnlineSubsystemUtils/OnlineSubsystemUtils.uplugin
LogPluginManager: Loaded Plugin OnlineSubsystemNull, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Online/OnlineSubsystemNull/OnlineSubsystemNull.uplugin
LogPluginManager: Loaded Plugin OnlineSubsystem, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Online/OnlineSubsystem/OnlineSubsystem.uplugin
LogPluginManager: Loaded Plugin UdpMessaging, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Messaging/UdpMessaging/UdpMessaging.uplugin
LogPluginManager: Loaded Plugin WmfMedia, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Media/WmfMedia/WmfMedia.uplugin
LogPluginManager: Loaded Plugin AvfMedia, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Media/AvfMedia/AvfMedia.uplugin
LogPluginManager: Loaded Plugin AndroidMedia, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Media/AndroidMedia/AndroidMedia.uplugin
LogPluginManager: Loaded Plugin CharacterAI, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Experimental/CharacterAI/CharacterAI.uplugin
LogPluginManager: Loaded Plugin LightPropagationVolume, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/Blendables/LightPropagationVolume/LightPropagationVolume.uplugin
LogPluginManager: Loaded Plugin Paper2D, From C:/Users/Bruno/Desktop/WindowsNoEditor/Engine/Plugins/2D/Paper2D/Paper2D.uplugin


Here is an example of a Plugin saving settings to the INIs inside the Config folder of the project; the user don’t have to edit anything, the Plugin’s UObject will save the INI automatically.
The plugins save to the Game Projec’s Config folder, it can’t have a Config folder for itself:

.h:



 UCLASS(ClassGroup = UserSettings, Category = "Settings", config = GameUserSettings)
 class MYGAME_API ULoginSettings : public UObject {
     GENERATED_BODY()
 public:
     UPROPERTY(Category = "Settings", EditAnywhere, BlueprintReadWrite, config)
     FString UserName;
 
     UPROPERTY(Category = "Settings", EditAnywhere, BlueprintReadWrite, config)
     FString UserPass;
 
     UFUNCTION(Category = "Settings", BlueprintCallable)
     void SaveCredentials(const FString InputName, const FString InputPass);
 
     UFUNCTION(Category = "Settings", BlueprintCallable)
     void ValidadeCredentials(const FString InputName, const FString InputPass);
 
 };


.cpp:



 void ULoginSettings::SaveCredentials(const FString InputName, const FString InputPass) {
 
      UserName = FMD5::HashAnsiString(*InputName);
      UserPass = FMD5::HashAnsiString(*InputPass);
 
      this->SaveConfig();
 }
 
 bool ULoginSettings::ValidadeCredentials(const FString InputName, const FString InputPass) {
 
      return (FMD5::HashAnsiString(*InputName)==UserName && FMD5::HashAnsiString(*InputPass)==UserPass);
 
 }


Check in project’s Config folder, the GameUserSettings INI file;
Both UserName and UserPass will be there right after you call this->SaveConfig();.

Reading back the value in Game code, from the settings saved by the Plugin:



 const auto &LoginSettings = GetMutableDefault<ULoginSettings>();
 
 UE_LOG(LogTemp,Warning,TEXT("%s :: %s"),*LoginSettings->UserName,*LoginSettings->UserPass);


Thanks. Well, it figures, but am I the only one thinking it’s pretty bad that this happens by default? Surely one of the benefits of breaking some of the engine code out into plugins is that you don’t have to include a bunch of stuff your project doesn’t need, but I bet most people aren’t aware they get all this stuff by default.

I really think the plugin dependencies need some work so there is a distinction made between ‘being enabled when you open the project in the editor’ and ‘being a dependency that gets linked in’. The former shouldn’t imply the latter.

Yep I know plugin objects can have their own config values, but that’s not what I was referring to. This doesn’t allow you to provide overrides for engine level config properties, which would be required for the examples I gave. Ideally, you should be able to add a PluginInput.ini, PluginEngine.ini etc, which would be processed as part of the config hierarchy, after the config files in the engine folder, but before those in a project folder. So plugins could override engine values, but project config files would have the final say.

Why override values when you can pick the UObject used by these engine and game INI values, change them as usual then call SaveConfig() …
All it takes is digging into the engine source and find the name of these UObject classess then call GetMutableDefault() on them from your plugin, change the object’s variables then save it. Just like the Settings panel does in Editor.

Because that will write values out to project config files. I don’t want to trample on the project level files of people that use my plugin, I just want to override engine defaults and let the project override my values.

Besides, the whole point of using config files is that you can modify values without hard coding it into source.

Probably i miss it during livestream but how to re-use a plugin in another project? I only have to compile it and copy/paste the dll? :slight_smile:

Just copy and paste the plugin.

And if i don’t want to share the plugin source code?