Unity×AI開発講座【第7回】
『Gemini & ChatGPT × Unity』で本格カフェ経営シミュレーションを作る!
エリアマップ画面での競合分析と、職種別スタッフの時給・シフト・人件費予測システムを構築しよう!
「店内のレイアウトや接客だけでなく、街全体の市場シェア争いやライバル店舗の競合分析、リアルなスタッフのシフト管理も作り込みたい!」
本格派シミュレーションゲームに不可欠なのが、店舗内(ミクロ視点)と街全体(マクロ視点)を行き来する経営管理機能です。ライバル店の弱点(接客スピード・価格・内装)を分析して新店舗を出店するエリアマップと、バリスタ・ウェイター・クリーナーの時給調整やシフト管理、人件費予測グラフを連動させるシステムを構築します。
第7回となる本記事では、エリアマップ画面(市場シェア・競合ピン)、ライバル店弱点分析ロジック、スタッフ能力値&シフトグリッドUI、月間人件費(¥1,250,000/月)の動的予測計算までをAIプロンプトを活用して完全実装します!
目次
1. はじめに(第7回で実装するエリアマップ&人件費管理システム)
カフェ経営を大きく飛躍させるには、単にコーヒーを淹れて売るだけでなく、周囲のライバル店舗の動向(競合分析)を把握し、スタッフの人件費コストを最適化する組織マネジメントが不可欠です。
1店舗のみの単調構造(拡張性なし)
店舗内の操作だけで完結してしまい、事業拡大の達成感や、時給・人件費の調整による経営的な駆け引きが生まれない。
エリアマップ × 人件費予測(本講座の方式)
マップ上でライバルの弱点を突き市場シェア(%)を獲得。能力の異なる職種(バリスタ等)の時給とシフトを割り当て月間人件費を最適化。
本章では、街全体の競合ピンと市場シェアを可視化するエリアマップ管理クラスと、スタッフの職種別能力・時給・人件費予測グラフを紐付けるマネージャーを完成させます。
2. Step 1: エリアマップ(マクロ経営)画面と競合分析ロジックの設計
街を見下ろすエリアマップ上に自店舗(緑ピン)とライバル店(赤ピン)、出店可能地($緑枠)を配置し、タップで詳細パネル(市場シェア・弱点分析)を開くロジックを設計します。
エリアマップ・競合分析パラメータ構造
| 要素名 | データ定義 | 競合分析における役割 |
|---|---|---|
| 1. 市場シェア(Market Share) | float(自店舗:35%) | エリア全体の客数のうち、自店舗を選んで来店する割合。評価(★)が高いほど拡大。 |
| 2. 弱点分析(Weakness Analysis) ★最重要 | Enum (SlowService / HighPrice / DatedInterior) | ライバル店の弱点(接客スピードが遅い、メニュー価格が高い等)を表示し、自店の対抗策を促す。 |
| 3. 新店舗出店(Expansion) | int(出店コスト:¥50,000) | 資金を支払って出店可能地に新店舗を開設し、市場シェアを奪取する機能。 |
初心者補足:マクロ経営(Macro Management)とは?
店内の個別の注文や清掃ではなく、街全体での市場シェア、ライバル店との価格競争、店舗展開など、経営全体を俯瞰した広域な戦略決定を行う視点のことです。
\ エリアマップ&競合分析コードをAIに自動生成させよう! /
3. Step 2: AIプロンプトによる「AreaMapManager.cs」スクリプトの自動生成
競合店舗の弱点・市場シェア率・評価(★)を管理し、マップ画面と店内画面のシーン切り替え(カメラ移動)を行う `AreaMapManager.cs` を生成させます。
コピペで使える!競合分析・エリアマップ生成プロンプト
Unity 2022.3 (C#) で動作する「AreaMapManager.cs」を作成してください。
【要件】
1. ライバル店データ構造 `RivalStoreData`:
- storeName (string), rating (float), marketShare (float)
- weaknessList (List) : 「接客スピードが遅い」「メニュー価格が高い」「内装が古い」
2. エリア全体の市場シェア計算:
- 自店舗評価(GameManager.Instance.currentRating)とライバル店評価の比率から自店舗市場シェア(%)を算出。
3. 出店可能地(Expansion Area)判定:
- 資金¥50,000を支払い新店舗を開設する関数 `TryExpandNewStore()` の作成。
4. UIイベント通知:
- System.Action OnAreaMapUpdated; // (自店シェア, 選択中ライバルデータ)
生成された C# スクリプト:AreaMapManager.cs
using System;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class RivalStoreData
{
public string storeName = "ライバル店 B";
public float rating = 3.8f;
public float marketShare = 25f;
public List weaknessList = new List { "接客スピードが遅い", "メニュー価格が高い", "内装が古い" };
}
public class AreaMapManager : MonoBehaviour
{
[SerializeField] private RivalStoreData rivalStoreB;
[SerializeField] private int expansionCost = 50000;
public float playerMarketShare { get; private set; } = 35f;
public event Action OnAreaMapUpdated;
private void Start()
{
CalculateMarketShare();
}
public void CalculateMarketShare()
{
float playerRating = GameManager.Instance != null ? GameManager.Instance.currentRating : 4.8f;
float totalScore = playerRating + rivalStoreB.rating + 3.0f; // 他競合補正
playerMarketShare = Mathf.Round((playerRating / totalScore) * 100f);
OnAreaMapUpdated?.Invoke(playerMarketShare, rivalStoreB);
}
public bool TryExpandNewStore()
{
if (GameManager.Instance != null && GameManager.Instance.currentMoney >= expansionCost)
{
GameManager.Instance.AddMoney(-expansionCost);
playerMarketShare += 15f; // 新店舗追加でシェア大幅拡大
OnAreaMapUpdated?.Invoke(playerMarketShare, rivalStoreB);
Debug.Log($"新店舗を出店しました!(出店コスト: ¥{expansionCost:N0})");
return true;
}
Debug.LogWarning("出店資金が不足しています!");
return false;
}
}
4. Step 3: スタッフ雇用・時給調整・シフト割り当て(StaffManager.cs)の実装
職種(BARISTA / WAITER / CLEANER)ごとに能力値(接客スピード・調理精度・忍耐力)を割り当て、時給調整スライダーと曜日・時間帯別シフトチェッカーUIを連動させます。
① BARISTA(バリスタ)
調理精度(5/5)が高い。ドリンク提供のクオリティを高め客満足度を向上。
② WAITER(ウェイター)
接客スピード(5/5)が最速。混雑時のレジ・配膳待ち時間を激減させる。
③ CLEANER(クリーナー)
忍耐力(5/5)が優秀。汚れたテーブルの清掃と空き席確保を素早くこなす。
StaffManager.cs スクリプト
using System;
using System.Collections.Generic;
using UnityEngine;
public enum StaffRole
{
Barista,
Waiter,
Cleaner
}
[Serializable]
public class StaffMember
{
public string staffName;
public StaffRole role;
public int serviceSpeed = 3; // 接客スピード 1-5
public int cookingAccuracy = 3; // 調理精度 1-5
public int stamina = 3; // 忍耐力 1-5
public int hourlyWage = 1100; // 時給 (¥1,100/時)
// 曜日・時間帯別シフト (7日 × 3時間帯[10-15時, 15-20時, 20-24時])
public bool[,] shiftSchedule = new bool[7, 3];
}
public class StaffManager : MonoBehaviour
{
public List staffList = new List();
public event Action OnStaffDataChanged;
private void Awake()
{
InitializeDefaultStaff();
}
private void InitializeDefaultStaff()
{
staffList.Add(new StaffMember { staffName = "バリスタ A", role = StaffRole.Barista, cookingAccuracy = 5, hourlyWage = 1100 });
staffList.Add(new StaffMember { staffName = "ウェイター B", role = StaffRole.Waiter, serviceSpeed = 5, hourlyWage = 1100 });
staffList.Add(new StaffMember { staffName = "クリーナー C", role = StaffRole.Cleaner, stamina = 5, hourlyWage = 1100 });
}
public void UpdateHourlyWage(int staffIndex, int newWage)
{
if (staffIndex >= 0 && staffIndex < staffList.Count)
{
staffList[staffIndex].hourlyWage = newWage;
OnStaffDataChanged?.Invoke();
}
}
public void ToggleShift(int staffIndex, int dayOfWeek, int timeSlot, bool isOn)
{
if (staffIndex >= 0 && staffIndex < staffList.Count)
{
staffList[staffIndex].shiftSchedule[dayOfWeek, timeSlot] = isOn;
OnStaffDataChanged?.Invoke();
}
}
}
\ 月間人件費を自動シミュレーションしよう! /
5. Step 4: 人件費予測(月額コスト)の動的算出とUIグラフ描画
スタッフに割り当てたシフトコマ数(1コマ=4〜5時間)と設定時給を掛け合わせ、月間予測人件費(合計人件費:¥1,250,000/月)を動的計算し、UI上の推移グラフを更新します。
人件費予測(Payroll Calculation)の数式と更新手順
`週間人件費 = ∑ (シフト入りコマ数 × 5時間 × 時給)` を各スタッフごとに計算し、4.3週(1ヶ月分)を掛けて月額予測を出します。
算出された月額人件費(¥1,250,000/月)を `TMP_Text` に表示し、緑色の折れ線・バーグラフの `fillAmount` を更新します。
PayrollUIController.cs スクリプト
using UnityEngine;
using TMPro;
public class PayrollUIController : MonoBehaviour
{
[SerializeField] private StaffManager staffManager;
[SerializeField] private TMP_Text totalPayrollText;
private void OnEnable()
{
if (staffManager != null) staffManager.OnStaffDataChanged += RecalculatePayroll;
}
private void OnDisable()
{
if (staffManager != null) staffManager.OnStaffDataChanged -= RecalculatePayroll;
}
public void RecalculatePayroll()
{
int weeklyTotal = 0;
foreach (var staff in staffManager.staffList)
{
int assignedSlots = 0;
for (int day = 0; day < 7; day++)
{
for (int slot = 0; slot < 3; slot++)
{
if (staff.shiftSchedule[day, slot]) assignedSlots++;
}
}
// 1コマ=5時間換算
weeklyTotal += assignedSlots * 5 * staff.hourlyWage;
}
// 月額(約4.3週分)換算
int monthlyTotal = Mathf.RoundToInt(weeklyTotal * 4.33f);
if (totalPayrollText != null)
{
totalPayrollText.text = $"合計人件費: ¥{monthlyTotal:N0}/月";
}
Debug.Log($"[人件費予測] 月額合計: ¥{monthlyTotal:N0}");
}
}
6. まとめ & よくある質問 (FAQ)
お疲れ様でした!第7回では、経営シミュレーションの奥深さを決定づける「エリアマップ競合分析」「新店舗出店」「職種別スタッフ管理」「人件費予測システム」を完成させました!
次回:最終回 第8回「最適化・デバッグ・ビルド(ゲーム完成!)」へ!
オブジェクトプールによる客AI(50体以上)軽量化、AIでのデバッグ手法、ゲームのWebGL/PC書き出し手順を解説します!
よくある質問 (FAQ)
Q. シフトのトグルUIをC#から大量に生成・アサインするのはどう行えば効率的ですか?
7日×3時間帯=21個のToggle Prefabを `Instantiate` し、生成ループ内で `int day = i / 3; int slot = i % 3;` のローカル変数を保持させた `onValueChanged.AddListener` をバインドするのが最もスマートです。
Q. エリアマップと店内シーンを切り替える際、時間が進んでしまいませんか?
エリアマップ表示中(マクロ画面)は `GameManager.Instance.isStoreOpen = false;` またはタイムスケールを調整して時間進行を一時停止させる設計がおすすめです。