Skip to content

Instantly share code, notes, and snippets.

@LotteMakesStuff
Last active March 24, 2023 16:37
Show Gist options
  • Star 41 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save LotteMakesStuff/b8853a16de3e680dc1c326fe6f5ebd7e to your computer and use it in GitHub Desktop.
Save LotteMakesStuff/b8853a16de3e680dc1c326fe6f5ebd7e to your computer and use it in GitHub Desktop.
StatsBar property drawer for Unity~ Add a [StatsBar] attribute to a property to make it draw a lil bar, really useful for visualizing character stats like Health or Mana.
// NOTE DONT put in an editor folder
using UnityEngine;
public class StatsBarAttribute : PropertyAttribute
{
public string valueMax;
public StatsBarColor color;
public StatsBarAttribute(string valueMax = null, StatsBarColor color = StatsBarColor.Red)
{
this.valueMax = valueMax;
this.color = color;
}
}
public enum StatsBarColor
{
Red,
Pink,
Orange,
Yellow,
Green,
Blue,
Indigo,
Violet,
White
}
// NOTE put in a Editor folder
using UnityEngine;
using UnityEditor;
using System.Collections;
[CustomPropertyDrawer(typeof(StatsBarAttribute))]
public class StatsBarDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var valueMax = property.serializedObject.FindProperty((attribute as StatsBarAttribute).valueMax);
float lineHight = EditorGUIUtility.singleLineHeight;
float padding = EditorGUIUtility.standardVerticalSpacing;
var barPosition = new Rect(position.position.x, position.position.y, position.size.x, lineHight);
float fillPercentage = 0;
string barLabel = "";
bool error = false;
switch (property.propertyType)
{
case SerializedPropertyType.Integer:
if (valueMax == null)
{
error = true;
barLabel = "you must provide a valueMax in the StatsBarAttribute!";
}
else
{
fillPercentage = property.intValue / (float)valueMax.intValue;
barLabel = "[" + property.name + "] " + property.intValue + "/" + valueMax.intValue;
}
break;
case SerializedPropertyType.Float:
if (valueMax == null)
{
if (property.floatValue > 1)
{
error = true;
barLabel = "property value is over 1, and no max value has been specified!";
break;
}
fillPercentage = property.floatValue / 1;
barLabel = "[" + property.name + "] " + (int)property.floatValue + "/" + 1;
}
else
{
if (valueMax.propertyType != SerializedPropertyType.Float)
{
error = true;
barLabel = "valueMax's type has to match the type of this property";
break;
}
fillPercentage = property.floatValue / valueMax.floatValue;
barLabel = "[" + property.name + "] " + (int)property.floatValue + "/" + valueMax.floatValue;
}
break;
default:
error = true;
barLabel = "unsupported type for a stats bar";
return;
}
if (error)
{
GUI.Label(barPosition, barLabel);
}
else
{
var color = GetColor((attribute as StatsBarAttribute).color);
var color2 = Color.white;
DrawBar(barPosition, Mathf.Clamp01(fillPercentage), barLabel, color, color2);
}
EditorGUI.PropertyField(new Rect(position.position.x, position.position.y+ lineHight + padding, position.size.x, lineHight), property);
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return (EditorGUIUtility.singleLineHeight * 2) + EditorGUIUtility.standardVerticalSpacing;
}
private void DrawBar(Rect position, float fillPercent, string label, Color barColor, Color labelColor)
{
if (Event.current.type != EventType.Repaint)
return;
Color savedColor = GUI.color;
var fillRect = new Rect(position.x, position.y, position.width * fillPercent, position.height);
EditorGUI.DrawRect(position, new Color(0.1f, 0.1f, 0.1f));
EditorGUI.DrawRect(fillRect, barColor);
// set alignment and cash the default
var align = GUI.skin.label.alignment;
GUI.skin.label.alignment = TextAnchor.UpperCenter;
// set the color and cash the default
var c = GUI.contentColor;
GUI.contentColor = labelColor;
// calculate the position
var labelRect = new Rect(position.x, position.y-3, position.width, position.height);
// draw~
EditorGUI.DropShadowLabel(labelRect, label);
// reset color and alignment
GUI.contentColor = c;
GUI.skin.label.alignment = align;
}
private Color GetColor(StatsBarColor color)
{
switch (color)
{
case StatsBarColor.Red:
return new Color32(255, 0, 63, 255);
case StatsBarColor.Pink:
return new Color32(255, 152, 203, 255);
case StatsBarColor.Orange:
return new Color32(255, 128, 0, 255);
case StatsBarColor.Yellow:
return new Color32(255, 211, 0, 255);
case StatsBarColor.Green:
return new Color32(102, 255, 0, 255);
case StatsBarColor.Blue:
return new Color32(0, 135, 189, 255);
case StatsBarColor.Indigo:
return new Color32(75, 0, 130, 255);
case StatsBarColor.Violet:
return new Color32(127, 0, 255, 255);
default:
return Color.white;
}
}
}
// Test compoent
using UnityEngine;
using System.Collections;
public class StatsComponent : MonoBehaviour
{
// Apply the StatsBar property Drawer to out property. Were passing "statMax" into the attribute.
// This is the name of the property that holds the maximum value the stat property can hold. The
// Drawer can then use this to look up the max value and get percentages correct. Because the max
// value is backed by a property, it can change whilst our game is running (like, say we grow a level)!
[StatsBar("statMax", StatsBarColor.Red)]
public float health = 25;
[StatsBar("statMax", StatsBarColor.Blue)]
public float mana = 50;
[StatsBar("statMax", StatsBarColor.Yellow)]
public float strength = 90;
public float statMax = 100;
void Start () {
health = 100;
mana = 100;
strength = 100;
}
void Update ()
{
health -= Time.deltaTime;
mana -= Time.deltaTime*4;
strength -= Time.deltaTime*8;
if (health < 25)
health = 100;
if (mana < 25)
mana = 100;
if (strength < 25)
strength = 100;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment