Exercise: a fight you can lose
Assets/
Scripts/
everything from tab 01–02
you already havethis lesson adds
Stay in Arena.unity and make everything from this tab work together at once: the Knight moving and animating, three skills on cooldown, three dummies with health bars, two artifacts — and Mage and Archer still there on keys 2 and 3.
what you reuse
Everything from tab 02 running at once in one scene.
Build it in four passes
Pass 1 — the character works
The Knight already has its model, CharacterController and CameraTarget from lesson 01 of this tab. Check it is still a prefab in Assets/Prefabs.
CharacterController sized to the body, PlayerMovement with walk / run / jump and gravity.
Animator with a Locomotion blend tree driven by Speed, plus Jump and Attack.
CharacterStats on the Knight with maxHealth 200, attack 25, defense 8, moveSpeed 5. Mage and Archer keep SimpleMover and no stats — they are scenery for now.
Pass 2 — three skills that feel different
Three ScriptableObject assets, three genuinely different jobs. If all three just deal damage in a sphere, you have one skill with three names.
Skill_Slash Q cooldown 1.5 mana 5 damage 30 range 3 melee sphere in front
Skill_Bolt E cooldown 4.0 mana 20 damage 55 projectile prefab
Skill_Nova R cooldown 12 mana 45 damage 90 range 6 hits everything around// in SkillData.cs
public enum SkillShape { MeleeArc, Projectile, Nova }
public SkillShape shape = SkillShape.MeleeArc;
// in SkillCaster.TryCast, replace the single ApplyDamage call
switch (s.shape)
{
case SkillShape.MeleeArc:
HitSphere(transform.position + transform.forward * s.range * 0.5f, s.range, s);
break;
case SkillShape.Projectile:
GameObject go = Instantiate(s.projectilePrefab, castPoint.position, castPoint.rotation);
go.GetComponent<Projectile>().Launch(gameObject, s.damage);
break;
case SkillShape.Nova:
HitSphere(transform.position, s.range, s);
break;
}
void HitSphere(Vector3 center, float radius, SkillData s)
{
foreach (Collider hit in Physics.OverlapSphere(center, radius, enemyLayers))
if (hit.TryGetComponent(out CharacterStats target))
target.TakeDamage(s.damage);
}Pass 3 — the dummies fight back (a little)
Three dummies on the Enemy layer, each with CharacterStats, a world-space health bar and HitFlash.
Give each a different maxHealth: 80, 120, 200 — so you can feel your damage numbers.
On death, disable the dummy and respawn it after 3 seconds so you can keep testing.
using System.Collections;
using UnityEngine;
public class Respawner : MonoBehaviour
{
[SerializeField] private CharacterStats stats;
[SerializeField] private float delay = 3f;
[SerializeField] private GameObject[] toHide;
void OnEnable() => stats.OnDied += HandleDeath;
void OnDisable() => stats.OnDied -= HandleDeath;
void HandleDeath() => StartCoroutine(Revive());
IEnumerator Revive()
{
foreach (GameObject g in toHide) g.SetActive(false);
yield return new WaitForSeconds(delay);
stats.currentHealth = stats.finalMaxHp;
foreach (GameObject g in toHide) g.SetActive(true);
}
}Pass 4 — two artifacts that visibly matter
Artifact_Ember: +40 flat Attack. Artifact_Swift: +25% MoveSpeed and +15% Attack.
Bind keys 7 and 8 to Equip / Unequip so you can toggle them while playing.
Skills must read finalAttack, not the base attack — otherwise equipping does nothing.
// in SkillCaster
float outgoing = s.damage * (myStats.finalAttack / 100f + 1f);
target.TakeDamage(outgoing);Done when
- ✓The Knight walks, runs with Shift, jumps, and the animation matches what it is doing — while keys 2 and 3 still hand control to the Mage and Archer.
- ✓Q, E and R each do something visibly different, and each has its own cooldown ring in the UI.
- ✓Casting with not enough mana, or on cooldown, is refused — and the player can tell why.
- ✓Every hit shows a damage number, a white flash, and a health bar that drops.
- ✓A dummy at 0 HP disappears and comes back 3 seconds later at full health.
- ✓Equipping an artifact changes finalAttack in the Inspector AND changes the damage numbers on screen.
- ✓Unequipping puts every number back exactly where it was — no drift.
- ✓No errors in the Console after two minutes of mashing every key.
Numbers to hit
| Metric | Target | Why |
|---|---|---|
| Time to kill a 120 HP dummy | 4–8 s | Under 4 s and skills feel pointless; over 8 s and it drags. |
| Input → visible reaction | < 100 ms | Anything slower reads as a broken button. |
| Artifact effect on damage | ≥ 20% | A bonus you cannot see is not a reward. |
| GC allocation per cast | 0 B | Pool the projectiles and popups; check in the Profiler. |
If you want more
Give one dummy a Chase state: it walks towards you when you get within 8 m.
Add a fourth skill that heals instead of damaging — reuse the same SkillData with negative damage.
Make Nova knock the dummies back with AddExplosionForce.
Show a tooltip built by BuildTooltip when you hover an artifact icon.