
ここまでで、お世話・放置・ショップと、育成ゲームの仕組みがそろいました。でも「育てている感」を一番感じるのは、やっぱりペットの見た目が変わる瞬間!シリーズ最終回の今回は、お世話の回数でペットが進化する仕組みと、最後まで育てたときのエンディング、そしてスマホで遊べるようにビルドするところまで作ってみたいと思います!
- シリーズの目次:ペット育成ゲームの作り方
- 前回:#7 コインでアイテムを買えるショップを作ろう
今回作るもの
- お世話の回数を数えて、3段階に進化する
- 進化したときに「〇〇に進化した!」のお知らせを出す
- 最後まで育てたらエンディング。「もういちど そだてる」で最初からやり直せる
- Android向けにビルドして、スマホで遊ぶ
| スクリプト | 今回やること |
|---|---|
| EvolutionData | 進化の段階1つ分のデータ(ScriptableObject、新しく作る) |
| PetStatus | お世話の回数を足す |
| PetController | お世話のたびに回数を数える |
| OfflineProgress | 読み込むときに、お世話の回数も戻す |
| EvolutionController | 進化の判定・見た目の切り替え・エンディング(新しく作る) |
前回の続きから
- Unityのバージョンは6.3 LTS
- 記事作成時点では6000.3.22f1で確認しています
- テンプレートはUniversal 2D
- #7の状態:ショップでアイテムを買って、ペットにあげられる
ビルドについては10-1 ビルドの基本と10-4 プラットフォームの変更とクロスプラットフォーム開発、ScriptableObjectは12-8 ScriptableObjectでデータを作ろうで紹介しています。
進化の素材を取り込もう
2段階目・3段階目のペットの画像、6枚を使います。
- pet2_idle・pet2_happy・pet2_sad:耳が伸びた2段階目
- pet3_idle・pet3_happy・pet3_sad:王冠をかぶった3段階目
素材は下のリンクからダウンロードしてください。シリーズで使う画像と音が全部入っているので、1回ダウンロードすれば#8まで使えます。
- PetRaisingAssets.zip(約4MB)
取り込み方は2つあります。
- かんたん:zipの中の
PetRaisingAssets.unitypackageをダブルクリック(またはUnityでAssets>Import Package>Custom Package…)。画像の取り込み設定(Sprite・Single)ごと入ります - 自分で入れる:zipの中の
PetRaisingフォルダを、UnityのAssetsにドラッグ&ドロップ(画像はSprite Mode:Singleにする)
素材は自由に使ってOKです(クレジット不要。作ったゲームの公開・販売にも使えます)。素材そのものの再配布はご遠慮ください。
- 6枚を PetRaising/Sprites に入れる
- まとめて選んで、Texture Type:Sprite (2D and UI)、Sprite Mode:Single にしてApply
表情の切り替えを、スクリプトからにしよう
#2では、待機・喜ぶ・しょんぼりのアニメーションの中で、Image.Sprite(表情)も一緒に切り替えていました。ただ、進化で絵が変わるとなると、段階ごとにアニメーションを作り直すことになってしまいます・・・。
そこで、アニメーションは動き(位置と大きさ)だけにして、表情はスクリプトで切り替えるようにします。
- Animationウインドで、PetIdle・PetHappy・PetSadの3つのクリップを順番に開く
- 左側の「Pet : Image.Sprite」を右クリック>Remove Properties で消す
- 3つとも消したら、Animationウインドを閉じる

