Hey everyone! 👋
One of the core pillars of A Witch’s Path is how the player interacts with the environment. I’ve always loved how games like Breath of the Wild and Tears of the Kingdom make the world feel alive. Throw something weird at it, and the game often has a response. That level of reactivity? I knew I wanted something similar in my own game.
It just so happened to pair perfectly with another core mechanic: crafting your own spells.
So let’s talk about how I built this with Unreal Engine and how surprisingly simple (yet powerful) the system is under the hood.
✨ The Big Idea
In A Witch’s Path, spells aren’t for combat, they’re tools for solving puzzles, revealing secrets, and even altering the world itself. Fire burns objects. Wind pushes things. Light uncovers hidden secrets.
To make that happen, I built a modular system that allows anything in the world to react to spells using a single UObject
, a Blueprint Interface, and an Actor Component.
🔌 Blueprint Interface – BPI_Reactor
This is where the magic starts. BPI_Reactor
is a simple interface with one function: ReactToEffects
.
That function accepts an array of WorldEffect
objects. These are custom UObject
classes I’ve implemented in C++ that store metadata for effects—like type (Fire, Light, Wind), strength, duration, and more.
If something in the world should react to a spell or environmental change, it implements this interface. From there, it can decide how to respond based on the effects it receives.
But let’s make it even better…
🧩 Actor Component – BPC_WorldEffectApplicator
Instead of duplicating code in every actor that can react to effects, I built a Blueprint Actor Component to handle the glue logic.
BPC_WorldEffectApplicator
has one job:
Call ApplyWorldEffectsToReactor(WorldEffectsArray)
and it’ll do the work of passing those effects along to any compatible components or interfaces on the actor.
This is great for spells like fireball. When it hits a surface, it spawns a new actor that emits a fire-type WorldEffect
. That actor then overlaps with nearby objects and calls into their interfaces via the Applicator
.
Here’s a quick breakdown of some of the interfaces I’m using:
BPI_Activatable
– Can be toggled on/offBPI_Burnable
– Catches fire with fire-based spellsBPI_Revealable
– Reacts to light spells to show hidden objects
So instead of hardcoding logic everywhere, I can mix and match components and interfaces to create layered reactions.
🔥 Fire in Action
Let’s say the player casts a fireball.
- The projectile hits a flammable crate.
- A
WorldEffect
with the Fire tag and intensity is created. - The effect overlaps the crate’s collider.
- The crate implements
BPI_Burnable
, so it receives the fire effect. - The
StartBurning
function is triggered. - 🔥 Boom—animated fire, damage over time, and maybe it burns away.
🌱 Why It Matters
This system means I don’t need dozens of hardcoded responses for every spell. I just keep building out my library of WorldEffect
types and Blueprint Interfaces, and the reactivity of the world grows organically.
The more spells I add, the more creative and weird the interactions can become—and since players can craft their own magic, I want the world to feel like it notices.
Also: this system will evolve. I’ve got plans for elemental combos, timeline-altering effects, and even world-state changes based on spells.
🧪 Want a Deep Dive?
I kept this post light, but if you want a deeper technical breakdown (with more code or use cases), let me know on Bluesky! Always happy to chat systems and nerd out about Unreal 💚
Thanks for reading! I’ll be sharing more dev logs like this soon, including footage from the demo build. Stay tuned.