I’m trying to develop a system where players can create new unit NPCs, using the Lyra game framework. This is using the dedicated server model. The NPC units are similar in nature to those from an RTS - Different classes of units players can create, units are on the same team as the player but not considered players themselves.
I’m unable to use the included LyraBotCreationComponent, as that system creates player bots, spawning them using GameMode->RestartPlayer(NewController).
I’ve created a widget that pops up and allows the player to select which units to spawn. That much, at least, works. Widget appears, buttons are interactable.
Where I’m having difficulty is in getting the command to spawn the unit to the server.
What almost works is creating a simple Game State Component, adding it to the experience like this, and calling it from the widget like this. It actually works perfectly! Problem is, this solution only works in Standalone or Listen Server mode. Calling it as a client results in:
LogNet: Warning: UNetDriver::ProcessRemoteFunction: No owning connection for actor LyraGameState_0. Function OrderUnit will not be processed.
I’ve tried routing the request through the player controller instead, however that results in an invalid spawn request that kicks me out of the game back to the main menu.
I have a feeling the ideal solution may lie within Lyra’s subsystems, but I’m just not familiar enough with them to see it. Can anyone help?
Updating this because I found a novel solution that may help others. Lyra’s implementation of the Gameplay Ability System solves this nicely as its replication is easy to manage. System goes: Widget (create order via gameplay event) > Gameplay Ability (order received on both server and client, parse payload tags into refs) > Controller Component (update UI and spawn/queue unit)
From the unit order widget, fire a gameplay event to the pawn. Event Tag will be an input tag for a new gameplay ability “Order Unit”. Put whatever information is needed to create the correct pawn into the GameplayEventData payload. I use tags, as they can be mapped to classes or linked to objects by a unique variable value down the road. Instigator tags have the unit class, target tags have the unit’s run path (array of IDs for linked spline objects).
Create the Order Unit gameplay ability and add it to the hero unit’s ability set, linked to the input tag set in #1. Pull payload data from the ActivateAbilityFromEvent event and turn your tags into actual refs as needed. I have a “tag to class map” that assigns a unit class to whatever tag is passed in, then a “tag to path map” that assigns a path array. Create a “unit order” struct that includes actual refs for everything (incoming unit class, path array, ordering unit controller, and ordering unit team integer).
Create a controller component to manage the unit ordering and attach it to your player via the game type’s “components” action set data asset. Create a “create unit” function that uses the unit order struct as an input parameter. From the ordering gameplay ability, pass the packaged unit order struct into the controller component (Gameplay event instigator > get component by class).
The controller component receives the order on both the server and the client, so you can use the event to update the UI on the client and build/queue the unit on the server. I use a queue, so each unit fires a local event after they’re spawned to notify the component they’ve been built.