Scoring a Skill Check and Firing Blueprint Events (Unreal Engine)

How a radial skill check scores the player's stop: compare the gauge angle to the great zone first, then the good zone, else a miss, and broadcast one of three Blueprint events. Why great is tested first and what else counts as a miss.

This is step six of the Radial Skill Check in Unreal Engine guide. The gauge is moving and the zones are placed; now the player presses the key and the component turns one angle into an outcome.

Stop, then evaluate

The player’s input calls AttemptSkillCheck. If a gauge is active it freezes the sweep, disables tick, scores the frozen angle, and tears the widget down:

void USkillCheckComponent::AttemptSkillCheck()
{
    if (!bIsGaugeActive) return;     // safe no-op when nothing is showing

    bIsGaugeActive = false;
    SetComponentTickEnabled(false);
    EvaluateSkillCheck();            // score the frozen angle
    DestroyWidget();
    // ... reschedule the next check if auto-triggering
}

Because it is a no-op when no gauge is up, you can fire it on every key press without guarding it first.

Great first, then good, then miss

Scoring is three range checks in a deliberate order. The zone boundaries are start plus size; the gauge angle is compared to the great range, then the good range:

const float GoodZoneEnd  = ZoneStartAngle + GoodZoneSize;
const float GreatZoneEnd = GreatZoneStartAngle + GreatZoneSize;

if (CurrentGaugeAngle >= GreatZoneStartAngle && CurrentGaugeAngle <= GreatZoneEnd)
{
    OnSkillCheckGreat.Broadcast();   // perfect
}
else if (CurrentGaugeAngle >= ZoneStartAngle && CurrentGaugeAngle <= GoodZoneEnd)
{
    OnSkillCheckGood.Broadcast();    // normal success
}
else
{
    OnSkillCheckMiss.Broadcast();    // wrong stop
}

The order is the important part. The great zone is nested inside the good zone, so an angle in the great range is necessarily in the good range too. If good were tested first it would match every perfect stop and the great outcome could never fire. Testing great first gives the precise hit priority.

The two ways to miss

There are two paths to a miss, and they meet at the same event:

  1. A wrong stop: EvaluateSkillCheck falls through both ranges (above) and broadcasts OnSkillCheckMiss.
  2. A timeout: the player never reacts and the gauge crosses its rotation budget. The tick calls OnGaugeFullRotation, which also broadcasts OnSkillCheckMiss (and, if auto-triggering, schedules the next check).

So whether the player stabs the key at the wrong moment or freezes entirely, your Blueprint sees one consistent miss event.

Audio is automatic

Each outcome optionally plays a sound straight from the settings, independent of your event wiring: a great, good, or failure sound on the matching result. Set them once and they fire themselves; you do not have to route audio through your handlers.

Binding the events

The three results are DECLARE_DYNAMIC_MULTICAST_DELEGATEs exposed as BlueprintAssignable properties, so you bind them on the component like any event. Select the component, open its events, and add a handler for each.

The On Skill Check Great, Good, and Miss events bound in an Unreal Engine Blueprint event graph

This is where the mechanic becomes your game: a great might deal bonus damage or speed a repair, a good advances it normally, a miss interrupts the action or alerts an enemy. The component reports the timing; what it means is up to you.

The last piece is deciding when checks appear in the first place: solving sessions and triggering.

Frequently asked questions

Why is the great zone checked before the good zone?
The great zone sits inside the good zone, so any angle in the great range is also in the good range. Testing great first means a perfect stop is scored as great instead of being swallowed by the good check that would otherwise match it too.
What are the three events?
OnSkillCheckGreat, OnSkillCheckGood, and OnSkillCheckMiss are dynamic multicast delegates with no parameters. You bind to them on the component in Blueprint and react however you like: advance a repair, deal bonus damage, interrupt the action.
What triggers a miss?
Either stopping the gauge outside both zones, which EvaluateSkillCheck scores as a miss, or never reacting until the gauge runs out its allowed rotations, which OnGaugeFullRotation reports as a miss. Both broadcast the same OnSkillCheckMiss event and play the failure sound.