/ue4-rts

Real-time strategy plugin and showcase for Unreal Engine 4.

Primary LanguageC++MIT LicenseMIT

license

Real-Time Strategy Plugin for Unreal Engine 4

Open-Source Real-Time Strategy Plugin for Unreal Engine 4 developed by the original creators of Hostile Worlds for Unreal Engine 3.

We really love the spirit of Unreal 4 moving to open-source, and we'd love to give something back.

Note that we're still in heavy development. Some things are already in place, such as

  • Camera Movement & Bounds
  • Initial Unit Placement
  • Single- and Multi-Unit Selection
  • Movement Orders
  • Stop Orders
  • Attack Orders
  • Health, Damage (and Healing), Cooldown, Range
  • Victory Conditions
  • Projectiles
  • Unit Target Acquisition
  • Control Groups
  • Health Bars
  • Minimap
  • Teams
  • Constructions
  • Unit Production/Tech Research
  • Resource Gathering
  • Fog of War

All of this is already completely working in multiplayer as well, and has been fully exposed to scripting, enabling you to update UI and play animations and sounds.

We're going to add all of this to the Unreal Marketplace for free as well soon (tm).

For a quick look, just open RTSSampleGame/Maps/RTSGameSampleMap.umap in the editor and hit Play. We recommend taking a closer look at that map as reference for your own ones as well.

Adding The Plugin

Note that the plugin currently requires a C++ Unreal project, which in turn requires a working compiler.

  1. Clone the repository.
  2. Close the Unreal Editor.
  3. Copy the RTSPlugin folder to Plugins folder next to your .uproject file.
  4. Right-click your .uproject file and select Re-generate Visual Studio project files.
  5. Build the resulting solution in Visual Studio.
  6. Start the Unreal Editor.
  7. Enable the plugin in Edit > Plugins > RTS.

Usage

Setting Up The Framewok

Make sure View Plugin Content is enabled in your view options.

  1. Create a player controller deriving from RTSPlayerController.
  2. Create a game mode deriving from RTSGameMode using that player controller.
  3. Set the number of teams for your game (e.g. 2). Compile and save.
  4. Use the new game mode in the world settings.
  5. Create a controller deriving from RTSCharacterAIController.
  6. Set the Character Behavior Tree Asset of the new controller to RTSCharacterBehaviorTree.
  7. Set the Character Blackboard Asset of the new controller to RTSCharacterBlackboard.
  8. Set the Game State Class of your game mode to any RTSGameState.
  9. Set the Player State Class of your game mode to any RTSPlayerState.

Creating Maps

  1. Add RTSPlayerStarts to the map.
  2. Set the Team Index for each player start.
  3. Add RTSCameraBoundsVolume to the map.
  4. Add a NavMeshBoundsVolume to the map, and build Navigation. You may press P to review your results in the viewport.

Setting Up The Camera

Creating The Camera

  1. Create a RTSPlayerPawn blueprint.
  2. Add a Camera component.
  3. Set the Location of the Camera component as desired (e.g. X = 0, Y = 0, Z = 1500).
  4. Set the Rotation of the Camera component as desired (e.g. X = 0, Y = 285, Z = 0).
  5. Use the RTSPlayerPawn as default pawn in your game mode.

Setting Up Camera Movement

  1. Bind the axis MoveCameraLeftRight (e.g. to Left and Right keys).
  2. Bind the axis MoveCameraUpDown (e.g. to Up and Down keys).
  3. At your RTSPlayerController, set the CameraSpeed (e.g. to 1000).
  4. At your RTSPlayerController, set the CameraScrollThreshold (e.g. to 20).

Adding Units

  1. Create a new RTSCharacter blueprint.