スライムアニメーションで絵を切り替えるのは、段階が1つだけのときはラク。でも見た目が増えると、スクリプトで切り替える方が管理しやすくなります
進化のデータを作ろう(EvolutionData)
進化の段階1つ分のデータです。#7のItemDataと同じ、ScriptableObjectで作ります。
- PetRaising/Scriptsに「EvolutionData」を作る
using UnityEngine;
// 進化の段階1つ分のデータ。Project ウインドの Create>PetRaising>Evolution Stage でアセットを作れる
[CreateAssetMenu(fileName = "NewStage", menuName = "PetRaising/Evolution Stage")]
public class EvolutionData : ScriptableObject
{
public string stageName; // 段階の名前(「ぴょこすけ」など)
public int requiredCareCount; // この段階になるのに必要なお世話の回数
public Sprite idleSprite; // ふつうの顔
public Sprite happySprite; // 笑顔
public Sprite sadSprite; // 泣き顔
}
- PetRaising/Dataの中に「Stages」フォルダを作る
- Stagesフォルダで右クリック>Create>PetRaising>Evolution Stage で、下の3つを作る
| ファイル名 | Stage Name | Required Care Count | Idle | Happy | Sad |
|---|---|---|---|---|---|
| Stage1 | ぴよまる | 0 | pet_idle | pet_happy | pet_sad |
| Stage2 | ぴょこすけ | 10 | pet2_idle | pet2_happy | pet2_sad |
| Stage3 | ぴょこおう | 25 | pet3_idle | pet3_happy | pet3_sad |


