π Lesson 8.3: Writing a C++ Plugin
A plugin is a self-contained bundle of modules, content, and assets you can drop into any project β enable it and its features appear. It's how you build reusable systems, share code across your games, and (if you like) publish to the marketplace. And it's built entirely from the module concepts you just learned.
π― Learning Objectives
By the end of this lesson, you will be able to:
- Explain what a plugin is and how it differs from a bare module
- Read a
.uplugindescriptor and its module list - Describe a plugin's folder structure
- Create a plugin with the editor's plugin wizard
- Decide when a plugin beats a module, and enable/disable plugins
Estimated Time: 60 minutes
Engine Version: Unreal Engine 5.8
In This Lesson
Plugin vs Module
A module (Lesson 8.1) is a unit of compiled C++ inside a project. A plugin is a portable package that contains one or more modules, plus its own content, assets, and descriptor β and can be moved between projects as a folder.
π The key difference: portability & toggling
A project module lives in that project. A plugin is self-contained and toggleable β enable/disable it in the Plugins browser, ship it independently, reuse it across every game you make. You've already used many: Enhanced Input, and (from your own course) the Unreal MCP plugin are exactly this β bundled modules you enable. Now you build your own.
Plugin Structure
Plugins live in a Plugins/ folder (project-level or engine-level). Each plugin is a folder mirroring a mini-project:
Plugins/
βββ MyInventorySystem/
βββ MyInventorySystem.uplugin # the descriptor (metadata + module list)
βββ Source/
β βββ MyInventorySystem/
β βββ MyInventorySystem.Build.cs
β βββ Public/ # the plugin's API (Lesson 8.1)
β β βββ InventorySubsystem.h
β βββ Private/
β βββ InventorySubsystem.cpp
βββ Content/ # optional: the plugin's own assets
βββ Resources/ # icon, etc.
β It's modules all the way down
Notice the Source/, Build.cs, and Public/Private layout β identical to Lesson 8.1. A plugin is modules plus a descriptor plus a home for content. Everything you learned about modules applies directly; the plugin just wraps them for portability. The Public/Private split especially matters here, since a plugin's public headers are the API other projects consume.
The .uplugin Descriptor
The .uplugin file is JSON that describes the plugin and lists its modules β the plugin equivalent of the Modules section in a .uproject (Lesson 8.1).
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "My Inventory System",
"Description": "A reusable inventory subsystem.",
"Category": "Gameplay",
"CreatedBy": "Ray de la Paz",
"EnabledByDefault": true,
"CanContainContent": true,
"Modules": [
{
"Name": "MyInventorySystem",
"Type": "Runtime",
"LoadingPhase": "Default"
},
{
"Name": "MyInventoryEditor",
"Type": "Editor",
"LoadingPhase": "PostEngineInit"
}
]
}
| Field | Meaning |
|---|---|
FriendlyName / Description | Shown in the Plugins browser |
CanContainContent | Whether the plugin ships its own assets |
Modules | The modules it contains, with Type & LoadingPhase (Lesson 8.1) |
Plugins (optional) | Other plugins this one depends on |
π Runtime + Editor module split
A well-structured plugin often has a Runtime module (ships in the game) and a separate Editor module (tools, custom asset editors β never shipped). Same target-type separation as Lesson 8.1, now inside a portable package. This keeps editor-only code out of your packaged game automatically.
Creating a Plugin
You rarely write the boilerplate by hand β the editor generates it. From Edit β Plugins β Add (or "+ Create Plugin") β choose a template (Blank, Blank with content, Editor Toolbar Button, etc.), name it, and Unreal scaffolds the .uplugin, Source/, module class, and build file.
The generated module implements IModuleInterface (Lesson 8.1) so you have startup/shutdown hooks:
// MyInventorySystem.cpp β generated plugin module.
#include "MyInventorySystem.h"
#include "Modules/ModuleManager.h"
#define LOCTEXT_NAMESPACE "FMyInventorySystemModule"
void FMyInventorySystemModule::StartupModule()
{
// Plugin loaded β register any plugin-wide systems here.
}
void FMyInventorySystemModule::ShutdownModule()
{
// Plugin unloading β clean up.
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FMyInventorySystemModule, MyInventorySystem)
β οΈ Enable it, and regenerate
After creating (or copying in) a plugin, make sure it's enabled in the Plugins browser and listed in your .uproject's Plugins section, then regenerate project files and rebuild (Lesson 1.3). A plugin whose modules aren't building is almost always disabled or not regenerated β the same fix as most module issues.
When to Use One
| Use a plugin when⦠| A plain module is enough when⦠|
|---|---|
| You'll reuse the system across multiple projects | The code is specific to this one project |
| You want it toggleable / optional | It's always part of the game |
| It ships its own content/assets | It's pure gameplay code in the main module |
| You'll share or sell it (marketplace) | It stays internal |
| You want a clean, isolated feature boundary | Tight coupling with game code is fine |
π‘ The reuse test: "Would I want this in my next game too?" If yes, build it as a plugin from the start β retrofitting a project module into a plugin later is more work than starting clean. A well-factored inventory, dialogue, or ability system is a natural plugin; a specific boss's AI is not.
Hands-on Exercise & Quiz
ποΈ Exercise: Package the inventory
Objective: Plan turning the inventory subsystem (Lesson 7.4) into a reusable plugin.
- Sketch the plugin folder structure for
InventoryPlugincontaining theUInventorySubsystem. - Which folder does
InventorySubsystem.hgo in so other projects can use it, and why? - Would you add a second Editor module? What might it hold?
- What's the "reuse test" answer that justifies making this a plugin?
β Answers
- Structure:
Plugins/InventoryPlugin/with.uplugin,Source/InventoryPlugin/{Build.cs, Public/, Private/}, optionalContent/. InventorySubsystem.hβPublic/, so dependent projects/modules can include it (Lesson 8.1 Public API).- An Editor module could hold a custom inventory editor window or a DataAsset editor β editor-only, never shipped.
- Inventory is a system you'd want in many games β yes, a plugin from the start.
π― Quick Quiz
Question 1: How does a plugin differ from a plain module?
Question 2: What does the .uplugin file contain?
Question 3: A system you want reusable across several of your games is best built as:
Summary
π Key Takeaways
- A plugin bundles one or more modules, optional content, and a
.uplugindescriptor into a portable, toggleable unit. - Its structure mirrors a module (
Source/,Build.cs,Public/Private) plusContent/and the descriptor β modules all the way down. - The
.upluginJSON lists modules withType/LoadingPhase; a common split is a Runtime module + an Editor module. - Create with the plugin wizard; enable it in the Plugins browser and regenerate project files.
- Reach for a plugin when a system is reusable, toggleable, or shippable; a plain module suffices for project-specific code.
π Additional Resources
π What's Next?
Module 8 is complete β you can structure, extend, and package C++ at the project level. Module 9 returns to gameplay-facing work: driving UMG user interface from C++, so your HUDs and menus are code you control.
π Module 8 complete!
Your code is organized, extensible, and packageable. Let's build some UI.