Guide 6 — Cozy Critters
Rhys Watson
What you're building
A pet sim in the Tamagotchi tradition, minus the anxiety. Your pitch is explicit: "the fear of the pet dying after 2 seconds of not paying attention does not exist." The pet idles and walks around one area, you have options to care for it, and caring for it raises happiness and shapes what kind of creature it becomes.
Nothing in this build can kill the pet. That's enforced in the scripts, not just in the design — need decay is measured per minute, and low needs make the pet slower and sadder, never dead.
Yours is the third movement rig and the only game with no player character at all. Light on scripts, heavy on UI.
Time: about two and a half hours, most of it UI.
1. Before you start
- Finish Guide 0.
- You need Guide B §B2 (managers) only. No player prefab, no camera rig.
- No extra packages, no new input actions — your game is played with mouse clicks.
2. Scripts you'll use
The pet (Tier 7)
NeedStat · PetBrain · CareAction · PersonalityTracker
Movement (Tier 5)
TopDownMover — in AI mode, driven by PetBrain rather than the player
Saving (Tier 7)
SaveData · SaveSystem
Core
GameManager · SceneLoader · AudioManager · HUDController · ChoiceFlagManager · (optionally ItemType, Collectible, CollectionTracker if food is limited)
You will not need: PlayerController2D, Health, Checkpoint, RespawnManager, or any combat. There is no player character and nothing takes damage.
3. Build the pet
- GameObject → Create Empty, name it
Pet. - Sprite Renderer with your critter sprite. (Species undecided is fine — a placeholder blob works, and you can swap the sprite any time.)
- Add:
| Component | Settings |
|---|---|
| Rigidbody2D | Gravity Scale 0 · Freeze Rotation Z ✓ |
| Capsule Collider 2D | fit the critter |
| TopDownMover | AI Controlled ✓ · Move Speed 2 · Facing FlipSprite |
| Animator | leave the controller empty for now |
| PlayerAnimatorBridge | leave its Controller field empty — PetBrain drives it |
AI Controlled ✓ is the key setting. It tells TopDownMover to ignore player input and wait for PetBrain to feed it directions. Without it your pet would respond to WASD, which is not the game.
Move Speed 2 is slow on purpose. A pet that darts around doesn't read as cozy.
4. Add the needs
You'll add three NeedStat components to the same Pet object. Three components of the same type on one object is unusual but correct here — each one is a different need.
Add them in this order, because the third one gets referenced by the first two.
4c first: Happiness
| Field | Value |
|---|---|
| Stat Name | Happiness |
| Value | 100 |
| Max Value | 100 |
| Decay Per Minute | 1 |
| Higher Is Better | ✓ |
| Low Threshold | 30 |
| Full Threshold | 90 |
| Affects Happiness | ✗ (it IS happiness) |
4a: Hunger
| Field | Value |
|---|---|
| Stat Name | Hunger |
| Value | 100 |
| Decay Per Minute | 3 |
| Low Threshold | 30 |
| Affects Happiness | ✓ |
| Happiness Stat | drag the Pet object in, then pick the Happiness component |
| Happiness Drain Per Minute | 2 |
4b: Energy
| Field | Value |
|---|---|
| Stat Name | Energy |
| Value | 100 |
| Decay Per Minute | 2 |
| Low Threshold | 20 |
| Affects Happiness | ✓ |
| Happiness Stat | the Happiness component again |
| Happiness Drain Per Minute | 1 |
Why the numbers are so low
At 3 per minute, a full hunger bar takes 33 minutes to empty. That's the whole point of your pitch. Compare: a classic Tamagotchi drains in a few minutes and punishes you for looking away.
If it feels too slow while you're testing, don't raise the decay — instead add a debug button that drains a stat instantly so you can test the low states without waiting half an hour.
Assigning the Happiness Stat field: drag the
PetGameObject into the slot. Unity will ask whichNeedStatyou mean — pick the one showingHappiness. If it grabs the wrong one, click the small circle in the field and choose from the list.
5. Add the brain
On Pet, add PetBrain:
| Field | Value |
|---|---|
| Energy | drag in the Energy NeedStat |
| Happiness | the Happiness one |
| Hunger | the Hunger one |
| Wander Area | see below |
| Wander Radius | 3 |
| Idle Time Range | (2, 5) |
| Walk Time Range | (1, 3) |
| Arrive Distance | 0.2 |
| Sleep Below Energy | 0.2 |
| Wake Above Energy | 0.8 |
| Energy Restored Per Minute | 20 |
| Sad Speed Multiplier | 0.6 |
The wander area
Your pitch says "there will only be one area." Two ways to define it:
- Simple: leave Wander Area empty and set Wander Radius to 3. The pet stays within 3 units of where it started.
- Precise: make an empty GameObject
PenAreawith a Box Collider 2D (Is Trigger ✓) covering the pen, and drag it into Wander Area. The pet wanders anywhere inside that box.
Use the box if your pen isn't circular. The gizmo shows you the area when the pet is selected.
What the brain does
Four states: Idle (stands, waits 2–5s), Wander (walks to a random nearby point), Sleep (when energy drops below 20%, refilling as it sleeps), and React (a brief perk-up when you care for it).
The ranges are ranges rather than fixed numbers so the pet doesn't feel mechanical. Don't set them both to the same value.
6. Build the care actions
One CareAction component per button. Put them on separate empty GameObjects so they're easy to find.
Feed
- GameObject → Create Empty, name it
FeedAction. - Add CareAction:
| Field | Value |
|---|---|
| Action Name | Feed |
| Effects | (size 2) |
| → Element 0 | Stat = Hunger, Amount 40 |
| → Element 1 | Stat = Happiness, Amount 5 |
| Requires Item | (empty — unlimited food) |
| Cooldown | 5 |
| Pet | drag the Pet object in |
| Personality Trait | well_fed |
| Effect Prefab | a little particle burst, if you have one |
| Sfx Name | care |
Play
Same, on a PlayAction object:
| Field | Value |
|---|---|
| Action Name | Play |
| Effects → Element 0 | Happiness +25 |
| Effects → Element 1 | Energy −15 |
| Cooldown | 8 |
| Personality Trait | playful |
Play costs energy. That's the one bit of tension in a cozy game: playing makes the pet happy and tired, so you can't just spam it. Small, but it makes the loop a loop.
Pet (stroke)
| Field | Value |
|---|---|
| Action Name | Pet |
| Effects → Element 0 | Happiness +15 |
| Cooldown | 4 |
| Personality Trait | cuddled |
Clean, Sleep, or others
Add as many as you like. Each one needs a different Personality Trait string, because those traits are what PersonalityTracker counts.
7. Add personalities
On Pet, add PersonalityTracker:
| Field | Value |
|---|---|
| Personalities | see below |
| Evaluate Every | 15 |
| Minimum Actions | 10 |
| Dominance Threshold | 0.4 |
| Happiness | drag the Happiness NeedStat in |
| Sad Personality Id | withdrawn |
| Sad Below | 0.25 |
| Sad Minutes Required | 5 |
Fill in the Personalities list
| # | Id | Display Name | Trait | Tint |
|---|---|---|---|---|
| 0 | ordinary | Ordinary | (leave empty — this is the default) | white |
| 1 | plump | Well-Fed | well_fed | slightly warm |
| 2 | playful | Playful | playful | slightly bright |
| 3 | affectionate | Affectionate | cuddled | slightly pink |
| 4 | withdrawn | Withdrawn | (leave empty) | slightly grey |
One personality must have an empty Trait — that's the fallback used before the pet has enough history.
How it decides
Every 15 seconds it compares the counters. It only settles on a personality once there have been 10 care actions total and one trait holds 40% or more of them. That prevents the pet flipping identity every few minutes.
If you have Animator Controllers per personality, drag them into each entry and the pet's whole animation set changes when its nature does — a lot of visible variety from a little art. The Tint field is the cheap version of the same idea.
8. The UI
This is the bulk of your work. Take it in two passes: buttons first, then bars.
Buttons
- GameObject → UI → Canvas.
- Right-click Canvas → UI → Button - TextMeshPro. Name it
FeedButton. Put it along the bottom. - Change its text to
Feed. - In the button's On Click (): click +, drag
FeedActionin, chooseCareAction.Perform. - Duplicate for
PlayButtonandPetButton, pointing at their own actions.
Stat bars
For each need:
- Right-click Canvas → UI → Slider, name it
HungerBar. - Delete the Handle Slide Area child, set Interactable ✗, Min 0 / Max 1.
- Colour the Fill — orange for hunger, blue for energy, pink for happiness.
- Add a TMP label next to it.
Repeat for EnergyBar and HappinessBar.
Optional but nice
- A TMP text showing the current personality name
- A "Welcome back — you were away 12 minutes" message on load
- Greying out a button while it's on cooldown (wire
OnCooldownChangedto a Slider or the button's Image fill)
9. Saving
- Empty GameObject
SaveSystem+ the SaveSystem component:
| Field | Value |
|---|---|
| Slot Name | save1 |
| Log Save Path | ✓ (useful — see below) |
| Save Flags | ✓ |
| Save Collectibles | ✗ (unless food is limited) |
| Save Player Position | ✗ |
| Save Pet Stats | ✓ |
| Save Clues | ✗ |
| Load On Start | ✓ |
| Save On Quit | ✓ |
| Auto Save Every | 60 |
| Persist Across Scenes | ✓ |
| Apply Offline Decay | ✓ |
| Max Offline Minutes | 480 |
- You also need a
ChoiceFlagManagerin the scene —PersonalityTrackerstores its trait counters there.
Offline decay — the Tamagotchi part, done kindly
When you reopen the game, SaveSystem tells each NeedStat how many real minutes you were away and decays accordingly. Max Offline Minutes 480 caps it at eight hours, so going away for a week doesn't return you to an empty pet. That cap is what makes this the cozy version.
Look at your own save file
With Log Save Path ticked, the Console prints where the file lives. Open it in Notepad — it's readable JSON with your pet's stats in it. Genuinely worth doing once; seeing your save as plain text explains more about how games store data than any explanation.
10. Camera and managers
Camera
Static. Select Main Camera, set Projection → Orthographic, and set Size so the pen fills the screen nicely (try 4). Position (0, 0, −10). No Cinemachine, no follow — a camera chasing a wandering pet would be unpleasant.
Managers
GameManager, AudioManager, SceneLoader, ChoiceFlagManager, SaveSystem.
11. Wire it up
| On this object | Event | Drag in | Choose |
|---|---|---|---|
FeedButton | On Click | FeedAction | CareAction.Perform |
PlayButton | On Click | PlayAction | CareAction.Perform |
PetButton | On Click | PetAction | CareAction.Perform |
Pet → Hunger NeedStat | On Value Changed | HungerBar | Slider.value (Dynamic float) |
Pet → Energy NeedStat | On Value Changed | EnergyBar | Slider.value (Dynamic float) |
Pet → Happiness NeedStat | On Value Changed | HappinessBar | Slider.value (Dynamic float) |
Pet → Hunger NeedStat | On Became Low | AudioManager | PlaySFX (string) → sad |
PetBrain | On Fell Asleep | AudioManager | PlaySFX (string) → snore |
All three bar wirings must use Dynamic float — OnValueChanged sends a 0–1 number and the static version would pin the bar.
Picking the right NeedStat: when you drag
Petinto an event slot and open the function dropdown, you'll seeNeedStatlisted three times. They're in the order you added the components. Click each one and check the Inspector to be sure — or temporarily rename them by reordering, since the Stat Name field doesn't show in the dropdown.
12. First playtest
- The pet idles, then wanders, then idles again. If it doesn't move, is AI Controlled ticked on
TopDownMover? IsPetBrainthere? - It stays inside the pen — check Wander Area or Wander Radius.
- All three bars slowly fall. Very slowly. Watch for thirty seconds.
- Feed raises the hunger bar and the pet perks up (React state).
- The button won't work again for 5 seconds (cooldown).
- Play raises happiness and lowers energy.
- Set Energy's Value to 15 in the Inspector while playing — the pet should lie down and sleep, then wake as energy refills.
- Quit and reopen. Stats should be roughly where you left them, minus a little decay.
Step 7 is the fastest way to test sleep without waiting. Editing a value in the Inspector during Play mode is a normal debugging technique — the change reverts when you stop.
13. Then add
- A species. Your pitch says undecided — the whole build works with any sprite, so try three and see which reads best. A creature with a clear idle pose and a clear happy pose is worth more than a detailed one.
- Animation. Idle, Walk, Sleep is enough. Guide B §B6 — you need
Speed,IsSleeping, and optionallyIsHappy. - More care actions — bathe, brush, give a toy. Each one needs its own trait.
- Personality animator controllers so a playful pet moves differently from a sleepy one.
- Decoration for the pen — a bed, a bowl, a window. Static sprites, no scripts.
- A day/night tint on the background.
- Limited food, if you want the sim to have an economy: make an
ItemTypecalledFood, add aCollectionTracker, and setRequires Itemon the Feed action.
14. Design notes for your game specifically
You removed the punishment, so you need a different reason to come back. Tamagotchi used guilt. Yours can't. What you have instead is change over time — the personality system means the pet becomes something specific because of how you treated it, and that's a much kinder hook. Make the personality visible: a name on screen, a different idle pose, a colour shift. If the player can't see it, it isn't doing its job.
Cooldowns are your pacing. With no death and no timer, the only thing stopping a player from maxing every bar in ten seconds is the cooldown. They're not an annoyance — they're what makes caring for the pet an ongoing relationship rather than a single button press.
There is no wrong personality. PersonalityTracker is descriptive, not a score. Resist the urge to make one outcome "best" — the moment there's an optimal way to raise the pet, it stops being cozy and starts being a puzzle.
The withdrawn personality is the closest thing to a fail state, and it's reversible. It only appears after five minutes of sustained low happiness, and it goes away when you look after the pet again. That's the right amount of consequence for your game: noticeable, gentle, fixable.
Offline decay is a design lever, not just a feature. Eight hours capped means a player who comes back after a day finds a pet that's a bit hungry, not a disaster. If you want returning to feel more urgent, lower the cap. I'd leave it.
15. Common problems
| What you see | What's wrong |
|---|---|
| Pet doesn't move | AI Controlled unticked on TopDownMover, or PetBrain missing |
| Pet wanders out of the pen | Wander Area not assigned, or Wander Radius too big |
| Pet won't stop moving | Idle Time Range is (0, 0) |
| Bars don't move | Decay Per Minute is 0 — or you're just not waiting long enough. Check by setting one to 60 temporarily |
| Bars stuck at full | Wired to the static value instead of Dynamic float |
| Wrong bar updates | You picked the wrong NeedStat from the three in the dropdown |
| Feed does nothing | Effects list is empty, or the Stat field in an effect isn't assigned |
| Buttons do nothing | On Click not wired, or you dragged the Pet in instead of the CareAction object |
| Pet never sleeps | Sleep Below Energy is 0, or Energy never gets that low — test by editing the value during Play |
| Personality never changes | No ChoiceFlagManager in the scene, or Minimum Actions not reached yet, or the traits on your CareActions don't match the Personalities list |
| Stats reset every launch | Load On Start unticked, or Save Pet Stats unticked |
| Pet is starving on every return | Max Offline Minutes too high, or Apply Offline Decay is doing exactly what you asked — lower the decay rates |