1. はじめに 〜大盛況のARプリクラ、実は「AI」が作りました〜
昨日、グループ展 中庭が開催され、私は「外見を飾る行為から、内面(AR空間)への没入へ」をコンセプトにした次世代ARプリクラ『IMMESNAP』展示しました。
IMMESNAPのARイマーシブ体験
体験していただいた方からは「まるで本物のプリクラ!」「こんなリアルタイムでWebAR体験できるの!?」と嬉しいお声をたくさんいただきました。ありがとうございます。
しかし、ここで一つの種明かしをさせてください。
実は私、この複雑なシステムのコードをほとんど自分で書いていません。
私は「プロダクトマネージャー(PM)」および「体験設計」に重きを置き、優秀な「AIエンジニア」たちとチームを組んで、ゴリゴリのAI駆動開発(AI-Driven Development)で作り上げました。
この記事では、[〜IMMESNAP実装編〜] として、iOS(Swift)× Unity WebGL × Firebaseという複雑なアーキテクチャを、いかにしてAIと構築したのか。そして、市販のプリクラ機に負けないクオリティを出すためにAIとどう激闘を繰り広げたのか、その「プロンプト」と「神コード」の全貌を公開します。
2. 全体アーキテクチャと「AIチーム」の異常な座組
IMMESNAPの体験フロー
システムは大きく4つのフェーズで構成されています。
- iPad (Swift/Unity): 高画質撮影 & リッチなデコレーション(落書き)
- Firebase (RTDB/Storage): 画像とセッションデータのクラウド同期
- 物理プリンタ: バックグラウンド処理で、体験者のQRコード付きオリジナルカードを熱転写プリント
- WebAR (スマホ): アプリレスでQRを読み込み、印刷されたカードの上にデコレーションがARで飛び出す
最強の「AI開発チーム」体制
この広範囲な技術スタックを実装するため、以下のような役割分担で開発を進めました。
- 私(人間): PM・体験設計・エンジニアを担当。
- デザイナー(人間): UI/UXデザインを担当。
- Gemini(Web): 技術顧問・アーキテクト。技術選定やトラブルシューティング、全体の構成案を相談する壁打ちAI。
- Antigravity: エンジニア。実際にSwiftやC#のコードを書き、バグを修正する実装担当AI。
💡 開発を爆速化させた「AIマネジメント」の極意
今回、AIを単なる「コード生成ツール」としてではなく、本当のチームメンバーレベルで扱いました。その最大のハックがAIにチケット(タスク)を切らせ、AI自身に実装プロンプトを考えさせるという手法です。
例えばですが、以下の1〜4の流れで一機能(ネオンペン)を作りました。
- 私が「ネオンペン作りたい!」とGemini(壁打ちAI)に言う。
- Geminiがそれを要件定義し、JiraやBacklogのような開発チケットに落とし込む。
- さらにGeminiが、Antigravity(実装AI)が一番理解しやすい完璧な指示プロンプトを生成する。
- それをAntigravityにコピペして投げ、実装させる。
この「AI to AI」のディレクション・リレーにより、非エンジニアでも信じられないスピードで高品質なシステムを組み上げることができました。
チケット管理の様子(今回は一人なんでスプシでやっちゃいました)

ここからは、実際にAIと繰り広げた技術的な激闘の記録です。
当然ですが、AIがプロンプトを書いたからと言って、バグが出ないわけではありません。全然でます。
3. 激闘の記録①:市販機に負けない「ネオンペン」の描画ロジック
背景:デコレーションがリッチじゃないとテンション上がらない
ARで飛び出す体験が今回の差分とはいえ、プリクラの醍醐味は「デコレーション(落書き)」です。リッチなデコじゃないとテンションは上がらないものです。
当初、Unityの GL クラスを使って透明な RenderTexture にQuadを描画する方式でペンを実装しました。しかし、指の移動座標間を補間して丸いテクスチャを連続スタンプする仕様上、**「線が点の連続に見えてしまう(スタンプ感)」「描き始めと終わりに不自然な丸が残る」**という致命的なダサさがありました。
AIへの無茶振りプロンプト
そこで私は、AIに対してネオン感が出るように指示を出しました。

