top of page

STARSHORE

StarShore was a solo project developed over 15 weeks, allowing me to experiment with and deepen my understanding of certain systems. On this page, you’ll find uncut gameplay footage of the prototype, along with detailed breakdowns of its core systems.

DESIGN AND LAYOUT

For this project, I was responsible for all gameplay logic, blueprints, animation blueprints, level design, and scene assembly. Various asset packs—including characters and environments—were utilized to assemble the game. Foliage was primarily procedurally generated using foliage generation volumes on the landscape, with some hand adjustments for finer detail.

CHARACTER CONTROLS AND ANIMATIONS

This character features two toggleable primary movement states: standard and fly mode. Fly mode is activated by double-clicking the "W" key and ends upon key release or interruption. The animation blueprint switches between a 180° blendspace for standard movement and dodging, and a 45° blendspace for fly mode, which only activates when there is forward input from the controller. Attack and reaction animations are managed in the character blueprint and played as montages in a designated animation slot.

CHARACTER STATS AND ABILITY MANAGEMENT

This project is built using Unreal’s GameplayAbilitySystem (GAS). Core values such as health, mana, and skill cooldowns are implemented as GameplayAttributes, which are modified through GameplayEffects. Abilities, along with their visual and audio effects, are managed via GameplayAbilities and GameplayCues, respectively. Additionally, various gameplay states are tracked using GameplayTags.

AUTOTARGETING SYSTEM

The character’s basic spell attacks require automatic, passive tracking of viable targets. This is accomplished by performing a large sphere trace at set intervals. All enemies possess a "DamageSystem" component implemented with a blueprint interface, which is used to filter trace hits—if the trace hits an actor with this interface, that actor is set as the target.

 

Once a target is acquired, further traces are paused to prevent constant retargeting and maintain consistent gameplay. Instead, new logic monitors two criteria: the distance between the player and the tracked enemy, and the player camera’s angle of view relative to the direction toward the enemy. The angle is determined using the player camera’s forward vector and the vector pointing to the enemy. The target is cleared if the player moves more than 750 units away from the enemy, or if the angular difference between the camera’s forward direction and the enemy exceeds 45°. When the target is cleared, tracing resumes to find a new valid target.

This setup was sufficient for the purposes of this project, but it could be expanded with additional functionality—such as allowing the player to manually switch targets. This could be implemented by adding a check in the trace function to determine whether the hit actor is the same as the previous target. Upon receiving player input, the trace would be executed again until a new target is found, at which point the standard tracking logic would resume.

INVENTORY SYSTEM

The inventory system manages its contents as a list of strings, each mapped to a custom structure (see section MASTER PICKUP ITEM). The user interface modularly displays the item list by creating child widgets—each constructed using data from these structures—within a scroll box. When a category filter is applied, the system clears and rebuilds the scroll box based on the "item type" enumerator field present in the structure.

SHOP SYSTEM

The shop system interacts directly with functions in the player's inventory component. Its item stock is sourced from a list of strings maintained on the vendor, which can be freely adjusted to reflect available merchandise. Similar to the inventory user interface, the shop dynamically constructs child widgets within a scroll box to display items. The grid layout is determined by the item’s index: the row number is calculated as the integer division of the index by x (the number of items per row), and the column is determined by the index modulo x.

MASTER PICKUP ITEM

Instead of creating hundreds of unique item actors, I developed a single modular asset that configures itself based on data from a datatable. For instance, the item's VFX is determined by a switch on the "rarity" enumerator within the item's data structure. This system could be extended to support unique meshes for different items by adding a field for the static mesh asset path, which would be referenced during construction. The same approach could be applied to Niagara systems if more scalability were needed, but for this project, a simpler solution was sufficient.

Enemy drops are managed by a dedicated loot component, where the specific items and their quantities can be configured. Upon the owning actor's death (or other bound events), the component also applies impulses to the spawned loot objects, launching them for simulation.

bottom of page