Lyra for a Singleplayer Narrative Third-Person Game Solo Project

Hi,

I am developing a singleplayer narrative single experience third-person game (with inventory and skill tree) in kind of a solo project (UE 5.2). I already learned a lot about Unreal, GameplayAbilities and Lyra during the past 1,5 years. I’d really like to have my game based on a decent software design.

A couple of weeks ago I started implementing my own basic ability system getting inspiration from the official GAS. In the end I created a new (3rd) repository from scratch using the offical GAS. I successfully isolated a copy of the Lyra enhanced input to native/ability GameplayTag system and integrated it into my project.

Questions

  1. Should I create a 4th repo based on Lyra with own subclasses getting updates through git? Or
  2. Should I stick to my 3rd repo and only take what I need from Lyra?

What is your opinion about this regarding the scope of my solo game project (already using GAS and Enhanced Input to GameplayTags), considering me being kind of a perfectionist with limited time?

See https://x157.github.io/UE5/LyraStarterGame/Development-Considerations

Appendix: Example Inventory System

IMHO Lyra uses far to many abstraction layers for what I’d like to achieve. The inventory system for example:

ULyraInventoryManagerComponent

class LYRAGAME_API ULyraInventoryManagerComponent : public UActorComponent
└─FLyraInventoryList InventoryList;
	└─TArray<FLyraInventoryEntry> Entries;
		├─int32 StackCount = 0;
		└─TObjectPtr<ULyraInventoryItemInstance> Instance = nullptr;
			└─TSubclassOf<ULyraInventoryItemDefinition> ItemDef;
				└─TArray<TObjectPtr<ULyraInventoryItemFragment>> Fragments;

ULyraInventoryItemDefinition

TSubclassOf<ULyraInventoryItemDefinition> ItemDef;
└─TArray<TObjectPtr<ULyraInventoryItemFragment>> Fragments;
	└─UInventoryFragment_EquippableItem
		└─TSubclassOf<ULyraEquipmentDefinition> EquipmentDefinition;
			├─TSubclassOf<ULyraEquipmentInstance> InstanceType;
			|	└───TArray<TObjectPtr<AActor>> SpawnedActors;
			|
			├─TArray<TObjectPtr<const ULyraAbilitySet>> AbilitySetsToGrant;
			|
			└─TArray<FLyraEquipmentActorToSpawn> ActorsToSpawn;
				├─TSubclassOf<AActor> ActorToSpawn;
				├─FName AttachSocket
				└─FTransform AttachTransform;

I was thinking about creating my own inventory system using ItemDefinitions but not Instrances, EquipmentDefintions etc.:

class UMyInventoryComponent: public UActorComponent
└─TArray<FMyInventorySlot> InventorySlots;
 └─FMyInventorySlot
  ├─int Count = 0;
  └─TSubclassOf<UMyInventoryItemDefinition> ItemDef;
	 └─TArray<TObjectPtr<UMyInventoryItemFragment>> Fragments;
	  ...
	  └─UInventoryFragment_EquippableItem
	   ├─TArray<TObjectPtr<const UMyAbilitySet>> AbilitySetsToGrant;
	   ├─TSubclassOf<AActor> ActorToSpawn;
	   ├─FName AttachSocket;
	   └─FTransform AttachTransform;

Btw. I already tried to isolate the lyra inventory system (see https://x157.github.io/UE5/LyraStarterGame/Inventory/) without success. Seems to be to depended on other parts of Lyra.

Thanks in advance for your thoughts.

1 Like

Personally, I would suggest to sticking with your own project and just stealing some code here and there.

Lyra is great and many of its systems make sense, especially for a multiplayer game. But for simpler singleplayer games, it’s just unnecessarily complicated. If you don’t already understand how efficient and extendable multiplayer games work, then trying to learn Lyra’s architecture is just going to be a waste of time.

1 Like

Thank you for your answer. I’m going to not base my game on Lyra, because as you already mentioned, it’s just too much tailored for multiplayer, and modularity that I actually don’t need. I might benefit from the learnings, but it would cost too much time and probably kill my solo project.

I’m going to use the Gameplay Ability System and have my inventory system inspired by Lyra with kind of Item Definitions, but much simpler.

That’s how I would do it too. GAS is great and item definitions are very important if you want to keep your memory usage controlled.

1 Like

That’s how I would do it too. GAS is great and item definitions are very important if you want to keep your memory usage controlled.

Do you mean item definitions keep memory usage controlled, because the alternative, storing AActor Classes directly in an inventory would bloat memory?

What I mean is Item Definitions allow multiple Item Instances to share some of the ‘static’ data between the instances. For example in Lyra, there isn’t a need to store all the basic weapon attributes of a given type within every single weapon instance of that type.

Imagine if you had 50 of the same weapon type in the level. It’s just a waste of memory, can increase network replication, increases save/load storage and time, and more room for accidental bugs.

The idea is to only store values that can change between instances in the actual Item Instance object. Even data that you want to be part of the definition but want to change in the instance can also be done by adopting a ‘modifier’ approach - where the instance never actually stores the absolute value but has a function that applies its modifier on top of the definition’s value.

Using static variables is one way to do something similar but you can’t use inheritance with static variables so it doesn’t really work that well.

There are similar but alternative ways to how Lyra does it in case something else feels more natural to you. For example, I would probably use DataAssets instead of classes.

Of course, none of this matters for a small game but it is something to be aware of in case you ever do work on a project that can involve many instances of the same item.

1 Like