UniversalBars plugin: PEAK-style universal UMG bars
Procedural M_UI_UniversalBar material (SDF rounded-rect, fill/delayed/shield/ penalty-zones/stripes/segments/flash/pulse), 6 preset instances, animated UUniversalBarWidget + UUniversalHUDWidget + global UUniversalBarsSubsystem API, UUniversalBarsTheme DataAsset, and a ready WBP_HUD_InGame with zone-tracking status chips. See README.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
231
README.md
Normal file
231
README.md
Normal file
@ -0,0 +1,231 @@
|
||||
# Universal Bars
|
||||
|
||||
PEAK-style universal UMG bars for Unreal Engine 5.7 — one procedural material
|
||||
drives every kind of stat bar (health, stamina, hunger, thirst, oxygen, cold,
|
||||
shield, injury, boss HP, item durability, progress), with a global subsystem
|
||||
API and animated damage / heal / low-value feedback.
|
||||
|
||||
Everything is **procedural** — no bar textures required. White rounded border,
|
||||
soft corners, dark translucent backdrop, bright flat fill: clean cartoon
|
||||
survival HUD.
|
||||
|
||||
---
|
||||
|
||||
## 1. Install / enable
|
||||
|
||||
The plugin lives at `Plugins/UniversalBars/`. It is a project plugin and is
|
||||
enabled by default. After pulling, regenerate project files and build the
|
||||
editor target once (it adds the `UniversalBars` runtime module). Content mounts
|
||||
under `/UniversalBars/`.
|
||||
|
||||
> New C++ classes (a new module) cannot be hot-loaded by Live Coding — do a full
|
||||
> editor build the first time.
|
||||
|
||||
---
|
||||
|
||||
## 2. What's inside
|
||||
|
||||
```
|
||||
/UniversalBars/
|
||||
Materials/
|
||||
M_UI_UniversalBar master material (Domain=UI, Translucent, procedural SDF)
|
||||
MI_UI_Bar_Health solo green bar
|
||||
MI_UI_Bar_Stamina solo yellow-green bar
|
||||
MI_UI_Bar_Injury striped "broken HP" bar
|
||||
MI_UI_Bar_Shield blue bar + shield overlay
|
||||
MI_UI_Bar_Boss segmented boss bar
|
||||
MI_UI_Bar_PeakCombined HP + hunger + weight in ONE bar (PEAK capacity)
|
||||
Components/
|
||||
WBP_UniversalBar one reusable bar (parent: UUniversalBarWidget)
|
||||
WBP_BarHealth combined-capacity variant
|
||||
WBP_BarStamina stamina variant
|
||||
WBP_HUD_InGame ready HUD: health + stamina + status chips
|
||||
Theme/ put DA_UniversalBars_* theme assets here
|
||||
|
||||
C++ (module UniversalBars):
|
||||
UUniversalBarWidget one animated bar
|
||||
UUniversalHUDWidget HUD container with high-level stat setters
|
||||
UUniversalBarsSubsystem global access point (UWorldSubsystem)
|
||||
UUniversalBarsTheme palette / geometry / chip-colour DataAsset
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Quick start
|
||||
|
||||
### Blueprint — easiest path (global API, no widget reference)
|
||||
|
||||
1. On `BeginPlay` (player controller / HUD), call
|
||||
`Universal Bars Subsystem → Create HUD` with `HUD Class = WBP_HUD_InGame`.
|
||||
2. From **anywhere** in BP:
|
||||
|
||||
```
|
||||
Get World Subsystem (UniversalBarsSubsystem)
|
||||
→ Set Health (0.62) // 0..1, animates + flashes automatically
|
||||
→ Set Stamina (0.8)
|
||||
→ Set Hunger (0.16) // penalty zone eats into max HP (combined bar)
|
||||
→ Set Weight (0.12)
|
||||
→ Damage Health (0.2) // red flash + instant drop + lag tail
|
||||
→ Heal Health (0.25) // green flash + smooth rise
|
||||
```
|
||||
|
||||
Direction is detected for you: a decrease plays the damage animation, an
|
||||
increase plays the heal animation.
|
||||
|
||||
### C++
|
||||
|
||||
```cpp
|
||||
#include "UniversalBarsSubsystem.h"
|
||||
|
||||
if (UUniversalBarsSubsystem* Bars = UUniversalBarsSubsystem::Get(this))
|
||||
{
|
||||
Bars->SetHealth(0.62f);
|
||||
Bars->SetHunger(0.16f);
|
||||
Bars->DamageHealth(0.2f);
|
||||
}
|
||||
```
|
||||
|
||||
### Driving a single bar directly
|
||||
|
||||
Place a `WBP_UniversalBar` (or a preset variant) anywhere and call:
|
||||
|
||||
```cpp
|
||||
UUniversalBarWidget* Bar = ...;
|
||||
Bar->SetFillPercent(0.5f); // animated
|
||||
Bar->SetShieldPercent(0.25f);
|
||||
Bar->SetSegmentCount(10); // boss segments
|
||||
Bar->SetPenaltyZone("Hunger", 0.16f, FLinearColor(0.9f,0.6f,0.2f,1)); // animated zone
|
||||
Bar->PlayDamageFlash(); // manual flash
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Animation model (same as the HTML prototype)
|
||||
|
||||
| Change | Bright fill | Lag tail | Flash |
|
||||
|---|---|---|---|
|
||||
| **Decrease / damage** | snaps down instantly | holds `DelayedDelay`s, then drains at `DelayedFallSpeed` | red (`DamageFlashColor`) |
|
||||
| **Increase / heal** | eases up at `FillRiseSpeed` | jumps to target (lighter "incoming" band) | green (`HealFlashColor`) |
|
||||
| **value < `LowThreshold`** | — | — | border pulses (low-value warning) |
|
||||
| **penalty zone change** | — | zone width eases at `ZoneInterpSpeed` | — |
|
||||
|
||||
All tuning fields live on `UUniversalBarWidget` (Bar|Anim category). Set
|
||||
`bAutoFlashOnChange=false` to drive flashes manually.
|
||||
|
||||
Under the hood the material exposes `FillPercent`, `DelayedFillPercent`,
|
||||
`FlashAmount`, `LowHPPulseAmount` — the widget tweens these every tick via a
|
||||
Dynamic Material Instance.
|
||||
|
||||
---
|
||||
|
||||
## 5. Combined "capacity" bar (PEAK)
|
||||
|
||||
One bar = current value (bright) + depleted-but-recoverable zone (dark) +
|
||||
striped penalty zones eating max from the right:
|
||||
|
||||
- `MaxFillPercent` — right edge of the usable region (`1 - sum(penalties)`).
|
||||
- `PenaltyCount` + `PenaltyEnd1..4` + `PenaltyColor1..4` — up to 4 striped zones.
|
||||
|
||||
You never set these by hand — `SetHunger / SetWeight / SetCold` (HUD) or
|
||||
`SetPenaltyZone(Id, Width, Color)` (bar) manage them and animate the widths.
|
||||
Set a penalty to `0` to retract its zone.
|
||||
|
||||
`PenaltyCount = 0` → the same material is a plain solo bar.
|
||||
|
||||
---
|
||||
|
||||
## 6. Material parameter reference
|
||||
|
||||
**Scalars:** `FillPercent`, `DelayedFillPercent`, `ShieldPercent`,
|
||||
`MaxFillPercent`, `PenaltyCount`, `PenaltyEnd1..4`, `BarOpacity`,
|
||||
`BackgroundOpacity`, `CornerRadius`, `BorderSize`, `InnerPadding`,
|
||||
`EdgeSoftness`, `BarAspect`, `FlashAmount`, `LowHPPulseAmount`, `PulseSpeed`,
|
||||
`StripeAmount`, `StripeScale`, `StripeSpeed`, `SegmentCount`,
|
||||
`SegmentDividerSize`, `SegmentDividerOpacity`, `UseVerticalFill`, `InvertFill`,
|
||||
`NoiseAmount`, `TimeOffset`.
|
||||
|
||||
**Vectors:** `FillColor`, `DelayedFillColor`, `ShieldColor`, `BackgroundColor`,
|
||||
`BorderColor`, `EmptyColor`, `FlashColor`, `StripeColorA`, `StripeColorB`,
|
||||
`PenaltyColor1..4`.
|
||||
|
||||
`BarAspect` must roughly match the on-screen width/height ratio so the rounded
|
||||
corners stay circular (default 8 ≈ a 600×75 bar).
|
||||
|
||||
---
|
||||
|
||||
## 7. Theme
|
||||
|
||||
`UUniversalBarsTheme` (DataAsset) centralises palette + geometry + chip colours.
|
||||
Create one under `/UniversalBars/Theme/` (right-click → Miscellaneous → Data
|
||||
Asset → Universal Bars Theme), then assign it to `WBP_HUD_InGame`'s `Theme`
|
||||
property. `UUniversalHUDWidget::ApplyTheme()` runs on construct and retints both
|
||||
bars and all chips. Per-preset look still lives in the `MI_UI_Bar_*` instances;
|
||||
the theme is the HUD-level override.
|
||||
|
||||
---
|
||||
|
||||
## 8. Presets (recommended values)
|
||||
|
||||
| Preset | Fill | Notes |
|
||||
|---|---|---|
|
||||
| Health | `(0.30,0.85,0.20)` | white border, low-HP pulse, damage lag |
|
||||
| Stamina | `(0.85,0.95,0.30)` | thinner, no pulse |
|
||||
| Injury | `(0.75,0.20,0.20)` + `StripeAmount=1` | striped "broken" HP |
|
||||
| Shield | `(0.30,0.70,1.0)` + `ShieldPercent` | blue + overlay |
|
||||
| Boss | `(0.85,0.15,0.15)` + `SegmentCount=10` | wide, segmented, less rounded |
|
||||
| PeakCombined | green + Hunger/Weight penalties | one-bar HP+hunger+weight |
|
||||
|
||||
Keep `BorderColor` pure white and `BorderSize` 0.06–0.10 for the toy/cartoon
|
||||
look; `CornerRadius` 0.5–0.7 for horizontal bars.
|
||||
|
||||
---
|
||||
|
||||
## 9. Demo / study mode (WBP_HUD_InGame)
|
||||
|
||||
`WBP_HUD_InGame` ships with **Demo Mode ON** (`UUniversalHUDWidget::bDemoMode`).
|
||||
While on, the HUD's `NativeTick` runs a 10-step cycle every `DemoStepInterval`
|
||||
(1.6 s) so you can watch every animation live in PIE:
|
||||
|
||||
```
|
||||
0 DamageHealth(0.25) red flash + instant drop + lag tail
|
||||
1 SetStamina(0.30) stamina drop
|
||||
2 HealHealth(0.20) green flash + smooth rise
|
||||
3 SetHunger(0.18) amber zone eases in from the right
|
||||
4 SetWeight(0.14) red zone eases in
|
||||
5 SetStamina(0.95) stamina refill
|
||||
6 HealHealth(0.30)
|
||||
7 SetHunger(0.0) hunger zone retracts
|
||||
8 SetWeight(0.0) weight zone retracts
|
||||
9 DamageHealth(0.45) big hit -> low-HP border pulse
|
||||
```
|
||||
|
||||
To watch: add the HUD (`Subsystem → Create HUD`, or just drop it in any widget /
|
||||
PIE) and press Play. The cycle restarts each time the widget constructs.
|
||||
|
||||
**Turn it off for shipping:** open `WBP_HUD_InGame` → Class Defaults → uncheck
|
||||
**Demo Mode**, or call `SetDemoMode(false)`. Read `DemoStepNow()` in
|
||||
`UniversalHUDWidget.cpp` to see exactly which API call drives each animation.
|
||||
|
||||
## 9b. Status chips (PEAK markers)
|
||||
|
||||
In `WBP_HUD_InGame` the chips live in a `CanvasPanel` (`ChipCanvas`) **overlaid on
|
||||
the health bar**, not in a row below it. Each tick `UUniversalHUDWidget::PositionChips()`
|
||||
slides them to sit just above the centre of their zone, using
|
||||
`UUniversalBarWidget::GetUsableEnd()` / `GetZoneCenter("Hunger"|"Weight"|"Cold")`:
|
||||
|
||||
- `ChipHeart` → the usable-HP / penalty boundary
|
||||
- `ChipHunger` → centre of the hunger zone (hidden until `SetHunger > 0`)
|
||||
- `ChipWeight` → centre of the weight zone
|
||||
- `ChipCold` → centre of the cold zone
|
||||
|
||||
So when hunger/weight grow or shrink, the chips ride along with the zone edges.
|
||||
Add your own marker by placing an `Image` in `ChipCanvas` and binding it (or extend
|
||||
`PositionChips`). Swap the placeholder tints for real icon textures.
|
||||
|
||||
## 10. Notes / limits
|
||||
|
||||
- The bar is a UI-domain material — it only renders inside UMG/Slate (not on
|
||||
meshes). Verify visuals in the UMG designer or content-browser thumbnail.
|
||||
- Up to 4 penalty zones are drawn by the material in a single draw call; the
|
||||
widget warns if you push more.
|
||||
- `SetFillPercent` clamps to 0..1. Feed it `CurrentHP / MaxHP`, etc.
|
||||
Reference in New Issue
Block a user