SpongeBob Roguelike: A Deep Dive into Custom Projectiles with Scene Graph

PUZZLER
Fri, 13 Mar 2026 23:15:00 +0000
Tutorial & Course Discussions

We are Puzzler Creations, a two person game dev studio run out of Ontario, Canada that has built games since 2013.

Our latest UEFN project is SpongeBob Roguelike, a mobile-first action roguelike where Plankton has unleashed mind-controlled citizens and robots across Bikini Bottom while Karen works to decode the stolen Krabby Patty formula. Players dodge attacks, collect SpongeBob-themed upgrade cards, and try to push deeper into progressively harder chapters and boss stages.

When the request for SpongeBob proposals opened up, we saw an opportunity to combine three pillars we care deeply about:

The humor and personality of SpongeBob

The fast replayability of roguelikes

The challenge of building a truly original experience inside Fortnite

From the beginning, our goal was clear: create something that felt fundamentally different from what players typically expect in Fortnite. We knew achieving that would require fully embracing the power of UEFN’s Scene Graph systems.

The Power of Scene Graph

Throughout development, Scene Graph became the backbone of our technical approach. Here are our key takeaways:

New Possibilities: Scene Graph enables functionality that was previously unavailable in Fortnite, including smooth key framed animation, custom hit detection and runtime component logic on entities. This allowed us to build a fully custom projectile system without relying on Fortnite’s default weapon framework.

Rapid Creative Iteration: By building modular Scene Graph components—such as projectile logic, area-of-effect systems, and collision verification—we were able to iterate quickly while keeping systems maintainable and scalable.

Designer Friendly: Because gameplay logic is encapsulated within components, our designers were able to modify patterns, meshes, and behaviors without needing to rewrite code. Scene Graph helped bridge the gap between engineering and design.

To help you start experimenting with and creating your own projectile-based systems, we posted a full set of our Verse files here.

Creating a Modular Projectile System

One of our core design goals was to eliminate traditional Fortnite weapons entirely. To achieve a roguelike feel, we needed:

Runtime-spawned projectiles

Editable patterns

Custom hit detection

Flexible animation

Independent damage logic

This presented us with our first technical challenge: how do we implement accurate hit detection and damage without Fortnite’s built-in weapon systems?

Custom Collision Detection Using Scene Graph

When we began, Scene Graph was still relatively unexplored territory for us. However, we discovered the EntityEnteredEvent, which triggers when a mesh component is overlapped by another entity.

This became the backbone of our collision system.

Here is an example of how we typically used this event to check if our projectiles have overlapped another entity:

InitProjectileHitDetection(PlayerAgent:agent): void =
        if(MeshComp := Entity.GetComponent[mesh_component]):
            MeshComp.EntityEnteredEvent.Subscribe(OnEntityEntered)

Whenever an entity overlaps the projectile mesh, OnEntityEntered handles the response—such as applying damage. However this situation introduced a new problem - we needed a reliable method for enemy verification because players, other projectiles, walls, environmental props and other assets were triggered by the event.

Runtime Tagging for Enemy Verification

To solve this problem, we created a lightweight Scene Graph component:

enemy_agent_tag_component<public> := class<final_super>(component):

This component acts purely as an identifier. At runtime, we add it to any agent intended to be damageable. Here is an example of how you could add this component to an agent.

AddEnemyAgentTagComponent(EnemyAgent:agent):void=
        if:
            EnemyFortCharacter := EnemyAgent.GetFortCharacter[]
            EnemyEntity := EnemyFortCharacter.GetEntity[]
        then:
            EnemyAgentTagComponent := enemy_agent_tag_component{Entity := EnemyEntity}
            EnemyEntity.AddComponents(array{EnemyAgentTagComponent})

Now, when EntityEnteredEvent fires, we verify whether the overlapping entity contains our custom tag component before applying damage. This tag provides some important benefits for authenticating enemies:

Precise enemy filtering

Reliable collision logic

Fully modular damage verification

Smooth Projectile Animation with Keyframed Movement

Traditional animation methods in Verse (e.g., MoveTo, TeleportTo) are limited by frame constraints and can result in choppy movement - unacceptable in a fast-paced roguelike.

Our solution was Scene Graph’s keyframed_movement_component which enabled:

Smooth, frame-independent animation

Deterministic projectile travel

Cleaner, scalable movement logic

The keyframed_movement_component allows for smooth animation through an array of keyframes known as keyframed_movement_delta’s, which represents a change in position and scale over time. You can set as few or as many keyframes as needed for your animation, but in this case we only need to set 1 for the target location.

This keyframed_movement_delta needs:

Transform (Target location for the animation)

Duration (How long the animation takes to play)

Easing (The style of easing we want to apply to the animation)

