Macを買わずに Windows + クラウドMac だけで iOS パズルゲームを個人リリースした話
「iOSアプリを出したいけどMacがない」問題を、Mac本体を買わずに突破した記録です。
この度、新作パズルゲーム 『tube-2048-数字を重ねるマージパズル』 を、紆余曲折ありながらも無事に App Store へリリースできました。🎉
📱 ストアリンク: https://apps.apple.com/us/app/tube-2048-数字を重ねるマージパズル/id6761907896
本作は『2048』の数字をマージしていく快感と、『ハノイの塔』のようなスタッキング(積み上げ)ロジックを融合させたパズルゲームです。
「Windowsしか持ってない個人開発者がiOSアプリをリリースする」という、地味に最大の物理的障壁をどう乗り越えたか、AI駆動開発(Antigravity)をどこまで使えたか、AdMobで何にハマったかを、実数値ベースでまとめます。
🎯 TL;DR(結論先出し)
時間がない人向けの結論です。
- ✅ Windows + MacinCloud(時間プリペイド)だけでiOSアプリは出せる。Mac本体は買わなくていい
- ⚠️ ただし MacinCloud は トータル15時間 消費、ストア申請は3回リジェクト された
- 🐛 クラウドMacでは実機エラー調査が面倒で、結局TestFlight配信+画面オーバーレイのログ表示で実機デバッグする力技に
- 🔁 App Store Connect でアプリ名・キーワード・説明文を変更するには毎回バージョンを上げて新しいビルドを提出する必要があり、ASOチューニングのたびにクラウドMac接続が発生して地味に効く
- 🤖 Antigravity(AI駆動開発)で実装の大半を生成できたが、設計力とアーキテクチャの目利きは人間側に必要
- 💸 AdMob は SDK 入れるだけでは終わらない。ストア連携ラグ・eCPM低下・広告リトライ設計の3点で詰む
- 🎨 デザインは「機能美」より「情報を引き算する勇気」が一番難しかった
- 📱 実機テストはエディタと挙動が違う。UIタップ判定とバイブ強度はビルド前提で詰めるべき
以下、ハマった度合いの大きい順に、「何が起きたか / なぜハマったか / どう解決した(あるいは凌いだ)か / 今ならこうする」 で書いていきます。
🥇 第1位:Windows から iOS ビルド & ストア申請の壁
圧倒的1位はこれです。「Windowsユーザーが iOS アプリをリリースする」 という最大の物理的障壁。
何が起きたか
- 手元に Mac がない状態でスタート
- ストア申請は 3回連続リジェクト
- MacinCloud のセッション時間を トータル約15時間 消費
なぜハマったか
iOS アプリのビルドと提出には Mac(正確には macOS 上の Xcode)が必須です。Mac mini を買えば数万円〜ですが、「個人開発で本当に売れるか分からないアプリのために本体を買う」のは投資判断としてしんどい。
そこでクラウドMac サービス MacinCloud の Pay-as-You-Go プラン(時間ベースのプリペイド)を契約しました。月額の固定プランではなく、「使った時間ぶんだけ消費する最小構成」 を選択。「とりあえずビルドと提出だけクラウドMacで済ませて、それ以外は Windows 側で完結させる」前提です。
どう解決したか
1. 魔の3回リジェクト、それぞれの原因
| 回 | リジェクト理由 | 対応 |
|---|---|---|
| 1回目 | バージョン情報の不一致: Unity 側と App Store Connect 側のバージョン番号が完全一致していないと弾かれる | Unity の Player Settings と Xcode の Info.plist、App Store Connect の3箇所を全部揃える |
| 2回目 | アイコンの仕様: ストア表示用とホーム画面用で扱いが異なる | ストア用はApp Store Connect、ホーム用はunityで設定 |
| 3回目 | プライバシー設定と各種申告漏れ: ATT(App Tracking Transparency)同意フローと、SDK が収集するデータの種類の申告 | App Store Connect の「App プライバシー」項目を AdMob/Unity Ads/LevelPlay すべて分で埋める |
2. CocoaPods の罠
Xcode でプロジェクトを開く前に、Mac のターミナルで pod install が必須です。これを忘れて Xcode を開くと、ビルド時に意味不明なエラーが出ます。
# ビルドしたフォルダへ移動
cd /path/to/your/folder
# ライブラリをインストール(これを忘れるとエラーになります)
pod install
3. エラー調査ログの取得が地味にしんどい
リジェクト対応や実機クラッシュの調査で何度もハマったのが、「実機で起きたエラーをどうやって自分の目で見るか」 の問題です。
ローカルMacなら、実機を USB ケーブルで繋いで Xcode の Devices and Simulators からデバイスログをリアルタイムで見られるのですが、MacinCloud にはそもそも自分の実機を物理的に繋ぐ手段がない(リモートデスクトップ越しの仮想Macなので、USB パススルーは使えない)。
そこで取った方法が 「TestFlight ビルドで配布して、実機画面上にログをオーバーレイ表示させる」 という力技でした。
具体的には:
- Unity 側に「画面端に最近のログを N 行表示する On-Screen Console」を実装
- リリース版でも debug ビルド扱いでログ表示を ON にした版をひとつ用意
- それを TestFlight で自分の iPhone に配布
- 実機でプレイしながら、画面に出るログを目視 or スクショで確認
- バグを直す → Unity でリビルド → MacinCloud で Archive → TestFlight に再アップロード
このサイクルがエラー1個追うのに TestFlight 配信反映の数十分待ち + 再ビルドの5〜10分 で、MacinCloud 接続時間を合計1〜2時間溶かしました。
次回はこうしたい: Xcode Cloud か GitHub Actions の macOS ランナーでビルドだけ自動化し、TestFlight 配信を CI 経由で回せれば、MacinCloud にログイン → リビルド → アップロードの手作業が激減するはず。あとは画面オーバーレイのログを Firebase Crashlytics などのリモートログ収集に置き換えれば「実機画面とにらめっこ」自体が不要になる。
4. App Store Connect で「バージョンを上げないと変更できない項目」が地味に多い
これも事前にイメージしてなかった落とし穴です。App Store Connect 上の項目は、ざっくり3階層に分かれています:
| 階層 | 例 | 変更タイミング |
|---|---|---|
| (A) いつでも変更OK(審査不要) | プロモーション用テキスト / プライバシーポリシーURL / サポートURL / 価格 | 保存即反映 |
| (B) 新しいバージョンを作って審査に出さないと変更できない | アプリ名 / サブタイトル / キーワード / 説明文 / スクショ / アイコン画像 / カテゴリ / 年齢制限 | バージョン番号を上げて新バイナリを提出する必要あり |
| (C) ↑に加えて Unity 側のリビルドが必須 | Bundle ID / Info.plist の権限文言 / ATT 同意フローの追加・修正 |
Unity でリビルド → クラウドMacで Archive → アップロード |
特にハマったのが (B)の罠。「アプリ名やキーワードを直したいだけ」なのに、新しいバージョンを作って新しいビルドをアップロードして審査に出さないと変更が反映されない、という仕様です(プロモーション用テキストだけが例外的にいつでも編集できる)。
つまり ASO で「キーワードちょっと変えてみよう」「説明文の冒頭3行を試したい」と思うたびに:
- Unity でビルド番号だけ上げて iOS ビルド
- Xcode プロジェクトを MacinCloud にアップロード
- クラウドMacにログイン →
pod install→ Archive → App Store Connect にアップロード - App Store Connect で新バージョンを作成し、修正したメタデータと一緒に提出
- 審査を待つ(通常24時間前後)
このフルコースが必須になります。コードは1行も変えてないのに、毎回クラウドMacへの接続・Archive・アップロードが発生するのが地味につらい。
そして審査に出す以上、提出前後の動作確認もクラウドMacで済ませたくなる場面が出てきます。1サイクルあたり 20〜30分の MacinCloud 接続が固定で乗ってくるので、ASOで PDCA を回そうとすると平気で半日溶かします。
4-1. 対策:バージョン更新を「1回にまとめる」運用に切り替える
- (A)プロモーション用テキスト等はこまめに更新:審査不要なので、アップデート告知やイベントに使う前提でフル活用
- (B)アプリ名・キーワード・説明文・スクショ等の変更は、必ず一括で出す:キーワード調整・説明文の改善・スクショ差し替え・アイコン更新を「1回のバージョン提出に全部のせる」運用にする
- (C)リビルド必須項目もここで一緒に確定させ、リジェクト時の修正回数を最小化
特に(B)を細切れにやってしまうと、変更内容自体は軽くても「新バージョン作成 → ビルド番号上げて再ビルド → クラウドMac起動 → アップロード → 審査待ち」というフローが何度も発生します。「直したいことを1〜2週間貯めてから一括で出す」 だけで、クラウドMac接続回数も審査待ち時間も劇的に減ります。
ASOチューニングは「1ヶ月単位の PDCA」で回すぐらいの意識でちょうどいい、というのが今回の学びでした。
今ならこうする(次の自分への手紙)
- MacinCloud は Pay-as-You-Go(時間プリペイド)から始めて十分。月数回しか触らない個人開発なら月額固定プランより割安。ただし1日のログイン時間は時間単位で切り上げ課金される仕様なので、細切れ接続は損
- アイコンと バージョン番号、プライバシー申告の3点だけは提出前にチェックリスト化しておく(これだけでリジェクト回数は1回に減らせたはず)
-
pod installを Unity のビルド後処理(PostProcessBuild)で自動化しておくと、MacinCloud 接続時間を半分以下に圧縮できる - 画面オーバーレイのログ表示で実機デバッグするのは初動には有効だが、TestFlight配信の反映待ちが毎回効いてくる。Firebase Crashlytics などのリモートログ収集を最初から組み込んでおけば、TestFlight に上げ直さなくてもクラッシュやエラーが手元の Web 管理画面で確認できる
- Xcode Cloud or GitHub Actions の macOS ランナーでビルド+TestFlight 配信を自動化しておけば、MacinCloud 接続は「リジェクト時の最終確認」だけで済む
- App Store Connect の変更は「1ヶ月単位でまとめて出す」運用に最初から決めておく。アプリ名・キーワード・説明文・スクショは細切れに直さず、メモに溜めて月1で一括提出するとクラウドMac接続回数が劇的に減る
- 月3回以上ビルドするなら 中古 Mac mini を買った方が長期的には安い(後悔ポイント)
🥈 第2位:AdMob 実装と広告最適化の沼
アプリの収益化のために Google AdMob を導入しましたが、SDK を入れるだけでは終わらないのが広告周りの辛いところです。
何が起きたか
| つまずいたポイント | 内容と対策 |
|---|---|
| ストア連携のラグ | アプリリリース直後は AdMob 側でアプリを検出できず、実測で約2〜3日 の紐付け待ち時間が発生 |
| eCPM の低下回避 | App Store の「マーケティングURL」にデベロッパーサイトを正しく記載しないと、広告単価が下がる |
| 広告リトライの設計 | ロード失敗時の即時リトライは BAN 対象。指数バックオフ(待機時間を段階的に延ばす)で安全な設計に |
なぜハマったか
「SDK 入れて広告ユニット ID 設定すれば終わり」と思っていたのが間違い。広告周りは アプリ起動時のロードフロー / 失敗時のフォールバック / 同意フロー(GDPR・ATT) の3階層を全部設計しないと、表示率が出ない・BANされる・eCPMが下がる、の三重苦になります。
どう凌いでいるか(現状)
正直に言うと、現状は AdMob 単独運用で凌いでいます。
- 同意フロー(GDPR・ATT) だけは初期から実装(これがないとそもそも広告が出ない国/環境がある)
- 広告リトライは最低限の実装にとどめて、即時リトライによる BAN だけは回避
- マーケティングURL はリリース後に気付いて修正済み
ストア連携ラグは「待つしかない」ので 2〜3日待って解決、eCPM の低下は当面飲み込み、フォールバック設計は後回しにしている状態です。
次回からこうする(やる予定)
ここからやるべきこととして、3段階のウォーターフォールを構築する予定です:
LevelPlay(メディエーション)
↓ ロード失敗
Unity Ads(セカンダリ)
↓ ロード失敗
AdMob(最終フォールバック)
LevelPlay をフロントに置くことで、複数広告ネットワークを束ねて入札させ、eCPM を底上げできるはず。Unity Ads と AdMob は単独だと表示率に波があるので、ウォーターフォールを組まないと収益効率が頭打ちになる、というのが現状の実感です。
個人開発で広告は「最初から最適に組む」のは現実的に無理で、まずは AdMob 単独でリリース → DLが伸びて広告表示数が増えてから収益効率の改善に手を入れる、という順番でいいと思っています。逆に DL が出てない段階でフォールバック設計を作り込んでも、表示数自体が少なくて改善効果が見えません。
今ならこうする(申請時の最低限)
- 広告ロードは「アプリ起動 → 5秒後」に開始(起動直後はネットワーク不安定でロード失敗率が高い)
- リトライは指数バックオフ必須(初回1秒、次2秒、次4秒...上限60秒)
- App Store 申請の「マーケティングURL」は最初から正しく入れる。後から変えるとeCPMの再評価に時間がかかる
- テスト広告 ID と本番 ID を Unity の Define Symbol で切り替えておかないと、デバッグ中に本番広告で BAN リスクがある
🥉 第3位:AI駆動開発の光と影(Antigravity と MCPサーバー)
今回は 「Vibe Coding」 を意識し、AI駆動開発ツール Antigravity を利用してプロンプトベースでスクリプトを記述する手法にチャレンジしました。
何が起きたか
- ✅ コード生成: 全実装の体感8割を AI が出力
- ⚠️ 設計の一貫性は人間が維持する必要があった
- ❌ MCP サーバー連携は活用しきれず、Unity 内のオブジェクト配置は結局手作業
なぜハマったか
1. スパゲッティ化の予兆
変更を繰り返すうちに、可読性や保守性を完璧に担保するのが難しくなりました。AIは「動くコード」は出してくれますが、プロジェクト全体の責務分離(MVCの境界線など)を勝手には守ってくれないので、人間側のレビューが甘いとファイルがどんどん肥大化します。
実際、本作の中核 TubeUI.cs は途中から partial 分割しました:
TubeUI.cs(本体)
├── TubeUI_Input.cs(入力処理)
├── TubeUI_Rendering.cs(描画)
├── TubeUI_Effects.cs(演出)
├── TubeUI_Segments.cs(ゲージ)
└── TubeUI_Theme.cs(テーマ切替)
partial で分けたことで AI も該当ファイルだけをコンテキストに入れて編集できるようになり、生成精度が上がりました。
2. MCPサーバーの活用不足
オブジェクトの配置などは結局、Unity エディタでの手作業(ポトペタ)で行うことに。MCP 経由で Unity のシーン操作を AI に任せられれば理論上は配置も自動化できますが、今回はその設定に時間を割けず、断念しました。
どう解決したか / 今ならこうする
-
MVC を最初から強制する: Model(
TubeGame.csUnity 非依存)、View(TubeUI.cs)、Controller(TubeUIController.cs)に分け、AI に「Modelには Unity の型を一切使うな」と明示プロンプトで縛る - partial 分割を最初から設計: 1ファイル500行を超えそうになったら即分割
- MCP は次回必ずフル活用する。Unity MCP を使えば「シーンに新規 GameObject を配置 → Inspector の値を設定」まで AI に任せられる(はず)
AI駆動開発の正直な感想
AIは「実装力」を確実に底上げしてくれるが、「設計力」は逆に試される。設計が甘いと AIは甘い設計のままコードを増殖させる。
ある意味、AI時代こそアーキテクチャ設計の重要性が高まっているというのが正直な実感です。
4️⃣ 第4位:デザインと「引き算」への葛藤
デザインセンスの壁にもぶち当たりました。最初は「とりあえず動く」状態のこんな感じの画面でした。
何が起きたか
- 初期画面は機能を全部詰め込んだ「とりあえず動く」UI
- ユーザーから「何を見ればいいか分からない」フィードバック多数
なぜハマったか
書籍や動画で UI/UX を学習しましたが、一番難しかったのは 「画面から情報を落とす(引き算する)」 という作業でした。
優れたデザインは機能美を伴ったシンプルなものが多いですが、自分で作るとどうしても要素を詰め込みたくなってしまいます(「この機能、いつ気づいてもらえるんだろう」と不安になる)。
どう解決したか
- 重要度の低い情報は1階層下のメニューに格納(設定、最大タイル履歴など)
- 常時表示は「現在スコア / ベストスコア / 補充ゲージ」の3つだけに絞る
- テーマカラー6種類(Cyan / Purple / Dark / Green / Navy / Maroon)で背景・チューブ・タイルパレットを統一管理し、配色のブレを排除
今回はアドバイスを求めながら、なんとか今のクリーンな形に落ち着かせました。
今ならこうする
- 次回作では Stitch などのAI UIデザインツールも取り入れる
- モックアップ段階で「3秒で何のゲームか分かるか」テストを友人にやってもらう
- デザイン原則:1画面1メッセージ。これを徹底するだけで完成度が一段上がる
📊 おまけ:数字で見る個人開発の実態
| 項目 | 数値 |
|---|---|
| 開発期間 | 約4ヶ月(平日夜+週末) |
| 実働時間 | 約200時間 |
| MacinCloud 利用時間 | トータル約15時間 |
| 申請リジェクト回数 | 3回 |
| AIが書いたコード比率(体感) | 約80% |
| 実装ファイル数 | 約30(Model 1 + UI partial 5 + Manager 系 8 + Config 3 + その他) |
| テーマ数 | 6種類 |
| BGM/SE | 一部プロシージャル生成(コード上で波形生成) |
🎬 おわりに
トラブルの連続でしたが、無事にリリースできた時の達成感はひとしおです。Windows環境でのiOS開発はハードルが高いですが、MacinCloud を駆使すれば十分可能だということが証明できました。
そして個人的に最大の学びは:
クラウドMacでリリースするのは実機のみ発生するバグがあったときに、ログを追うこと自体が大変になる
開発はAI駆動で実装スピードを劇的に上げるが、設計力を持っていないと「速く崩壊するコード」を量産するだけ。AI時代こそ、アーキテクチャ設計とドメイン分離の基本が効く。
ということでした。
パズルゲーム 『tube-2048-数字を重ねるマージパズル』、ぜひ遊んでみてください!👇
📱 App Store: https://apps.apple.com/us/app/tube-2048-数字を重ねるマージパズル/id6761907896
質問・感想・「自分はこう解決した」エピソードがあれば、コメントや X でぜひ教えてください。次回作では今回の反省を活かして、MCPサーバーをフル活用した自動化開発を目指します!
