Last active
January 23, 2025 01:57
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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