For our transform we first calculate a forward vector by simply getting the forward facing axis of our projectile and multiplying it by our desired travel distance. With this forward facing vector we can then add it to the projectile’s current location in order to get our desired target location for our projectile. We can then set this target destination as our translation in the transform we will be using in our keyframed_movement_delta.

The duration in our case represents the time we want the projectile to take to arrive at it’s target location. We can easily calculate this by doing some basic physics such as TravelTime := TravelDistance/ProjectileSpeed.

InitProjectile(PlayerAgent:agent): void =
        if(KeyComp := Entity.GetComponent[keyframed_movement_component]):
            CalculateDestination(PlayerAgent)

CalculateDestination(PlayerAgent:agent): void =
        CurrentTransform := Entity.GetGlobalTransform()
        ForwardVector := CurrentTransform.Rotation.GetForwardAxis() * TravelDistance
        DestinationTranslation := CurrentTransform.Translation + ForwardVector
        spawn{AnimateProjectile(ForwardVector)}

AnimateProjectile(DestinationTranslation:vector3)<suspends>: void =
        TravelTime := TravelDistance/ProjectileSpeed


        NewTransform:transform = transform:
            Translation := DestinationTranslation
            Scale := vector3{Left := 0.0, Up := 0.0, Forward := 0.0}


        KeyDelta : keyframed_movement_delta = keyframed_movement_delta :
            Transform := NewTransform
            Duration := TravelTime
            Easing := linear_easing_function{}

        if(KeyComp := Entity.GetComponent[keyframed_movement_component]):
            KeyComp.SetKeyframes(array{KeyDelta}, oneshot_keyframed_movement_playback_mode{})
            Sleep(0.1)
            KeyComp.Play()

Modular Parent-Child Projectile Architecture

All of the projectiles were made using Entity Prefab Definitions containing custom-made Scene Graph components. These prefabs allowed us to rapidly make changes to our projectiles without affecting the underlying code.

All projectile systems are encapsulated within two primary components:

projectile_container_component

projectile_component

Container (Parent) Entity Prefab contains the following

Transform component

projectile_container_component

The container entity sets its transform to the player’s location and initializes any child entities containing the projectile logic component.

Projectile (Child) Entity Prefab is reusable across nearly all projectiles and contains these elements:

transform_component

keyframed_movement_component

mesh_component

projectile_component

The projectile component handles:

Hit detection

Enemy verification

Animation

Damage logic

Rapid Pattern Creation

Because the child entities that contain the projectile_component are reusable, we can duplicate them inside a “container” or parent prefab to create new patterns instantly—without modifying code. For example:

Add three child entities that contain the projectile_component to a parent entity that contains the projectile_container_component

Rotate two by +45° and -45°

Result: a functional spread shot projectile

We can then further customize each individual child entity by changing:

Static meshes

Niagara VFX

Audio

Speed

Travel distance

This system allows near-infinite projectile variations while keeping engineering complexity stable.

This screenshot shows an example of 2 completed projectile prefabs. The parent entity in both prefabs contains only a transform_component and our projectile_container_component.

They both have the exact same child entity contains a transform_component, a mesh_component, a keyframed_movement_component, and our projectile_component.

On the left side we duplicated this child entity 3 times, and changed the static mesh to a green sphere and offset the translation of the transform to create a projectile that shoots 3 green spheres forward in a line (A wide type projectile).

The right side also has the child entity duplicated 3 times, but this time we changed the rotation of the transform and swapped the mesh to a blue sphere. This creates a projectile that shoots 3 blue spheres in a cone shaped angle pattern, or a common “spread shot” type found in many games.

This gives us a very fast simple way to create several varying types of projectiles. We can simply create a new entity prefab as our “container” entity and add as many duplicates of the child entity we want and modify the components for transform, mesh, particle systems etc without ever having to touch the code.

You can of course expand on these using verse to make more reusable and customizable projectile_components. For example you could add editable verse fields for damage, “poison toggle”, “knockback” etc.

Conclusion

SpongeBob Roguelike was both a creative opportunity and a technical proving ground. We were able to design a full mobile-first roguelike that feels fast, readable, and authentic to SpongeBob’s world. By fully embracing Scene Graph, we were able to:

Eliminate Fortnite’s default weapon systems

Build a modular, scalable projectile architecture

Deliver smooth, mobile-first action gameplay

Empower designers through component-based iteration

We posted a full set of our Verse files as snippets here, and encourage you to experiment with editing the components, setting up Entity Prefab Definitions and starting to create your own projectile-based systems.

Our mission was to demonstrate that even a small team can deliver polished, technically ambitious experiences in UEFN.

This project pushed us to rethink animation workflows, collision logic, and modular game architecture - with Scene Graph at the center.

At Puzzler Creations, we’re excited to continue exploring new systems, new genres, and new creative possibilities inside Fortnite. We look forward to sharing more technical breakdowns and design insights as UEFN continues to evolve.

2 posts - 2 participants