Unityで放置アプリを作ってみた(後編)

2026.03.19

こんにちは、エンジニアのやまじです。
前編の記事から長らく時間が開いてしまいました、申し訳ありません…。
今回は前回予告していた通り、放置アプリの動作についてソースコードと動作している動画を交えて解説していきます。

👉前編はこちらからご覧になれます。


放置アプリの大まかな解説

「状態取得 → 植木鉢にタネを植える → 成長 → 収穫 → 最初に戻る」という一連の流れを行います。
最後まで成長して育った果物を収穫することで、DB上の合計スコアを増やしていくという処理も実装しています。
収穫のたびにサーバー側のDBにスコアが蓄積されていくため、別のブラウザや端末からアクセスしてもデータが保持されたり、将来的にランキング機能を実装したりといった拡張も可能です。
ただ放置するだけでなく、自分のスコアが積み上がっていくことで、シンプルながらもちょっとした達成感が感じられるアプリを目指しています。

放置アプリを構成する5つのステップ

状態取得(GetState)

アプリ起動時、サーバーへ植木鉢の状態は現在どうなっているか確認します。

●ここでやっていること

Unity:GetState を実行し、サーバーへ現在の保存データ確認のためのリクエストを送信。
PHP:getState 関数が実行され、DBから現在の plant_state(植木鉢の状態)や planted_at(時刻)を取得して返す。

// GameAPI.cs(Unity側)
public IEnumerator GetState(string userId)
{
    string url = ApiBaseUrl + "/game/getState";
    GetStateRequest requestData = new GetStateRequest { userId = userId };
    string json = JsonUtility.ToJson(requestData);
    yield return PostRequest(url, json, HandleResponse);
}
// api.php(サーバー側)
function getState($data) {
    $userId = $data['userId'] ?? '';
    $conn = getDbConnection();
    
    // ユーザーデータの存在確認・初期化
    // ...中略...

    // 最新のゲーム状態(成長度や残り時間)を取得して返却
    $gameState = getGameStateByUserId($conn, $userId);
    sendSuccessResponse($gameState);
    $conn->close();
}

タネを植えて放置スタート

植木鉢に何も植えられていない状態で「タネを植える」ボタンを押すことで、放置アプリがスタートします。

●ここでやっていること

Unity:Plant を実行し、サーバー側にタネを植えて成長を開始するためのリクエストを送信。
PHP:plant 関数が実行され、サーバー側の現在時刻を planted_at としてDBに記録。植木鉢の状態(ステータス)を「タネの状態」に設定。

// GameAPI.cs(Unity側)
private IEnumerator Plant()
{
    string url = ApiBaseUrl + "/game/plant";
    ApiRequest requestData = new ApiRequest { userId = _currentUserId };
    string json = JsonUtility.ToJson(requestData);
    yield return PostRequest(url, json, HandleResponse);
}
// api.php(サーバー側)
function plant($data) {
    $userId = $data['userId'] ?? 0;
    $conn = getDbConnection();
    $now = date('Y-m-d H:i:s');
    
    // ステータスを1(タネ状態)にし、現在の時刻をタネを植えた時間として保存
    $stmt = $conn->prepare("UPDATE game_states SET plant_state = 1, planted_at = ? WHERE user_id = ?");
    $stmt->bind_param("si", $now, $userId);
    $stmt->execute();
    // ...
}

成長判定とグラフィックの変更

本アプリの核心部分です。アプリを閉じていても、サーバー側の時刻計算によって自動で成長が進みます。また、「様子を見る」ボタンを押すことで、画面上の残り時間が更新されます。

●ここでやっていること

Unity:updateGrowthState 内で「現在時刻 - 植えた時刻」から経過秒数を算出し、成長段階を判定・更新。
PHP:サーバーから届いた currentState に合わせ、switch 文で対応するスプライト(画像)に切り替え。

// GameAPI.cs(Unity側)
private void UpdateUI(GameStateResponse state)
{
    int currentState = (state.plant != null) ? state.plant.currentState : 0;
    Sprite targetSprite = sprite_Empty;

    // ステータス番号に対応するスプライトをセット
    switch (currentState)
    {
        case 1: targetSprite = sprite_Growth1; break; // 最初の芽
        case 2: targetSprite = sprite_Growth2; break; // 少し成長
        case 3: targetSprite = sprite_Growth3; break; // 花
        case 4: targetSprite = sprite_HarvestReady; break; // 収穫可能
    }
    plantRenderer.sprite = targetSprite; // スプライトを差し替え
}
// api.php (サーバー側)
$elapsedSeconds = $now->getTimestamp() - $plantedTime->getTimestamp();

foreach ($growth_times as $stage => $requiredTime) {
    if ($elapsedSeconds >= $requiredTime) {
        $newState = $stage + 1; // 経過時間が設定した数値を超えていれば植木鉢を次の段階へ
    }
}

収穫とスコアの記録

最後まで成長すると、植木鉢に生えていた植物は果物に変化。クリックすることで収穫できます。

●ここでやっていること

Unity:実った果実をクリックすることで HarvestPlant を実行。サーバーへ収穫のリクエストを送信。
PHP:harvest 関数内で現在の成長状態を最終チェック。クリックされたらDB上のフルーツ所持数をカウントアップ。

