18 — Fuzzy Turret Defense Demo¶
🇬🇧 English | 🇺🇦 Українська
The plugin's optional FuzzyLogicDemo module ships a second demo scene: a turret defends itself against waves of enemy drones using three chained Mamdani systems instead of a single hand-tuned threshold. One system scores threats, the second aims, and the third decides when it's actually safe to fire — and none of them is a switch statement.
How to Run It¶
In the Content Browser, enable the settings (gear) icon → Show Plugin Content if Plugins isn't visible, then navigate to Plugins → Fuzzy Logic Content → Demo → FuzzyTurretDefense → Maps and open FuzzyTurretDefense.
Press Play or Standalone Game. Enemy drones approach from the arena's edge; the turret tracks the nearest one, spins up, and fires when its fuzzy FireAuthorization output clears the threshold. Shell casings eject from the gun's side port, land on the floor under physics, and fade out after 14 seconds. A Fire Control visualization panel in the bottom-right corner plots the three input membership functions and the aggregated FireAuthorization surface live — see 16 — Demo Content for its HIDE/SHOW and PAUSE/RESUME controls.
Assets¶
All of this demo's assets live in the Content Browser under Plugins → Fuzzy Logic Content → Demo → FuzzyTurretDefense (enable Show Plugin Content if Plugins isn't visible):
| Asset | Purpose |
|---|---|
Maps/FuzzyTurretDefense |
The demo map |
DA_RadarAssessment |
Threat-priority UFuzzySystemAsset |
DA_TrackingControl |
Aiming-speed UFuzzySystemAsset |
DA_FireControl |
Firing-authorization UFuzzySystemAsset |
RadarAssessment.json, TrackingControl.json, FireControl.json |
The editable JSON sources of the three systems |
Blueprints/BP_FuzzyTurret |
The turret actor: rotation, radar sampling, firing, heat buildup |
The set names in the JSON are kept in English so they're easy to search for in Blueprint, but their exact meaning is given below.
The output number isn't a switch. It's a defuzzified result within the stated range: rules activate fuzzy sets, they overlap one another, and the Centroid method returns their center of gravity. That's why the transition between states is smooth.
How to Read the Parameters¶
For Triangle, the parameters Left, Peak, Right mean: the degree of membership is 0 at the left and right points and 1 at the peak. Between them, the value changes linearly. For Trapezoid, full membership lasts from LeftShoulder to RightShoulder. For Ramp, the value changes from 0 at Foot to 1 at Shoulder; if Shoulder is less than Foot, it's a falling set.
The overlap between neighboring sets is intentional: for example, a result can be partially Standby and partially Authorize at the same time. See Membership Functions for more on shapes, and Rule Language and Inference Settings for rules and defuzzification.
1. RadarAssessment — Threat Assessment¶
This system determines how much priority the nearest hostile target deserves. TargetDistance is measured in Unreal units, ClosingRate in Unreal units per second. Each frame, the turret computes ClosingRate as (previous distance − current distance) / Delta Seconds and clamps the result to the 0…1200 range: moving away gives 0, fast closing gives a higher value. The ThreatPriority result is passed to FireControl.
| Variable | Range | Set | Parameters | Meaning |
|---|---|---|---|---|
TargetDistance |
0…3200 | Critical |
Ramp: 1600 → 100 | critically close; full membership near 100 and below, fading out to 1600 |
Tactical |
Triangle: 700 / 1700 / 2700 | working range; most typical around 1700 | ||
Distant |
Ramp: 1900 → 3200 | far target; strength rises after 1900 and is full near 3200 | ||
ClosingRate |
0…1200 | Slow |
Ramp: 650 → 0 | the target is closing slowly or barely closing at all |
Fast |
Ramp: 250 → 1100 | fast closing; full membership near 1100 | ||
ThreatPriority |
0…1 | Observe |
Triangle: 0 / 0.12 / 0.45 | observe, no high priority |
Track |
Triangle: 0.30 / 0.58 / 0.82 | track the target | ||
Engage |
Triangle: 0.68 / 0.93 / 1 | threat is sufficient to engage |
Rules raise the priority for a close or fast-closing target. A distant, slow target gives Observe, a distant fast one gives Track, and a critical or tactical fast one gives Engage.
2. TrackingControl — Aiming Speed¶
This system chooses the servo speed. AimError is the angular error between the gun's axis and the target, in degrees. The TrackingSpeed result is a rotation-speed multiplier, not an angle.
| Variable | Range | Set | Parameters | Meaning |
|---|---|---|---|---|
TargetDistance |
0…3200 | Near |
Trapezoid: 0 / 0 / 650 / 1450 | close target |
Medium |
Triangle: 800 / 1650 / 2500 | medium range | ||
Far |
Trapezoid: 1900 / 2700 / 3200 / 3200 | far target | ||
AimError |
0…180° | Aligned |
Trapezoid: 0 / 0 / 3 / 13 | gun is on target: full match up to 3°, fading out to 13° |
Tracking |
Triangle: 5 / 35 / 85 | target is being tracked | ||
Lost |
Ramp: 45 → 150 | large error: target nearly or fully lost | ||
TrackingSpeed |
0.8…7.5 | Precise |
Triangle: 0.8 / 1.5 / 3.2 | slow, precise fine-tuning |
Responsive |
Triangle: 2.2 / 4.2 / 6.1 | normal tracking | ||
Rapid |
Triangle: 4.8 / 7.0 / 7.5 | fast search or interception |
The main rule here is simple: Lost gives Rapid, Tracking gives Responsive, Aligned gives Precise. An additional rule guarantees Rapid when the target is both far and lost.
3. FireControl — Firing Authorization¶
This system combines accuracy, threat priority, and thermal state. Its output, FireAuthorization, is a smooth firing-permission indicator from 0 to 1. It doesn't replace mechanical constraints: the Blueprint also checks the reload state.
| Variable | Range | Set | Parameters | Meaning |
|---|---|---|---|---|
AimError |
0…180° | Locked |
Trapezoid: 0 / 0 / 2.5 / 9 | a solid lock; full match up to 2.5°, fading out to 9° |
Marginal |
Triangle: 3 / 14 / 34 | acceptable but imprecise aim | ||
Unsafe |
Ramp: 14 → 75 | dangerous error; full membership from 75° | ||
ThreatPriority |
0…1 | Low |
Ramp: 0.70 → 0.05 | low priority; full membership near 0.05 and below |
High |
Ramp: 0.35 → 0.95 | high priority; full membership near 0.95 | ||
WeaponHeat |
0…1 | Safe |
Ramp: 0.82 → 0.05 | safe temperature; full membership near 0.05 |
Hot |
Ramp: 0.58 → 0.98 | overheating; full membership near 0.98 | ||
FireAuthorization |
0…1 | Inhibit |
Triangle: 0 / 0.08 / 0.42 | hold fire; strongest near 0.08 |
Standby |
Triangle: 0.30 / 0.55 / 0.78 | keep tracking and wait for better conditions; peaks near 0.55 | ||
Authorize |
Triangle: 0.68 / 0.94 / 1 | permission to fire; strongest near 0.94 |
What the FireAuthorization Values Mean¶
0…0.42: theInhibitset is active; firing isn't allowed.- roughly
0.30…0.78: theStandbyregion; the system may still track the target, but conditions aren't sufficient to fire. 0.68…1:Authorizeis active; the closer the result to0.94, the stronger the combined case for firing.
In the demo Blueprint, firing is actually permitted by the check FireAuthorization > 0.64 together with a zero FireCooldown. The threshold is lower than the start of Authorize (0.68) so that no abrupt switching occurs in the transition zone, while still ensuring low, indeterminate results can't trigger a shot.
Safety rules take priority: Unsafe, Low, or Hot lead to Inhibit. Only the combination of Locked, High, and Safe gives Authorize; Marginal, High, Safe gives an intermediate Standby.
The Role of JSON¶
DA_RadarAssessment, DA_TrackingControl, and DA_FireControl were each built from their matching JSON file (RadarAssessment.json, TrackingControl.json, FireControl.json) via FuzzyLogicStatics.load_fuzzy_system_from_json. At runtime, BP_FuzzyTurret reads the three Data Assets directly; none of the JSON files is parsed at runtime or needed by a packaged build.
You can also open any of the three Data Assets, change the system in the editor, and click Save To JSON to manually sync the external preset.
What to Try¶
- lower the
FireAuthorization > 0.64gate in the Blueprint and watch the turret fire earlier, less certainly; - widen
AimError.Lockedin FireControl and see how much sloppier aim the turret tolerates before it stops firing; - change
WeaponHeat.Hotso the turret needs to cool down sooner; - add a fourth
ThreatPriorityset (e.g.Critical) and a matching rule in FireControl; - switch
FireControl's defuzzification fromCentroidtoMean of Maximaand compare how decisively it commits toAuthorize.
The demo classes live in the plugin's own FuzzyLogicDemo module (Plugins/FuzzyLogic/Source/FuzzyLogicDemo) — they ship with the plugin by default, but can be excluded from the build entirely; see 16 — Demo Content.
The Meaning of DefaultValue¶
DefaultValue on an input is the starting value before the first Set Input. For example, AimError: 90 means that before receiving telemetry, the system considers the gun's axis to be off by 90°.
DefaultValue on an output doesn't participate in inference. It's just the default value in the variable's structure; the result is always computed from the rules and membership functions. For FireAuthorization: 0, it's also a safe initial state before the first evaluation.