Skip to content

Commit 103a3f8

Browse files
committed
feat(core): add tutorial interlude 4 code
1 parent 2db4fe3 commit 103a3f8

7 files changed

Lines changed: 147 additions & 117 deletions

File tree

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
Shader "Custom/Healthbar"
2+
{
3+
Properties
4+
{
5+
_Health ("Health", Range(0, 1)) = 1.0
6+
_LowHealthColor ("Low Health Color", Color) = (1, 0, 0, 1)
7+
_HighHealthColor ("High Health Color", Color) = (0, 1, 0, 1)
8+
_LowHealthThreshold ("Low Health Threshold", Range(0, 1)) = 0.2
9+
_HighHealthThreshold ("High Health Threshold", Range(0, 1)) = 0.8
10+
[NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
11+
[MaterialToggle] _PulseIfLow ("Pulse If Low", Float) = 1.0
12+
_Ratio ("Ratio", Float) = 8.0
13+
_BorderColor("Border Color", Color) = (0, 0, 0, 1)
14+
_BorderThickness ("Border Thickness", Range(0, 0.5)) = 0.2
15+
_Width ("Width", Float) = 5.0
16+
_Height ("Height", Float) = 0.5
17+
}
18+
SubShader
19+
{
20+
Tags {
21+
"RenderType" = "Opaque"
22+
"DisableBatching" = "True" // to avoid flickering when rendering multiple
23+
}
24+
25+
Pass
26+
{
27+
CGPROGRAM
28+
#pragma vertex vert
29+
#pragma fragment frag
30+
31+
#include "UnityCG.cginc"
32+
33+
struct MeshData
34+
{
35+
float4 vertex : POSITION;
36+
float2 uv : TEXCOORD0;
37+
};
38+
39+
struct Interpolators
40+
{
41+
float4 vertex : SV_POSITION;
42+
float2 uv : TEXCOORD0;
43+
};
44+
45+
float _Health;
46+
float4 _LowHealthColor;
47+
float4 _HighHealthColor;
48+
float _LowHealthThreshold;
49+
float _HighHealthThreshold;
50+
sampler2D _MainTex;
51+
float _PulseIfLow;
52+
float _Ratio;
53+
float4 _BorderColor;
54+
float _BorderThickness;
55+
float _Width;
56+
float _Height;
57+
58+
Interpolators vert (MeshData v)
59+
{
60+
Interpolators o;
61+
o.vertex = mul(UNITY_MATRIX_P,
62+
mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
63+
+ float4(v.vertex.x, v.vertex.y, 0.0, 0.0)
64+
* float4(_Width, _Height, 1.0, 1.0));
65+
o.uv = v.uv;
66+
return o;
67+
}
68+
69+
float InverseLerp( float a, float b, float v )
70+
{
71+
return ( v - a ) / ( b - a );
72+
}
73+
74+
float4 frag (Interpolators i) : SV_Target
75+
{
76+
float2 coords = i.uv;
77+
coords.x *= _Ratio;
78+
79+
float2 pointOnLineSegment = float2( clamp( coords.x, 0.5, _Ratio - 0.5 ), 0.5 );
80+
float sdf = distance( pointOnLineSegment, coords ) * 2 - 1;
81+
clip( -sdf );
82+
83+
float borderSdf = sdf + _BorderThickness;
84+
float pd = fwidth(borderSdf); // screen space partial derivative of borderSdf
85+
float borderMask = 1 - saturate( borderSdf / pd );
86+
87+
float fillMask = i.uv.x < _Health;
88+
89+
float3 texCol = tex2D( _MainTex, float2( _Health, i.uv.y ) );
90+
float tFillColor = saturate( InverseLerp ( _LowHealthThreshold, _HighHealthThreshold, _Health ) );
91+
float3 col = lerp( _LowHealthColor, _HighHealthColor, tFillColor );
92+
col *= texCol;
93+
94+
if ( ( _PulseIfLow == 1 ) && ( _Health <= 0.2 ) ) {
95+
float flash = cos( _Time.y * 4 ) * 0.3;
96+
col = saturate( col * ( 1 + flash ) );
97+
}
98+
99+
return float4( lerp( _BorderColor, col * fillMask, borderMask ), 1 );
100+
}
101+
ENDCG
102+
}
103+
}
104+
}

Assets/Resources/Shaders/Healthbar.shader.meta

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Scripts/Tools/Utils.cs

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
using System.Collections.Generic;
2-
using System.Text.RegularExpressions;
1+
using System.Collections.Generic;
2+
using System.Text.RegularExpressions;
33
using UnityEngine;
44

55
public static class Utils
@@ -79,40 +79,6 @@ public static Bounds GetViewportBounds(Camera camera, Vector3 screenPosition1, V
7979
return bounds;
8080
}
8181

82-
public static Rect GetBoundingBoxOnScreen(Bounds bounds, Camera camera)
83-
{
84-
// get the 8 vertices of the bounding box
85-
Vector3 center = bounds.center;
86-
Vector3 size = bounds.size;
87-
Vector3[] vertices = new Vector3[] {
88-
center + Vector3.right * size.x / 2f + Vector3.up * size.y / 2f + Vector3.forward * size.z / 2f,
89-
center + Vector3.right * size.x / 2f + Vector3.up * size.y / 2f - Vector3.forward * size.z / 2f,
90-
center + Vector3.right * size.x / 2f - Vector3.up * size.y / 2f + Vector3.forward * size.z / 2f,
91-
center + Vector3.right * size.x / 2f - Vector3.up * size.y / 2f - Vector3.forward * size.z / 2f,
92-
center - Vector3.right * size.x / 2f + Vector3.up * size.y / 2f + Vector3.forward * size.z / 2f,
93-
center - Vector3.right * size.x / 2f + Vector3.up * size.y / 2f - Vector3.forward * size.z / 2f,
94-
center - Vector3.right * size.x / 2f - Vector3.up * size.y / 2f + Vector3.forward * size.z / 2f,
95-
center - Vector3.right * size.x / 2f - Vector3.up * size.y / 2f - Vector3.forward * size.z / 2f,
96-
};
97-
Rect retVal = Rect.MinMaxRect(float.MaxValue, float.MaxValue, float.MinValue, float.MinValue);
98-
99-
// iterate through the vertices to get the equivalent screen projection
100-
for (int i = 0; i < vertices.Length; i++)
101-
{
102-
Vector3 v = camera.WorldToScreenPoint(vertices[i]) / GameManager.instance.canvasScaleFactor;
103-
if (v.x < retVal.xMin)
104-
retVal.xMin = v.x;
105-
if (v.y < retVal.yMin)
106-
retVal.yMin = v.y;
107-
if (v.x > retVal.xMax)
108-
retVal.xMax = v.x;
109-
if (v.y > retVal.yMax)
110-
retVal.yMax = v.y;
111-
}
112-
113-
return retVal;
114-
}
115-
11682
public static Vector3 MiddleOfScreenPointToWorld()
11783
{ return MiddleOfScreenPointToWorld(MainCamera); }
11884
public static Vector3 MiddleOfScreenPointToWorld(Camera cam)

Assets/Scripts/UI/Healthbar.cs

Lines changed: 0 additions & 49 deletions
This file was deleted.

Assets/Scripts/UI/Healthbar.cs.meta

Lines changed: 0 additions & 11 deletions
This file was deleted.

Assets/Scripts/Units/Buildings/BuildingManager.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,16 @@ protected override bool IsMovable()
107107

108108
protected override void UpdateHealthbar()
109109
{
110-
if (!healthbar) return;
111-
Transform fill = healthbar.transform.Find("Fill");
110+
if (!_healthbarRenderer) return;
112111

113112
// if in construction: show current construction HP
114113
// else, show current health
115114
int hp = (IsActive() && !_building.IsAlive)
116115
? _building.ConstructionHP
117116
: Unit.HP;
118-
fill.GetComponent<UnityEngine.UI.Image>().fillAmount = hp / (float)Unit.MaxHP;
117+
118+
_healthbarRenderer.GetPropertyBlock(_MaterialPropertyBlock);
119+
_MaterialPropertyBlock.SetFloat("_Health", hp / (float)Unit.MaxHP);
120+
_healthbarRenderer.SetPropertyBlock(_MaterialPropertyBlock);
119121
}
120122
}

