ValueComparison is a reusable utility for showing changes between two values in UI (old -> new), with optional increase/decrease coloring.
It is designed to be domain-agnostic: inventory, RPG stats, settings diffs, save slot comparisons, and more.
ValueDeltaTypeRepresents the direction of change:
NEUTRALINCREASEDECREASEValueComparisonLineData model for one comparison row.
public struct ValueComparisonLine
{
public string Key;
public string Name;
public Sprite Icon;
public string OldValue;
public string NewValue;
public ValueDeltaType DeltaType;
public bool HideOldValue;
}Use GetDeltaType(float value, float comparisonValue) to compute the delta state for numeric comparisons.
ValueComparisonLineControllerUI Toolkit controller that renders a single ValueComparisonLine.
Features:
TooltipControllerThe controller builds its own row elements in C# — all your UXML needs is a host element to parent it under. Assign this UXML to the PanelRenderer's Source Asset:
<ui:UXML xmlns:ui="UnityEngine.UIElements">
<ui:VisualElement>
<ui:VisualElement name="ComparisonHost" />
</ui:VisualElement>
</ui:UXML>The generated row uses Luna utility classes internally (flex-row, items-center, size-36, the icon-arrow-right arrow), so the panel's Panel Settings must point at the Luna theme — see Theme Stack.
using CupkekGames.Luna;
using UnityEngine;
using UnityEngine.UIElements;
public class ValueComparisonExample : MonoBehaviour
{
[SerializeField] private PanelRenderer _panelRenderer;
private ValueComparisonLineController _controller;
private void Awake()
{
if (_panelRenderer == null)
{
_panelRenderer = GetComponent<PanelRenderer>();
}
if (_panelRenderer != null)
{
_panelRenderer.RegisterUIReloadCallback(OnUIReload);
}
}
// PanelRenderer delivers the visual tree asynchronously —
// query elements in the reload callback, not in Awake/Start.
private void OnUIReload(PanelRenderer renderer, VisualElement root, int version)
{
if (_controller != null) return; // sentinel: only init once
VisualElement host = root.Q<VisualElement>("ComparisonHost");
float oldValue = 12f;
float newValue = 17f;
ValueDeltaType delta = ValueComparisonLine.GetDeltaType(newValue, oldValue);
var line = new ValueComparisonLine(
key: "Damage",
name: "Damage",
icon: null,
oldValue: oldValue.ToString(),
newValue: newValue.ToString(),
deltaType: delta,
hideOldValue: false
);
_controller = new ValueComparisonLineController(host, withName: true, withIcon: false);
_controller.SetData(line);
}
private void OnDestroy()
{
if (_panelRenderer != null)
{
_panelRenderer.UnregisterUIReloadCallback(OnUIReload);
}
}
}If you previously used item-specific stat line utilities:
ItemStatChangeType -> ValueDeltaTypeItemStatLine -> ValueComparisonLineItemStatLineController -> ValueComparisonLineControllerItemStatDataController still lives in Inventory because it depends on ItemStatData, but now uses these generic value-comparison utilities internally.
TooltipController the optional per-line tooltips run throughSettings
Theme
Light
Contrast
Material
Dark
Dim
Material Dark
System
Sidebar(Light & Contrast only)
Font Family
DM Sans
Wix
Inclusive Sans
AR One Sans
Direction