【私からの指示(抜粋)】
実際に投げたプロンプト
# Bolt 26: デコペン描画ロジック刷新
## 1. 課題(画像1参照)
- 描画の始終点に不自然な「丸」が残る。
- 線がスタンプの連続(ドット感)に見える。
## 2. 実装要件(画像2, 3の再現)
現在のGL描画とUndoロジックを維持したまま、以下を実装してください。
- **描画改善**: 補間間隔やアルファ処理を最適化し、スタンプ感と端の丸残りを解消。
- **3種のスタイル選択**:
1. **Normal**: 滑らかな通常ペン。
2. **Outline(縁取り)**: 選択色を暗くした下地 + 選択色の芯。
3. **Neon(ネオン)**: 選択色の発光下地 + 白色の芯。
- **動的カラー計算**: ユーザーが選んだ1色から、スタイルに応じたサブカラーを自動算出。
## 3. 進行
まず、丸残りを消すための「描画アルゴリズムの改善案」と、2パス描画(下地→芯)に対応させるための「データ構造の更新案」を提示してください。
AIが叩き出した「2パス描画+加算合成」の神コード
古のプロンプトから、AIエンジニアは**「動的カラー計算を用いた2パス描画(下地+芯)」と「ブレンドモードの変更」**という完璧な最適解を出してきました。
ネオンの発光感(Bloom感)を疑似再現するために、下地を超太め・超低アルファ値のガウスぼかしテクスチャにし、さらに 加算合成(Blend SrcAlpha One) で描画するロジックです。
AIが生成した実際の描画ロジック(C#抜粋)
// ネオンペンの2パス描画ロジック(簡略化)
public void DrawNeonStroke(Vector2 start, Vector2 end, Color baseColor, float thickness)
{
// --- パス1:発光(下地)の描画 ---
// 発光感(Bloom)を出すため、加算合成マテリアルを使用
neonGlowMaterial.SetPass(0);
// ベース色からアルファ値を極端に下げ(0.05等)、太さを3〜5倍にする
Color glowColor = new Color(baseColor.r, baseColor.g, baseColor.b, 0.05f);
float glowThickness = thickness * 4.0f;
GL.Begin(GL.QUADS);
GL.Color(glowColor);
// 補間ポイントごとに柔らかいグラデーションテクスチャをスタンプ(加算されて光が強くなる)
DrawQuadAt(start, end, glowThickness);
GL.End();
// --- パス2:芯(白線)の描画 ---
// くっきりさせるため通常のアルファブレンドを使用
normalBlendMaterial.SetPass(0);
// 芯は明度を最大(真っ白)にし、細く描く
Color coreColor = Color.white;
float coreThickness = thickness * 0.8f;
GL.Begin(GL.QUADS);
GL.Color(coreColor);
DrawQuadAt(start, end, coreThickness); // スタンプ感を消すため補間距離を密に調整
GL.End();
}
4. 激闘の記録②:iOS Vision APIによる「超・高精度」切り抜き
背景:AR演出のために背景を綺麗に切り抜きたい!
今回のコンセプト中に、「ARでより内面へ没入する」というものがあります。
ユーザーがQRを読み込んでスマホをかざした時、AR空間の背景が「ただの壁」だったら、一気に現実に戻されてしまいますし、何より面白くない! 別次元にダイブしたような「Wow!」という感動を生むためには、人物だけを完璧に切り抜き、背景をごっそりAR空間のものにすり替える必要がありました。
AIとの突破劇:Unityを捨ててiOSネイティブに頼る
最初はUnity内で切り抜き処理(セグメンテーション)を行おうとしましたが、iPadの処理落ちや精度の低さが壁になりました。
ここでAIに相談したところ、iPadのネイティブパワー(Neural Engine)をフル活用するべき。iOSのVision Frameworkで切り抜き、その結果のマスク画像をUnityに渡すのが最強というアーキテクチャ提案を受け、実装に移りました。
AIが実装したiOSネイティブの人物切り抜き(Swift抜粋)
import Vision
import CoreImage
// Neural Engineを駆使した人物セグメンテーション
func performPersonSegmentation(on image: CIImage) -> CIImage? {
let request = VNGeneratePersonSegmentationRequest()
request.qualityLevel = .accurate // 最高精度を指定
request.outputPixelFormat = kCVPixelFormatType_OneComponent8
let handler = VNImageRequestHandler(ciImage: image, options: [:])
do {
try handler.perform([request])
guard let maskPixelBuffer = request.results?.first?.pixelBuffer else { return nil }
// 生成されたマスク(白黒画像)を元画像に適用
let maskImage = CIImage(cvPixelBuffer: maskPixelBuffer)
let blendedImage = image.applyingFilter("CIBlendWithMask", parameters: [
kCIInputMaskImageKey: maskImage
])
return blendedImage
} catch {
print("Vision APIエラー: \(error)")
return nil
}
}
これが本当に革命でした。めっちゃ綺麗に切り抜ける!!!
この結果、髪の毛一本まで綺麗に抜ける超高精度な人物切り抜きが爆速で完了し、ARで背景を夜景や宇宙空間にすり替える「Wow!」な演出が実現しました。
5. 激闘の記録③:WebGL × Firebaseの極限軽量化と、Safariの罠
背景:WebARのロード時間かかりすぎ問題
アプリ不要で体験できるWebARですが、Unity WebGLのビルドデータは重くなりがちです。ロードに数秒かかると、展示がグダグダになってしまします。
さらに、iOS Safari特有の地獄のバグであるカメラ権限を許可した瞬間に画面がブラックアウト(無限フリーズ)するという現象にも直面しました。
AIの神提案:SDKの排除とUIオーバーレイ
私はAIに「とにかくロードを爆速にして、Safariのフリーズを回避して!」と指示。
するとAIは、**「重いFirebaseの公式Unity SDKをすべて削除し、REST API(URL直叩き)で通信する」**という驚きの軽量化アプローチを提案してきました。
さらに非同期処理の競合を防ぐため、Firebase側に isReadyForAR というフラグを用意。画像アップロードが完全に終わるまで、WebAR側は軽量なJSONだけを毎秒ポーリング(監視)し続ける安全な設計です。
公式SDKを捨てた、爆速REST API監視ロジック(C#抜粋)
// WebGLから直接Firebase Realtime DatabaseのREST APIを叩く
private IEnumerator CheckReadyStatus(string sessionId)
{
string url = $"https://[プロジェクトID][.firebaseio.com/sessions/](https://.firebaseio.com/sessions/){sessionId}/isReadyForAR.json";
while (true)
{
using (UnityWebRequest request = UnityWebRequest.Get(url))
{
yield return request.SendWebRequest();
// JSONが "true" になっていれば、初めて重いテクスチャのDLを開始する
if (request.result == UnityWebRequest.Result.Success && request.downloadHandler.text == "true")
{
Debug.Log("アップロード完了を確認!ARのロードを開始します。");
StartCoroutine(DownloadTextures(sessionId));
yield break;
}
}
// 1秒待機して再確認(ポーリング)
yield return new WaitForSeconds(1.0f);
}
}
Safariのカメラフリーズ問題についても、AIは「WebGLの描画初期化とカメラの起動が衝突している」と原因を特定し、カメラが完全に起動するまでHTML側のUI(DOM)で画面を覆い隠すというハックで完璧に回避してくれました。
6. 現場のリアル:展示を止めない「フェールセーフ」設計
ソフトウェアが完璧でも、物理ハードウェアが絡む展示ではプリンタの紙詰まり・インク切れという惨劇が必ず起きます...
エラーでユーザーのデータが消えれば、体験者のテンションはどん底です。
ここで私がこだわったのが、絶対にデータをロストさせないリカバリー設計です。AIに「印刷失敗時に復旧できる管理画面を作って」とチケットを切りました。
AIは、前述の isReadyForAR(アップロード完了)とは別に、isPrinted(物理印刷完了)というフラグをデータベースに追加しました。
プリンタ復旧用のサルベージロジック(C#抜粋)
/// <summary>
/// 印刷待ちのセッション(isReadyForAR == true かつ isPrinted == false)のみを抽出
/// </summary>
public async UniTask<List<SessionData>> GetUnprintedSessionsAsync()
{
// (中略:REST APIで全セッションを取得)
var unprintedSessions = new List<SessionData>();
foreach (var session in allSessions)
{
// 準備完了しているが、まだ紙として出力されていないデータだけを救出
if (session.isReadyForAR && !session.isPrinted)
{
unprintedSessions.Add(session);
}
}
return unprintedSessions;
}
この裏メニュー(PrintRecoveryScene)のおかげで、現場で紙詰まりが起きても、スタッフがiPadを数回タップするだけで即座に未印刷のカードだけを再出力でき、展示を一度も止めることなく回し切ることができました。
7. おわりに:次の野望と「AI時代のモノづくり」
実は今回のMVP(最小限のプロダクト)リリースに間に合わず、泣く泣くカットした機能があります。
もっと盛れる機能(目を大きくする、スタンプのデコレーションなどなど)を実装していきたいです!!
また、今回の展示で強く思ったのは、
非エンジニアでも「想像力」があればシステムは作れる
この巨大で複雑なアーキテクチャを少人数かつ爆速で組み上げられたのは、間違いなくAI駆動開発のおかげです。
PM(人間)が「こういう体験を作りたい!」という強い熱量とバイブスを持ち、壁打ちAI(Gemini)と要件を詰め、実装AI(Antigravity)に的確なプロンプト(チケット)を投げる。
AIを単なる「チャットボット」ではなく「チームメンバー」として扱うことで、個人のクリエイターが普通のプリクラではできない体験を作り出せる時代が来ました。
この記事が、皆さんの「作りたい!」という熱狂の背中を少しでも押せたら嬉しいです。
(最後まで読んでいただき、ありがとうございました!)