Assets/Scripts/Units/UnitManager.cs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@
55
[RequireComponent(typeof(BoxCollider))]
66
public class UnitManager : MonoBehaviour
77
{
8+
protected static MaterialPropertyBlock _materialPropertyBlock;
9+
protected static MaterialPropertyBlock _MaterialPropertyBlock
10+
{
11+
get
12+
{
13+
if (_materialPropertyBlock == null)
14+
_materialPropertyBlock = new MaterialPropertyBlock();
15+
return _materialPropertyBlock;
16+
}
17+
}
18+
819
public GameObject selectionCircle;
920
public GameObject fov;
1021
public Renderer meshRenderer;
@@ -22,8 +33,8 @@ public class UnitManager : MonoBehaviour
2233
public int SelectIndex { get => _selectIndex; }
2334
private bool _hovered = false;
2435

25-
protected GameObject healthbar;
26-
private Transform _canvas;
36+
public GameObject healthbar;
37+
protected Renderer _healthbarRenderer;
2738
private GameObject _levelUpVFX;
2839
private Material _levelUpVFXMaterial;
2940
private Coroutine _levelUpVFXCoroutine = null;
@@ -33,8 +44,13 @@ public class UnitManager : MonoBehaviour
3344

3445
private void Awake()
3546
{
36-
_canvas = GameObject.Find("Canvas").transform;
3747
_meshSize = meshRenderer.GetComponent<Renderer>().bounds.size / 2;
48+
49+
if (healthbar)
50+
{
51+
healthbar.SetActive(false);
52+
_healthbarRenderer = healthbar.GetComponent<Renderer>();
53+
}
3854
}
3955

4056
private void OnMouseEnter()
@@ -137,8 +153,7 @@ public void Deselect()
137153

138154
EventManager.TriggerEvent("DeselectedUnit", Unit);
139155
selectionCircle.SetActive(false);
140-
Destroy(healthbar);
141-
healthbar = null;
156+
healthbar.SetActive(false);
142157
_selected = false;
143158
_selectIndex = -1;
144159
}
@@ -169,18 +184,10 @@ private void _SelectUtil()
169184
Globals.SELECTED_UNITS.Add(this);
170185
EventManager.TriggerEvent("SelectedUnit", Unit);
171186
selectionCircle.SetActive(true);
172-
if (healthbar == null)
187+
if (healthbar)
173188
{
174-
healthbar = GameObject.Instantiate(Resources.Load("Prefabs/UI/Healthbar")) as GameObject;
175-
healthbar.transform.SetParent(_canvas);
189+
healthbar.SetActive(true);
176190
UpdateHealthbar();
177-
Healthbar h = healthbar.GetComponent<Healthbar>();
178-
Rect boundingBox = Utils.GetBoundingBoxOnScreen(
179-
meshRenderer.bounds,
180-
Camera.main
181-
);
182-
h.Initialize(transform, IsMovable(), boundingBox.height * 0.5f);
183-
h.SetPosition();
184191
}
185192

186193
// play sound
@@ -199,9 +206,10 @@ private void _Die()
199206

200207
protected virtual void UpdateHealthbar()
201208
{
202-
if (!healthbar) return;
203-
Transform fill = healthbar.transform.Find("Fill");
204-
fill.GetComponent<UnityEngine.UI.Image>().fillAmount = Unit.HP / (float)Unit.MaxHP;
209+
if (!_healthbarRenderer) return;
210+
_healthbarRenderer.GetPropertyBlock(_MaterialPropertyBlock);
211+
_MaterialPropertyBlock.SetFloat("_Health", Unit.HP / (float)Unit.MaxHP);
212+
_healthbarRenderer.SetPropertyBlock(_MaterialPropertyBlock);
205213
}
206214

207215
public void LevelUp()

0 commit comments

Comments
 (0)