Note that you may use any class derived from Actor, if you want to. The plugin does not expect any kind of character whatsoever. Right now, RTSCharacter doesn't do much more than showing a nice selection circle, and relaying damage events. You can copy this functionality to any actor you like. Note that, for receiving orders such as Move or Attack, you need to derive from Pawn at least, because orders require AI.

  1. Set skeletal mesh, position, rotation, animation, capsule size and max walk speed as usual. (If you're new to the Unreal animation system, we can readily recommend the tutorial at https://docs.unrealengine.com/latest/INT/Programming/Tutorials/FirstPersonShooter/4/index.html)
  2. At the CharacterMovement component, you may set the Max Acceleration property to a high value to avoid stuttering when changing move orders.
  3. Set pawn AI controller class to your RTSCharacterAIController.
  4. Add a SelectableComponent.
  5. Add a PortraitComponent.
  6. Add an OwnerComponent.
  7. Ensure Pawn > Auto Possess AI is set to "Placed in World or Spawned".
  8. At the SelectionCircleDecalComponent of the RTSCharacter, set the Decal Material (e.g. to M_RTSSelectionCircle).
  9. You may want to disable the collision of the Mesh of your character and rely on its capsule instead.

Adding Buildings

  1. See Adding Units.
  2. Add an RTSConstructionSiteComponent and set the ConstructionTime.
  3. Set the Construction Costs to any resources required for construction.
  4. Set the Construction Cost Type to to Pay Immediately if all costs should be paid in full when starting construction, or to Pay Over Time for continuously paying costs (similar to Command & Conquer).
  5. Set the Refund Factor to the factor to multiply refunded resources with after cancelation.
  6. Set the Consumes Builders flag if builders working at the construction site should be destroyed when finished (similar to Zerg in StarCraft).
  7. Set Max Assigned Builders if you want to require a builder to work at the construction site to make progress, and/or to allow multi-building (similar to Age of Empires).
  8. Set the Progress Made Automatically and Progress Made Per Builder factors.
  9. Set the Start Immediately flag unless you want to trigger construction start from script.
  10. Add an RTSContainerComponent if you want builders to enter the building site while building.

Selecting Units

Enabling Selection

  1. Bind the action Select (e.g. to left mouse button).
  2. Bind the action AddSelection (e.g. to Left Shift).
  3. Bind the action ToggleSelection (e.g. to Left Ctrl).
  4. Add SelectableComponents to everything selectable.
  5. Listen to the OnSelectionChanged event broadcasted by the RTSPlayerController.

Showing Selection Frames

  1. Create a new HUD deriving from RTSHUD.
  2. Use the new RTSHUD in your game mode.
  3. In your RTSHUD, implement the DrawSelectionFrame event as desired.

Example: Drawing selection frame as transparent rectangle with borders

Draw Selection Frame

Enabling Control Groups

  1. Bind the actions SaveControlGroup0 to SaveControlGroup9 (e.g. to CTRL+0 to CTRL+9).
  2. Bind the actions LoadControlGroup0 to LoadControlGroup9 (e.g. to 0 to 9).

Showing Selection

  1. For each character, set the Decal Material of its SelectionCircleDecalComponent.

Enabling Unit Orders

  1. Bind the action IssueOrder (e.g. to the right mouse button). This will enable typical smart orders, such as moving when right-clicking ground, and attacking when right-clicking enemies.
  2. Bind the action IssueStopOrder (e.g. to the S key).

Setup Up Attacks

  1. Add the RTSAttackableComponent and RTSHealthComponent to any actors that can be attacked.
  2. Set the Current Health and Maximum Health properties of the RTSHealthComponent for these actors.
  3. Add the RTSAttackComponent to any actors than can attack.
  4. Add an attack to the RTSAttackComponent of these actors, setting its Cooldown, Damage, Range, Acquisition Radius and Chase Radius.

Setting the Damage Type is optional. Remaining Cooldown is handled by the framework and just exposed for scripting purposes.

Adding Projectiles

  1. Create a new RTSProjectile blueprint.
  2. Add a static mesh and any visual effects.
  3. At the ProjectileMovement component, set its Initial Speed (e.g. to 1000).
  4. For all RTSAttackComponents that should use this projectile, reference the new projectile.

Setup Victory Conditions

  1. Set the Initial Actors for your RTSGameMode. This will spawn initial units for each player at their player start.
  2. Optionally, set the Defeat Condition Actor type for your RTSGameMode. This will check whether any actors of the specified type exist for a player whenever he or she loses a unit. If no actor of the specified type remains, the player is defeated. Note that it is up to you to define how defeated players should be handled, e.g. whether you've making a 1v1, FFA or team game.

Add HUD

Showing Health Bars

  1. In your RTSHUD, set AlwaysShowHealthBars, ShowHoverHealthBars, ShowSelectionHealthBars and ShowHotkeyHealthBars as desired.
  2. If you checked ShowHotkeyHealthBars, bind the action ShowHealthBars (e.g. to the LeftAlt key).
  3. In your RTSHUD, implement the DrawHealthBar event as desired.

Example: Drawing health bars as rectangles with borders

Draw Health Bars

Showing Construction Progress Bars

  1. In your RTSHUD, set AlwaysShowConstructionProgressBars, ShowHoverConstructionProgressBars, ShowSelectionConstructionProgressBars and ShowHotkeyConstructionProgressBars as desired.
  2. If you checked ShowHotkeyConstructionProgressBars, bind the action ShowConstructionProgressBars (e.g. to the LeftAlt key).
  3. In your RTSHUD, implement the DrawConstructionProgressBar event as desired.

Showing Production Progress Bars

  1. In your RTSHUD, set AlwaysShowProductionProgressBars, ShowHoverProductionProgressBars, ShowSelectionProductionProgressBars and ShowHotkeyProductionProgressBars as desired.
  2. If you checked ShowHotkeyProductionProgressBars, bind the action ShowProductionProgressBars (e.g. to the LeftAlt key).
  3. In your RTSHUD, implement the DrawProductionProgressBar event as desired.

Showing Hovered Unit Effects

  1. In your RTSHUD, implement the DrawHoveredActorEffect event as desired.

Example: Drawing names of unit owners

Draw Player Name

Setup Minimap

Minimap Background Layer

  1. Create a new Asset > Materials & Textures > Render Target (e.g. called MinimapBackgroundRenderTarget).

  2. Set its Compression Settings to User Interface and Texture Group to UI.

  3. Create a Material from your Render Target.

  4. Set its Material Domain to User Interface and make sure the texture is connected to Final Color.

  5. Set its height to a reasonable distance (e.g. Z = 2000).

  6. Rotate it, making it face your map (e.g. Rotation Y = -90).

  7. In the Scene Capture section, assign your render target to the Texture Target of the SceneCapture2D.

  8. Disable Capture Every Frame.

  9. Still in the Scene Capture section, in the hidden settings, at General Show Flags, disable everything that doesn't make sense for a minimap background (e.g. check BSP, Landscape, Static Meshes only).

Minimap Units Layer

  1. Add a MinimapVolume at the very center of your map.
  2. Set its brush size to match the extents of your playable map.
  3. Create a new RTSMinimapWidget blueprint.
  4. Set the minimap background image to your minimap background render target material.
  5. Set the minimap background image size to a reasonable value (e.g. 256 x 256).
  6. Setup brushes for own units, enemy units and neutral units (e.g. image = WhiteSquareTexture, size = 4 x 4, tint = green, red, yellow, respectively).
  7. Add your RTSMinimapWidget to your UI, with a matching size (e.g. 256 x 256).
  8. Set its Behaviour > Visibility to Visible if the player should be able to move the camera and give orders using the minimap.

Minimap Fog of War Layer

  1. Setup fog of war (see below).
  2. Set the FogOfWarMaterial of your RTSMinimapWidget to M_RTSFogOfWarMinimap.
  3. In your player controller blueprint (or whichever owns the minimap widget), when setting up (e.g. in BeginPlay):
    1. Use the blueprint function RTSPlayerController::GetTeamInfo to get the team of the local player.
    2. Use the blueprint function GetVisionInfoForTeam to get vision info for the local player.
    3. Call SetupVisionInfo for the minimap widget.
  4. In your player controller blueprint (or whichever owns the minimap widget), handle the OnVisionInfoAvailable event and call SetupVisionInfo for the minimap widget. This is required for properly setting up vision info on clients where replication may cause a different initialization order.

Setup Building Placement

  1. Create an RTSBuildingCursor, setting its valid and invalid materials (or use BP_RTSBuildingCursor).
  2. In your player controller, set the building cursor reference.
  3. Bind any input or UI button to the BeginBuildingPlacement function of your RTSPlayerController.
  4. Bind the action ConfirmBuildingPlacement (e.g. to Left Mouse Button).
  5. Bind the action CancelBuildingPlacement (e.g. to Right Mouse Button).
  6. Bind the action CancelConstruction (e.g. to Escape).

Setup Construction

  1. Add the RTSBuilderComponent to any actors you want to be able to construct buildings.
  2. Set the Constructible Building Types for these builders.
  3. Set the Enter Construction Site if you want the builder to be unavailable while building (similar to Orcs in WarCraft).

Setup Unit Production

  1. Add the RTSProductionComponent to any actors you want to be able to produce units or research technology.
  2. Add everything you want to produce or research to the Available Products for these factories.
  3. Set the Queue Count, specifying how many products can be produced in parallel.
  4. Set the Capacity Per Queue, specifying how many products can be produced one after another.
  5. Add the RTSProductionCostComponent to everything you want to be produced.
  6. Set the Production Time for these products.
  7. Set the Resources to any resources required for production.
  8. Set the Production Cost Type to to Pay Immediately if all costs should be paid in full when starting production, or to Pay Over Time for continuously paying costs (similar to Command & Conquer).
  9. Set the Refund Factor to the factor to multiply refunded resources with after cancelation.
  10. Bind the action CancelProduction (e.g. to Escape).
  11. In your ingame UI, bind the actions of any of your buttons to call IssueProductionOrder on your player controller.

Note that, technically, producing units does not differ from researching technology. You can create actor blueprints without physical representation for each technology to research, and add them as products. Then, you can check whether any player owns an actor of that technology for checking a tech tree.

Add Resource Gathering

  1. Create an RTSResourceType blueprint for each resource in your game.
  2. Add the resource types to your player controller to enable players to keep resources in stock. Listen for the OnResourcesChanged event to update your UI.
  3. Create a unit (see above) and add an RTSResourceSourceComponent for each type of resource node in your game (e.g. gold mine, tree).
    1. Set the resource type and maximum and current resources of the source.
    2. Set the gathering factor for increaing the yield of any gatherers (e.g. golden minerals).
    3. Add an RTSContainerComponent, check Gatherer Must Enter and set the Gatherer Capacity if you want gatherers to enter the resource source (e.g. Refinery in StarCraft).
  4. Create a unit (see above) and add an RTSResourceDrainComponent for each type of building gatherers may return resources to.
    1. Set the resource types to all resources accepted by the drain.
  5. Create an RTSGathererComponent to any unit that should be able to gather resources.
    1. Add any resource type the gatherer should be able to gather to Gathered Resources.
      1. Gathering works similar to attacks, with "damage" and "cooldown". Set Amount Per Gathering to the value to add to the gatherers inventory each time the cooldown is finished.
      2. Set the Cooldown to the time between two gatherings.
      3. Set the Capacity to the amount of resources the gatherer can carry before returning to a resource drain.
      4. Check Needs Return To Drain if the gatherer needs to move to another actor for returning resources (e.g. Age of Empires). Uncheck if they should return all gathered resources immediately when hitting the capacity limit (e.g. Undead in WarCraft).
      5. Set Range as desired.
    2. Add all Resource Source Actor Classes the gatherer may gather from (e.g. Undead in Warcraft need Haunted Gold Mine).
    3. Set the Resource Sweep Radius to the radius in which the gatherer should look for similar resources if their current source is depleted.

Setup Fog of War

  1. Add the RTSVision component to your units and set their Sight Radius (e.g. 1000).
  2. Add an RTSVisionVolume to your map, encompassing the whole valid visible map area (e.g. 4096x4096).
  3. Set the Size Per Tile of the vision volume (e.g. 16).
  4. Add a PostProcessVolume to your map, encompassing the whole valid camera area.
  5. Add an RTSFogOfWarActor to your map.
  6. Set the Fog Of War Material of the actor (e.g. to the M_RTSFogOfWar material shipped with the plugin).
  7. Set the Fog Of War Volume reference to the post process volume created before.

Bugs & Feature Requests

We are sorry that you've experienced issues or are missing a feature! After verifying that you are using the latest version and having checked whether a similar issue has already been reported, feel free to open a new issue. In order to help us resolving your problem as fast as possible, please include the following details in your report:

  • Steps to reproduce
  • What happened?
  • What did you expect to happen?

After being able to reproduce the issue, we'll look into fixing it immediately.

Contributing

You'd like to help make this plugin even more awesome? Seems like today's our lucky day! In order to maintain stability of the tool and its code base, please adhere to the following steps, and we'll be pleased to include your additions in our next release.

Note that this plugin is distributed under the MIT License. So will be your code.

Step 1: Choose what to do

If you've got no idea how to help, head over to our issue tracker and see what you'd like to do most. You can basically pick anything you want to, as long as it's not already assigned to anyone.

If you know exactly what you're missing, open a new issue to begin a short discussion about your idea and how it fits the project. If we all agree, you're good to go!

Step 2: Fork the project and check out the code

Real-Time Strategy Plugin for Unreal Engine 4 is developed using the GitFlow branching model. In order to contribute, you should check out the latest develop branch, and create a new feature or hotfix branch to be merged back.

Step 3: Implement your feature or bugfix

Real-Time Strategy Plugin for Unreal Engine 4 is based on Unreal Engine 4.16.1.

Step 4: Open a pull request

Finally, open a pull request so we can review your changes together, and finally integrate it into the next release.

License

Real-Time Strategy Plugin for Unreal Engine 4 is dual-licensed: