Beings Beyond

Engage in thrilling and strategic combat alongside your loyal companions, utilizing their unique abilities to overcome formidable adversaries.

Highlights

  • Extended Unreal Engine’s Gameplay Ability System to work with turn-based abilities and effects
  • Implemented a custom Utility AI plugin for modeling the behavior of creatures in combat
  • Developed a reusable solution for inventory management across multiple game systems
  • Created tools for streamlining the creation process for character assets

Gameplay Trailer

Full Demo Gameplay

Overview

Beings Beyond is a turn-based action game where you tame and fight alongside creatures that will aid you in your journey of restoring a long-abandoned planet.

Combat Design and Implementation

The combat mechanics were inspired by a few turn-based games (e.g. Saiyuki: Journey West, Honkai: Star Rail, Shadow Hearts: Covenant, etc.) I have played or researched that had me curious about a combination of their elements.

The challenge in this aspect was trying to combine these elements in a way that could make sense for my envisioned game setting without making the combat feel like a hodgepodge of the aforementioned elements.

Tap-timing

Elemental Affinities and Reactions

Gameplay Ability System (GAS) Implementation

Developing a cohesive and flexible solution for abilities and effects can become unwieldy, which was why I was excited to experiment with the GAS framework.

At the time of development (using UE 5.2 ), I had to create a workaround for turn-based effects since Gameplay Effects would only work well out of the box for realtime gameplay.

I originally tried using the built-in stacks from the GameplayEffect class to track an effect’s remaining turns, but it did not work well with effects that needed to stack. So, I created a system that would filter certain effects that have “turn-based” gameplay tags and keep track of handles that belong to those effects.

Filter applied effects for turn-based effects

// This is a callback that receives and filters every GameplayEffect that is applied to the owner ASC for effects that have the required "turn-based" GameplayTags.
void UBongoTurnBasedGlobalAbilitySystem::HandleGameplayEffectAppliedToSelfASC(UAbilitySystemComponent* ASC, const FGameplayEffectSpec& Spec, FActiveGameplayEffectHandle ActiveHandle)
{
	Super::HandleGameplayEffectAppliedToSelfASC(ASC, Spec, ActiveHandle);

	if (ActiveHandle.IsValid())
	{
		if (const UGameplayAbility* AbilityInstance = UBongoAbilitySystemBlueprintLibrary::GetGameplayAbilityInstanceFromActiveEffectHandle(ActiveHandle))
		{
			if (const UBongoTurnBasedGameplayAbility* TurnBasedGameplayAbilityInstance = Cast<UBongoTurnBasedGameplayAbility>(AbilityInstance))
			{
				FGameplayTagContainer AssetTags;
				Spec.GetAllAssetTags(AssetTags);

				// Return if it's not a turn-based effect.
				if (!AssetTags.HasTag(TurnBasedGameSettings->Tag_TurnBasedEffect)) return;

				const bool bTracked = FBongoActiveTurnBasedEffectSpec::GetGlobalMap().Contains(GetTypeHash(ActiveHandle));
				const int32 Turns = TurnBasedGameplayAbilityInstance->GetTurnBasedEffectDuration(ActiveHandle);

				// Create new effect spec.
				const FBongoActiveTurnBasedEffectSpec NewSpec { ActiveHandle, Spec, Turns };

				// Skip if continuous, non-stackable, active handle is already tracked
				if (bTracked && (NewSpec.IsContinuous() && !NewSpec.IsStackable())) return;

				// Prevents ticking effects applied just now. We defer their first tick to the next tick.
				if (bTicking)
				{
					NewEffectSpecsFromTick.Add(NewSpec);
				}
				else
				{
					NewSpec.AddToGlobalMap();
				}
			}
		}
	}
}

Tick method for turn-based effects

void UBongoTurnBasedGlobalAbilitySystem::TickTurnBasedEffectsForQuery(const FGameplayTagRequirements& TagRequirements)
{
	bTicking = true;

	for (auto PairIt = FBongoActiveTurnBasedEffectSpec::GetGlobalMap().CreateIterator(); PairIt; ++PairIt)
	{
		if (!TagRequirements.RequirementsMet(PairIt->Value.GetEffectAssetTags())) continue;

		FBongoActiveTurnBasedEffectSpec& EffectSpec = PairIt->Value;

		if (EffectSpec.Tick())
		{
			if (OnTickTurnBasedEffectDelegate.IsBound())
			{
				OnTickTurnBasedEffectDelegate.Broadcast(EffectSpec.GetActiveGameplayEffectHandle(), EffectSpec.GetTurnsRemaining());
			}
		}
	}

	// Tick all effects that were recently applied. Doesn't matter when they tick based on query.
	for (auto PairIt = FBongoActiveTurnBasedEffectSpec::GetGlobalMap().CreateIterator(); PairIt; ++PairIt)
	{
		FBongoActiveTurnBasedEffectSpec& EffectSpec = PairIt->Value;

		if (EffectSpec.WasRecentlyApplied())
		{
			if (EffectSpec.Tick())
			{
				if (OnTickTurnBasedEffectDelegate.IsBound())
				{
					OnTickTurnBasedEffectDelegate.Broadcast(EffectSpec.GetActiveGameplayEffectHandle(), EffectSpec.GetTurnsRemaining());
				}
			}
		}
	}

	bTicking = false;

	// Clean global map to prepare for next tick
	FBongoActiveTurnBasedEffectSpec::CleanGlobalMap();

	// Deferred effect spec ticks can now be added to map
	for (FBongoActiveTurnBasedEffectSpec Spec : NewEffectSpecsFromTick)
	{
		Spec.AddToGlobalMap();
	}

	NewEffectSpecsFromTick.Reset();
}

Utility AI Implementation

The combat AI was one of the bigger hurdles to overcome. The challenge here was to implement a decision-making AI that can select a sequence of abilities by accounting for various factors:

  • Magnitude of the action (e.g. prefer big damage, heal, etc.)
  • Target elemental affinity
  • Prioritize damage-dealers, healers, buffers, or debuffers
  • and many more…

So, I created a custom Utility AI plugin with Unreal Engine.

Implementation for AI selecting actions

Inventory System Integrations

I used my custom Inventory System Plugin to implement the following game systems.

Demonstrations

Inventory system in action for collected modules, including filtering and sorting
Demonstrating reusable inventory items (modules) in other game systems
Demonstrating management of creature and gadget items when setting up parties

StateTree Usages

Video

Showcases the creature's running StateTree

Tools

Below are some editor tools that have greatly increased QoL regarding asset validations, creation, and modifications.

Creature Creator

Showcases the tool used to create modular pipelines for importing and creating creature assets

Skill Event Editor

Showcases the editor used for quickly viewing and modifying skill activation data

Team Spawner

Seeing how the combat plays out with a very weird spawn placement
Method for generating spawn points

Tony Nguyen
Tony Nguyen
Technical Game Designer

Tenacious game developer with an unwavering passion for overcoming game development challenges.