// GameAPI.cs(Unity側)
public void HarvestPlant() { StartCoroutine(Harvest()); }

private IEnumerator Harvest()
{
    string url = ApiBaseUrl + "/game/harvest";
    // ユーザーIDを含めたリクエストを作成
    ApiRequest requestData = new ApiRequest { userId = _currentUserId };
    string json = JsonUtility.ToJson(requestData);
    // サーバーへ収穫リクエストをPOST送信
    yield return PostRequest(url, json, HandleResponse);
}
// api.php(サーバー側)
function harvest($data) {
    // ...中略...
    // 成長状態を更新し、ステージ5(収穫可能)か判定
    updateGrowthState($conn, $userId);
    if ($currentState == 5) {
        // フルーツを+1加算し、栽培データ(状態と時刻)をリセット
        $stmt = $conn->prepare("UPDATE game_states SET plant_state = NULL, planted_at = NULL, fruits = fruits + 1 WHERE user_id = ?");
        $stmt->bind_param("i", $userId);
        $stmt->execute();
    }
}

最初の状態に戻る(リセット)

収穫が完了すると、植木鉢は自動で栽培前の状態へ戻り、再び遊べるようになります。

●ここでやっていること

PHP:収穫処理と同時に、DB上の plant_state と planted_at を NULL(空)に書き換えることで植木鉢の状態をリセット。
Unity:リセットされたデータ(plantnull)を受け取り、UIを「タネを植える」ボタンが表示される初期状態へ戻す。

// api.php (サーバー側)
// ステータスと時刻をNULLに更新して、鉢を空の状態にする
$stmt = $conn->prepare("UPDATE game_states SET plant_state = NULL, planted_at = NULL, fruits = fruits + 1 WHERE user_id = ?");
// GameAPI.cs (Unity側)
private void UpdateUI(GameStateResponse state)
{
    // plantデータがNULL(またはcurrentStateが0)なら未植栽と判断
    int currentState = (state.plant != null) ? state.plant.currentState : 0;

    // 最新のフルーツ数を反映
    fruitCountText.text = "これまで獲得したフルーツ: " + (state.inventory?.fruits.ToString() ?? "0");

    // 状態が0なら「タネを植える」ボタンを再表示
    plantButton.gameObject.SetActive(currentState == 0);
    harvestButton.gameObject.SetActive(currentState == 4);
}

おわりに

3ヶ月越しの完結となりましたが、いかがでしたでしょうか。 時刻管理をサーバーに任せることで、アプリを閉じていても正確に時間が進む放置ゲームの基礎を構築できました。
「サーバーで時間を管理する」という手法は、放置ゲームだけでなく、スタミナ回復やログインボーナスなど、多くのオンライン要素が絡む技術でもあり、昨今のアプリ制作には欠かせない仕組みとなっています。

今後の課題としては、以下のような機能拡張を考えています。

  • アイテムのバリエーションの追加: タネや果物の種類を増やす。
  • 残り時間のリアルタイム表示: Unity側でサーバーとの差分を毎フレーム更新し、より滑らかなカウントダウンを実装。
  • ユーザー登録機能を正式に実装し、複数ユーザーがそれぞれのデータで独立して遊べるよう改良する。

それでは。


🏢 株式会社ハジメクリエイトについて

この記事は、 株式会社ハジメクリエイト のエンジニアが執筆しました。


💻 Webシステム開発のプロフェッショナル

私たちは、ビジネスの成長をサポートするため、 PHPを用いたオーダーメイドのシステム開発 を提供しています。
お客様一人ひとりのニーズに応じたカスタムシステムを、 企画から開発・運用まで一貫してサポート
さらに、 React Nativeを活用したiOS/Android対応のアプリ開発 も得意としています。

単に「作る」だけでなく、
課題の本質に向き合い、最適な解決策を提案する のがハジメクリエイトのスタイルです。


🧑‍💻 一緒に働く仲間を探しています!

株式会社ハジメクリエイトでは、 自ら考え行動できるエンジニア を募集しています。
「私はこれがしたい!」という想いを持つあなた、一緒にモノづくりを楽しみませんか?

  • 技術で人の役に立ちたい
  • 意見が通る小さなチームで働きたい
  • フロントエンドもバックエンドも、いろいろ挑戦してみたい
  • お客さんと一緒にプロジェクトを育てたい

そんな気持ちがある方なら、きっと居心地のいい環境だと思います。
正社員はもちろん、パートタイムでの参加も歓迎中! 柔軟な関わり方で、あなたらしく働いてください。

👉 採用情報を見る
👉 お問い合わせはこちら


ちょっとでも「この会社、気になるな」と思ったら、ぜひお気軽にご連絡ください📩
最後まで読んでいただきありがとうございました!

  • Web技術

この記事を書いた人

やまじ

Engineer やまじ

2024年8月に入社したエンジニアです。日々の勉強を通して学んだこと・知ったことを本ブログでも投稿していきたいと思います。よろしくお願いします。

やまじの書いた記事一覧へ

ハジメクリエイトでは一緒に働く仲間を募集しています!

関連記事