Freeform Friday

Crafting my perfect Turn-Based Combat System: The Risks and Challenges in My Unity JRPG

A devlog on the Zone Shifting turn-based combat system in my Unity JRPG: four zones, the camping problem it created, and the zone-targeting fix I'm testing.

Devlog · By Game Design Jar · · P.11

I’ve spent most of the last few months fine-tuning the combat system for Crown Code Chronicles, my pixel-art JRPG that’s “Coming Soon-ish” on Steam. This week I want to talk about the main mechanic of that system, and the riskiest call in the whole design: a positioning mechanic I’ve been calling Zone Shifting, that I’m hoping players find unique, challenging and strategic rather than boring or limiting.

What Zone Shifting actually is

Each side of the battle, hero and enemy, has four zones: Attack, Defense, Magic and Vitality. Each character has an innate zone they’re naturally better in, based on their role and their skill tree. Only one combatant can occupy a zone at a time, so with a four-person party every hero has their own specialty locked down in exactly one zone, and every zone has exactly one occupant.

The twist is that a combatant can only use the skills assigned to whichever zone they’re currently standing in. So your healer might have Cure and Regen loaded into their Vitality zone, and something completely different, say a fire spell, loaded into their Magic zone. Move that healer into Magic mid-battle and you can’t cast Cure or Regen anymore. You get the fire spell instead.

I wanted position to actually matter, and for moving a character to cost you something and gain you something in the same action. That way every turn has a real decision behind it.

Moving to a new zone uses up a turn. And because all four zones are always occupied, every move is a swap: the character already standing there trades places with the one you moved. There’s never an empty zone to step into. That still left the real problem, which was making a spent turn worth it.

The setup screen

Before a fight, the player assigns skills to zones per character. Not every fight, just whenever you feel the need to make changes. It’s basically a grid: four characters down, four zones across. Each character starts out with at least one skill in every zone, and you unlock more through the skill tree.

If you’ve built anything with a ScriptableObject-driven data layer before, this is exactly that kind of problem, and I leaned on the same approach I used for the dialogue system built with ScriptableObjects: each skill is its own asset, and a character’s loadout is a small container object holding one list of skills per zone.

The problem: players find a comfy zone and never leave

Here’s what I realized once I started testing it. When a player worked out a setup that felt good, say a tank sitting in Defense soaking hits while a mage sits in Magic throwing damage every turn, they had zero reason to ever waste a turn moving anyone. The system I built to reward movement was quietly training players to stand still.

Players try to use whatever system they’re given in the most optimal way they can, so they’re not going to start burning turns without a good reason. All the pressure to move was self-imposed, in that you switch because a different skill set looks useful this turn, and once someone had a rhythm that worked, that pressure disappeared.

The fix: skills that target the zone, not the character

The change I’m really excited about, and currently testing, is letting skills target a zone instead of a specific combatant. Most attacks and support skills still target a character the normal way: you pick a target, damage or effect lands on them. But these new skills, on the hero and enemy side, target a zone.

So whoever is standing in the Defense zone gets their Magic Defense lowered for a few turns. Or whoever is in Vitality loses 100 HP every turn until it wears off. That second one might mean swapping your healer and your tank for a while. Remember that every character has at least one skill in every zone, so the tank filling in as a stand-in healer can still do something useful, just not as well as the real one, and your actual healer lives to see another turn.

That one change does two things at once. It gives enemies a reason to punish a zone the player is leaning on, since an enemy skill that always targets Magic makes camping your mage there dangerous. And because the zones are always full, you can’t answer that by emptying the zone. You can only decide who’s standing in it when the attack lands.

It also opens the reverse. A support skill that targets “whoever is in Vitality” rewards the player for putting a fragile ally there right before they cast it, which nudges them toward moving people into a zone on purpose rather than leaving everyone where they landed.

The skill resolves against the zone rather than against a combatant. It’s a small change in code terms, but it reshapes the incentive completely, because now every zone assignment carries risk and reward instead of just convenience.

How it looks in code

This is roughly the shape of it, targeting Unity 6, though none of this is Unity-specific. It’s just a plain C# data model:

public enum CombatZone
{
    Attack,
    Defense,
    Magic,
    Vitality
}

public enum Side
{
    Heroes,
    Enemies
}

public enum SkillTargetMode
{
    Character,
    Zone
}

[CreateAssetMenu(fileName = "NewSkill", menuName = "Combat/Skill")]
public class SkillData : ScriptableObject
{
    public string skillName;
    public SkillTargetMode targetMode;

    // Where the caster has to be standing to use this at all.
    public CombatZone requiredZone;

    // Zone mode only. These two are separate from requiredZone on purpose:
    // where you cast from and what you hit are different questions, and an
    // enemy's Magic zone is not the same slot as your own.
    public CombatZone targetedZone;
    public Side targetedSide;

    public int power;
    // ...effects, cost, animation refs, etc.
}

And the resolution step, simplified, just branches on the target mode when it’s time to work out who actually gets hit:

public Combatant ResolveTarget(SkillData skill, Combatant explicitTarget, CombatZoneManager zones)
{
    if (skill.targetMode == SkillTargetMode.Character)
    {
        return explicitTarget;
    }

    // Zone-targeted: hit whoever is standing there right now. This comes back
    // null when the zone is empty, which happens with a party under four or
    // after a KO, so the caller has to check before applying anything.
    return zones.GetOccupant(skill.targetedSide, skill.targetedZone);
}

CombatZoneManager is a small class that maps each of the eight zones, four per side, to whichever combatant is currently standing in it, updated whenever someone moves. The interesting part isn’t the code, it’s deciding which skills get to be zone-targeted at all. If every skill did it, positioning would become chaotic and unreadable. I’m currently limiting it to a handful of signature skills, but that may change after some playtesting.

What I still haven’t solved

A few things are unresolved and I want to be honest about that rather than pretend this system is finished.

First, telegraphing. If an enemy is about to fire a Magic-zone attack, the player needs to know before they commit to leaving their mage there. Right now I’m leaning toward reusing the main info panel and showing how many turns until the zone gets hit, Final Fantasy or Pokemon style. I’m also not sure how to show that an effect is already active. I’ve tried dedicated panels the player opens with a button press and I’ve tried icons, and I haven’t landed on either.

Second, enemy AI has to actually use this well or it’s pointless. An enemy that always targets the same zone regardless of who’s there just becomes a pattern to memorize and route around, which defeats the point. I want the AI to sometimes target the zone the player has been camping in longest, which means tracking occupancy history per zone, and I haven’t built that yet.

Third, and this is the one that actually scares me: does zone-targeting make the system more interesting, or does it just feel punishing? I can imagine reactions ranging from “dumbest combat system ever” to “this is genius,” and I’m obviously hoping for the second one. That said, I’m happy with the design decisions so far, because this is the system I personally want to build and play. As a huge JRPG fan I’ve played a lot of these, and I’ve tried to study and borrow from the ones I enjoyed most.

If you’re building a turn-based system of your own and something about it feels solved too early, that’s usually the sign to watch for. A setup the player never wants to change is a system that isn’t asking anything of them any more. Worth checking whether your own combat loop has a version of this.

This system has evolved like crazy over time. It started as an ATB system (Active Time Battle, where each character’s turn fills on a timer instead of going in a strict order), so who knows what it’ll look like by release. Follow Game Design Jar and Crown Code Chronicles for updates.

unityjrpgcombat-designgame-designdevlogturn-based

Registration card

Register to receive one focused post every weekday — engine tutorials, marketing tactics, and design craft. Free, unsubscribe anytime.

No spam. We never share your address. No purchase necessary — it's free.