- requiredCareCount
- お世話(ごはん・あそぶ・アイテムをあげる)の合計の回数
- 0・10・25なので、10回お世話すると2段階目、25回で3段階目になります
お世話の回数を数えよう
PetStatus
お世話の回数を、セーブデータに入れます。
using System;
using System.Collections.Generic;
using UnityEngine;
// ペットの状態(おなか・きげん・コイン・持っているアイテム・お世話の回数)をまとめたデータ
[Serializable]
public class PetStatus
{
public const float Max = 100f;
[Range(0f, Max)] public float hunger = 80f; // おなか(0でペコペコ)
[Range(0f, Max)] public float mood = 80f; // きげん(0で最悪)
public int coins = 0;
public List<InventorySlot> items = new List<InventorySlot>(); // 持っているアイテム
public int careCount = 0; // お世話した回数(追加)
}
PetController
お世話とアイテムをあげたときに呼ばれるRejoiceで、回数を1増やします。
// ペットが喜ぶ(お世話したときと、アイテムをあげたとき)
private void Rejoice()
{
status.careCount++; // お世話の回数を数える(追加)
animator.SetTrigger(HappyHash);
statusView.Show(status);
}
OfflineProgress
読み込んだときに、お世話の回数も戻します。#7で足した持ち物の下に1行足すだけです。
// 閉じたときの状態に戻す
PetStatus status = pet.Status;
status.hunger = data.petStatus.hunger;
status.mood = data.petStatus.mood;
status.coins = data.petStatus.coins;
status.items = data.petStatus.items;
status.careCount = data.petStatus.careCount; // お世話の回数(追加)
進化させよう(EvolutionController)
お世話の回数から今の段階を決めて、ペットの絵を切り替えるスクリプトです。エンディングもここで出します。
- PetRaising/Scriptsに「EvolutionController」を作る
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
// お世話の回数でペットを進化させ、見た目を切り替える。最後まで育てたらエンディングを出す
public class EvolutionController : MonoBehaviour
{
[SerializeField] private PetController pet;
[SerializeField] private Image petImage;
[SerializeField] private Animator animator;
[SerializeField] private List<EvolutionData> stages = new List<EvolutionData>();
[SerializeField] private int careCountToEnding = 40; // この回数まで育てるとエンディング
[Header("進化のお知らせ")]
[SerializeField] private GameObject evolvePanel;
[SerializeField] private TMP_Text evolveText;
[Header("エンディング")]
[SerializeField] private GameObject endingPanel;
[SerializeField] private TMP_Text endingText;
private int currentStage;
private bool endingShown;
private void Start()
{
evolvePanel.SetActive(false);
endingPanel.SetActive(false);
// 始めたときは、お知らせを出さずに見た目だけ合わせる
currentStage = StageFor(pet.Status.careCount);
ApplyFace();
}
private void Update()
{
int stage = StageFor(pet.Status.careCount);
if (stage != currentStage)
{
currentStage = stage;
evolveText.text = $"{stages[currentStage].stageName}に\nしんかした!";
evolvePanel.SetActive(true);
}
ApplyFace();
CheckEnding();
}
// 今の状態に合わせて、ペットの絵を切り替える
private void ApplyFace()
{
EvolutionData stage = stages[currentStage];
if (animator.GetCurrentAnimatorStateInfo(0).IsName("Happy"))
{
petImage.sprite = stage.happySprite;
}
else if (animator.GetBool("Sad"))
{
petImage.sprite = stage.sadSprite;
}
else
{
petImage.sprite = stage.idleSprite;
}
}
// お世話の回数から、今の段階を決める
private int StageFor(int careCount)
{
int stage = 0;
for (int i = 0; i < stages.Count; i++)
{
if (careCount >= stages[i].requiredCareCount)
{
stage = i;
}
}
return stage;
}
private void CheckEnding()
{
if (endingShown)
{
return;
}
if (currentStage < stages.Count - 1 || pet.Status.careCount < careCountToEnding)
{
return;
}
endingShown = true;
endingText.text = $"{stages[currentStage].stageName}になるまで\nそだててくれてありがとう!";
endingPanel.SetActive(true);
}
// 進化のお知らせの OK ボタンの On Click に登録する
public void CloseEvolvePanel()
{
evolvePanel.SetActive(false);
}
// エンディングの「もういちど そだてる」ボタンの On Click に登録する
public void Restart()
{
SaveSystem.Delete();
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
- StageFor
- お世話の回数以下のrequiredCareCountを持つ段階のうち、一番後ろのものを返す
- 回数を直接比べるだけなので、進化した段階をセーブデータに持たなくてOK
- ApplyFace
- Animatorの状態を見て、今の段階の絵に切り替える
GetCurrentAnimatorStateInfo(0).IsName("Happy"):今Happyのアニメーションが再生されているかanimator.GetBool("Sad"):#3でPetControllerが設定したSadの値
- Startでは進化のお知らせを出さない
- 読み込んだ直後は、前回の続きなので「進化した!」は出さずに、見た目だけ合わせる
- Restart
- セーブデータを消して、今のシーンを読み込み直す(シーンの切り替えは8-3 スクリプトでシーンを切り替えよう)
- 読み込み直すと、最初の状態から始まります
お知らせとエンディングのパネルを作ろう
#5のおかえりパネルと同じ作り方です。2つ作ります。
- Canvasを右クリック>UI (Canvas)>Panel で「EvolvePanel」を作る
- HierarchyでShopPanelの下、WelcomePanelの上に置く
- ImageのColorを黒、Aを150ぐらいに
- 子に Image で「Window」(Pos Y:520、Width:800、Height:440、Source Image:UISprite、Image Type:Sliced)
- Windowの子に Text – TextMeshPro で「EvolveText」(stretch、Left・Right:40、Top:40、Bottom:180、Font Size:64、真ん中)
- Windowの子に Button – TextMeshPro で「OKButton」(bottom-center、Pos Y:100、360×120、テキスト「OK」)
- 同じように「EndingPanel」を作る
- テキストは「EndingText」、ボタンは「RestartButton」(テキスト「もういちど そだてる」、Font Size:44、520×120)
- EndingPanelは、HierarchyでEvolvePanelの下(WelcomePanelの上)に置く


スクリプトを付けよう
- HierarchyでGameManagerを選び、Add Component>EvolutionController
- 次のようにドラッグ&ドロップする
- Pet:Pet
- Pet Image:Pet(Petに付いているImage)
- Animator:Pet(Petに付いているAnimator)
- Stages:「+」を3回押して、Stage1・Stage2・Stage3を順番に入れる
- Care Count To Ending:40
- Evolve Panel:EvolvePanel、Evolve Text:EvolveText
- Ending Panel:EndingPanel、Ending Text:EndingText
- OKButton(EvolvePanelの中)のOn Click ()に、GameManagerのEvolutionController>CloseEvolvePanel ()を登録
- RestartButton(EndingPanelの中)のOn Click ()に、GameManagerのEvolutionController>Restart ()を登録


シーンをビルドに登録する
Restartでシーンを読み込み直すため、シーンをビルドの一覧に入れておきます。
- File>Build Profiles を開く
- Scene List に Main のシーンが入っていなければ、「Add Open Scenes」で追加する


動かして確認しよう
- 再生(▶)する
- 「ごはん」「あそぶ」を押してお世話を10回する
- お世話の回数は、PetのPet ControllerのStatus>Care Countで見られます
- 10回目で「ぴょこすけに しんかした!」のお知らせが出て、ペットの耳が伸びる
- OKを押して閉じ、さらにお世話を続ける
- 25回で「ぴょこおうに しんかした!」。王冠をかぶる
- 40回でエンディングが出る
- 「もういちど そだてる」を押すと、最初の状態(1段階目)から始まる
確認のときは、Care Countの数字をInspectorで直接変えると早いです(再生中に24にして、1回お世話すると進化します)。




スマホで遊べるようにしよう
最後に、Android向けにビルドしてスマホで遊べるようにします。iOSはMacとXcodeが必要なので、ここではAndroidで進めます(手順は10-4 プラットフォームの変更も見てください)。
準備
- Unity HubのInstallsで、使っているUnityに次のモジュールが入っているか確認する
- Android Build Support、OpenJDK、Android SDK & NDK Tools
- 入っていなければ、HubのAdd modulesから追加する
プレイヤーの設定
- Edit>Project Settings>Player を開く
- Company Name・Product Nameを決める(アプリの名前になります)
- Resolution and Presentationを開いて、画面の向きを縦に固定する
- Default Orientation:Portrait
- Other Settingsを開いて確認する
- Package Name:
com.会社名.petraisingのような形(ほかのアプリと重ならない名前にする) - Minimum API Level:そのままでOK
- Package Name:
- 名前を変えると、セーブデータの保存先も変わります
Application.persistentDataPathは「会社名/製品名」のフォルダなので、#6までに保存したデータは読み込まれなくなります- 消えたわけではなく、前の名前のフォルダに残っているだけです。配信するゲームでは、最初に名前を決めておきましょう


ビルドする
- File>Build Profiles を開く
- 左の一覧からAndroidを選び、「Switch Platform」を押す
- 画像の作り直しが走るので、数分かかることがあります
- Scene ListにMainが入っていることを確認
- 「Build」を押して、保存先とファイル名(PetRaising.apk)を決める


出来た.apkファイルをスマホに移してインストールすると、実機で遊べます。スマホで開いて、次のことを確認してみてください。
- 縦画面で、ゲージもボタンも切り欠きにかぶっていない(#1のSafe Area)
- ボタンを押すと音が鳴る
- ホームに戻ってしばらくしてから開き直すと、おなかが減っている(#5)



自分のスマホでペットが動いていると、感動もひとしおです・・・!



ここまで作れたら、もう立派なゲーム1本!おつかれさまでした!
シリーズのまとめ
全8回で、こんなものを作りました。
| 回 | 作ったもの | 覚えたこと |
|---|---|---|
| #1 | 縦画面のレイアウト | Canvas Scaler、アンカー、Safe Area |
| #2 | ペットの表示とアニメーション | Animation・Animator、Sprite |
| #3 | おなかときげんのゲージ | 時間で減るパラメータ、UIへの反映 |
| #4 | お世話のボタン | ボタンの処理、効果音とBGM |
| #5 | 閉じている間の時間 | DateTime、保存のタイミング |
| #6 | セーブデータ | JSON、ファイルへの保存 |
| #7 | ショップ | ScriptableObject、List、Scroll View |
| #8 | 進化とエンディング、ビルド | データで見た目を切り替える、Androidビルド |
ここから先は、自分なりに遊びを足してみてください。
- お世話のバリエーションを増やす(おふろ、おさんぽ)
- 進化の分岐(おなか重視なら食いしん坊タイプ、きげん重視なら元気タイプ)
- 図鑑や実績、BGMの切り替え
次のシリーズは、ヴァンサバ風のサバイバーゲームを作る予定です。今度は動きのあるアクションゲームで、敵がどんどん出てくるタイプ。またよろしくお願いします!
コメント