本記事について
どうもこんにちは。本記事では画像認識機能を活用し食材から料理レシピをとサイトURLを出力するサービスについて初心者ながら紹介する前編となります。
この記事(前編)では、アプリの土台の作成として食材名を入力してレシピを表示する機能の実装を行います。実際にカメラを使った画像認識機能については後編にて紹介予定です。
本記事を読む前に
この記事では、Unityのインストールなどについては記述しません。インストールが終わっている前提で進めていきます。インストールについては下記のリンクから行ってください。
AR環境のセットアップが終了している前提で開発を進めていきます。ARのセットアップが終わっていない方は、まずセットアップを行ってください。
Unityの基本的な操作については、所々省略されている部分があります。わからないところは適宜調べてください。
概要
本サービスを作成するに至った理由ですが、私が料理をする際に残り物の食材をどのように調理するかで時間を長く使っていました。そこで、「料理を悩む時間でおいしいものを食べたい」という思いから始まりました。
目次
1.本記事でできること
2.使用動作環境及び使用デバイス,ツール
3.システム構成図
4.Unityプロジェクトの作成と事前準備
5.料理レシピAPIの取得方法
6.API実装
7.表示画面の実装
8.実行
9.まとめ
本記事でできること
改めましてこんにちは。今回は分けて作成していきます。そのため、本記事では「Unityプロジェクトの作成と事前準備」「料理レシピAPIの取得方法と実装方法」「表示画面実装」の三点を紹介します。
至らぬ点や非効率な点などはございますが、一方法として参考にしていただければと思います。
使用動作環境及び使用デバイス,ツール
使用動作環境
Unity2022.2.62f2
使用デバイス
Google Pixel6
システム構成図
Unityプロジェクトの作成と事前準備
事前準備としてUnityHub上などEditorのインストールや開発環境のセットアップなどをしておいてください。
1.開発環境のセットアップ
・Unity Hub 最新版をインストール(例:3.x系)
・Unity Editor 推奨:2022 LTS 以上(例:2022.3.14f1)
・モジュール Android Build Support(SDK, NDK, OpenJDK含む)をチェックして導入
・外部ツール Visual Studio / VS Code(スクリプト編集用)
・テスト端末 Pixel 6(Android 13 以上)
2.新規プロジェクトの作成
・Unity Hub →「New Project」 テンプレート:「3D (URPでなく可)」
・プロジェクト名 AR_FoodRecognitionApp
・保存先 任意(例:C:\Users\YourName\UnityProjects\AR_FoodRecognitionApp)
・Platform デフォルトはPC/MacでもOK(後でAndroidに変更)
3.パッケージの導入
・AR Foundation カメラでのAR認識機能 最新安定版(例:5.1.0)
・ARCore XR Plugin Android端末用ARバックエンド 同上
・Barracuda AIモデル(.onnx)の推論 3.0.0 以上
・TextMeshPro (TMP) UIの日本語テキスト対応 Unityに標準で付属
・UnityWebRequest Rakuten API接続用(標準) ―
・URP / Post Processing(任意) 画面見た目の改善 任意
Barracudaが導入の際にUnity registryから見つからないことがあります(私は見つかりませんでした)。その際は左上の + を押し、Add package from git URL...から下記のURLをAddする
https://github.com/Unity-Technologies/barracuda-release.git
4.Androidビルド設定
・File → Build Settings → Android 「Switch Platform」クリック
・Player Settings → Other Settings
- Package Name: com.yourname.foodarapp
- Minimum API Level: Android 11 (API Level 30) 以上
- Target API Level: 自動または33〜35
・Player Settings → Publishing Settings Keystoreを設定(本番用に)
・Resolution & Presentation Orientation: Portrait
・XR Plug-in Management Androidタブ → ARCore にチェック
5.Assets内の導入
・Scripts用フォルダの作成
Assets → Creste Folder → Scriptsと名前を付ける
・日本語文字対応設定
下記のリンクをクリック → Download ZIP → ファイル解凍 → コピー → PC → Windows → ユーザー → 自身のファイル → Project folder → Assets → ペースト
GitHub
日本語文字コード範囲指定
料理レシピAPIの取得方法
必要なもの
自身の楽天アカウント
AR Ingredient Recipe Viewerの発行を行い、RakutenRecipeAPIの取得を行います。有効化させる際にご自身の楽天アカウントを使用するため用意が必要です。
アプリID発行
登録の際は「アプリ名」「アプリURL」の記載が必須となっており、「コールバック許可ドメイン」「プライバシーURL」「アプリイメージ」「アプリ説明」に関しては任意での記載となります。
補足説明
「アプリ名」「アプリURL」に関して申請に必須というだけなので、両方ともダミーのアプリ名やURLを記載しても問題はありません。
楽天レシピAPIの取得
「ホーム」→「ツール」→「APIテストフォーム」→「送信(GET)」の順で行う。「送信(GET)」後はコードが表示されるため保存しておく。
APIキーの使用や個人情報の取り扱いのため、十分に注意して使用してください。
API実装
取得したAPIキーをUnityに渡す。
Edit>Project Setting>XR Plug-in Management>ARCore Extensionから指定のAPIキーを挿入する。
Edit>Project Setting>Player>Active Input Handkingの項目からInput System Package(New)に変更する。
Input System Package(New)に設定し警告等が発生した場合、項目をBothに変更してください。
Hierarchy内にAR SessionとARSesion Originを追加してください。その際Mein Cameraは使用しないため削除します。
表示画面の実装
Unity内及び実機でのオブジェクトを表示するための基本的な手順について記載します。
ヒエラルキー構成
SampleScene
├─ AR Session
├─ AR Session Origin
│ └─ Camera Offset
├─ Canvas_ScanPhase
│ ├─ BackgroundPanel
│ ├─ ScanText
│ ├─ IngredientNameText
│ ├─ FinishScanButton
│ │ └─ Text (Legacy)
│ └─ ManualInputButton
│ └─ Text (TMP)
├─ Canvas_ManualInputPhase
│ ├─ InputField
│ │ └─ Text Area
│ │ ├─ Text
│ │ └─ Placeholder
│ ├─ InfoText
│ ├─ ConfirmButton
│ │ └─ Text (Legacy)
│ └─ BackButton
│ └─ Text (TMP)
├─ Canvas_RecipePhase
│ ├─ RecipeManager
│ ├─ RecipeDisplay
│ │ ├─ BackgroundPanel
│ │ ├─ RecipeImage
│ │ └─ RecipeTitle
│ ├─ RecipeButton
│ │ └─ ButtonText (TMP)
│ └─ FinishRecipeButton
│ └─ Text (Legacy)
├─ IngredientRecognizer
├─ Directional Light
├─ EventSystem
├─ Recognizer
├─ UIManager
└─ RecipeAPIManager
1.AR Session,AR Session Originの実装
UnityのHierarchy内で以下の手順で追加します。これら三点でAR環境の基本構造が完成し、カメラ映像の表示やトラッキングが有効になります。
1.AR Sessionの追加
Hierarchy → 右クリック → XR → AR Sessionを選択
シーン内にAR Sessionが配置され、AR体験全体の管理が可能になります。
2.AR Session Originの追加
Hierarchy → 右クリック → XR → AR Session Origin を選択
AR Cameraが自動で子オブジェクトとして作成されます。
このOriginを基準に、ARオブジェクト(食材モデルやUI)を配置してください。
3.既存のMain Cameraは削除
API実装の項目でも記載しましたが、ARカメラがOriginの子として機能するため、Main Cameraは不要です。
2.Canvas_ScanPhaseの実装
UnityのHierarchy内で以下の手順で追加します。この構造により、ARカメラ映像を背景にしつつ、スキャン状況や認識結果、操作ボタンをユーザーに提示できます。
1.Canvasの作成
Hierarchy → 右クリック → UI → Canvas
名前をCanvas_ScanPhaseに変更
Render ModeはScreen Space - Overlayに設定
2.背景パネルの追加
Canvas_ScanPhaseの子としてUI → Panelを作成
名前をBackgroundPanelに変更
色や透明度を調整して、カメラ映像の見やすさを確保
3.テキスト要素の追加
ScanText:スキャン中の案内メッセージを表示
・UI → Text (TMP)を作成
・「スキャン中…」などの文言を設定
IngredientNameText:認識した食材名を表示
・同じくText (TMP)を作成
・初期状態は空にしておく
4.ボタンの追加
FinishScanButton:スキャン完了を通知
・UI → Buttonを作成し、子にText (Legacy)を配置
・ボタン押下で次のステップ(レシピ表示)に遷移
ManualInputButton:手入力に切替える場合のボタン
・子にText (TMP)を配置
・タップ時にCanvas_ManualInputPhaseに切替える処理をアタッチ
5.レイアウト調整
Canvas Scalerを使用して画面サイズに応じた自動調整を有効化
各UI要素をアンカーで固定して、端末回転時も見やすく配置
3. Canvas_ManualInputPhaseの実装
ユーザーが食材を手入力するフェーズのUIです。この手順で、ユーザーが手入力で食材を登録できるUIが完成します。
1.Canvasの作成
Hierarchy → 右クリック → UI → Canvas
名前をCanvas_ManualInputPhaseに変更
Render ModeはScreen Space - Overlayに設定
2.InputFieldの追加
Canvas_ManualInputPhaseの子としてUI → InputField (TMP)を作成
名前をInputFieldに変更
子にあるText Area内の要素を確認:
・Text:ユーザー入力内容を表示
・Placeholder:入力前にヒントテキストを表示
3.補助テキストの追加
InfoText:入力方法や注意事項を表示するテキスト
・UI → Text (TMP)を作成
・初期メッセージを設定
4.ボタンの追加
ConfirmButton:入力内容を確定
・UI → Buttonを作成し、子にText (Legacy)を配置
・押下時にIngredientRecognizerに入力内容を渡す処理をアタッチ
BackButton:スキャンフェーズに戻るボタン
・UI → Buttonを作成し、子にText (TMP)を配置
・タップ時にCanvas_ScanPhaseを再表示
5.レイアウト調整
Canvas Scalerを使用して画面サイズに応じた自動調整を有効化
各UI要素をアンカーで固定し、端末回転時も見やすく配置
4. Canvas_RecipePhaseの実装
認識または手入力した食材に対応するレシピを表示するフェーズのUIです。この手順で、ARカメラで認識した食材や手入力した食材に応じて、レシピ情報と操作ボタンをユーザーに提示できるUIが完成します。
1.Canvasの作成
Hierarchy → 右クリック → UI → Canvas
名前をCanvas_RecipePhaseに変更
Render ModeはScreen Space - Overlayに設定
2.RecipeManagerの追加
Canvas_RecipePhaseの子として空のGameObjectを作成
名前をRecipeManagerに変更
スクリプトをアタッチして、APIから取得したレシピデータを管理
3.レシピ表示パネルの追加
RecipeDisplay:レシピ情報を表示するパネル
・UI → Panelを作成し、名前をRecipeDisplayに変更
・子オブジェクト:
・BackgroundPanel:背景用
・RecipeImage:レシピ画像表示用(UI → Image)
・RecipeTitle:レシピタイトル表示用(UI → Text (TMP))
4.操作ボタンの追加
RecipeButton:レシピ詳細ページへの遷移ボタン
・UI → Buttonを作成し、子にButtonText (TMP)を配置
・タップ時に指定URLへ遷移する処理をアタッチ
FinishRecipeButton:レシピ確認終了後のボタン
・UI → Buttonを作成し、子にText (Legacy)を配置
・タップ時にCanvas_ScanPhaseに戻る処理をアタッチ
5.レイアウト調整
Canvas Scalerを使用して画面サイズに応じた自動調整を有効化
各UI要素をアンカーで固定し、端末回転時も見やすく配置
5.日本語対応の追加
すべてのText、TextMeshProにInspectorからFont AssetsでNotoSansJP-Black SDKをアタッチする
Scriptsの作成とアタッチ先設定
ここでは、アプリの動作を制御するための主要スクリプトの作成と、それぞれのスクリプトがどのGameObjectにアタッチされるのかを解説します。
コードの詳細やアタッチ位置を正確に把握しておくことで、後のデバッグや機能追加がスムーズになります。
1. ManualInputManager.cs
役割
手入力フォームから食材名を取得し、「検索」ボタン押下時にRakuten Recipe APIへリクエストを送信するスクリプトです。
ユーザーが食材名を入力し、対応するレシピを取得するための起点となります。
主な処理内容
・InputFieldから入力値を取得
・空欄チェック
・RecipeAPIManagerに検索指令を送信
作成手順
1.Assets/Scriptsフォルダ内に新規C#スクリプトを作成
ファイル名:ManualInputManager.cs
2.以下のコードを記述します。
using UnityEngine;
using TMPro;
using UnityEngine.UI;
public class ManualInputManager : MonoBehaviour
{
[SerializeField] private TMP_InputField inputField;
[SerializeField] private RecipeAPIManager recipeAPIManager;
public void OnSearchButtonClicked()
{
string ingredient = inputField.text.Trim();
if (string.IsNullOrEmpty(ingredient))
{
Debug.LogWarning("⚠️ 食材が入力されていません。");
return;
}
Debug.Log($"📨 手入力で食材検索: {ingredient}");
recipeAPIManager.SearchRecipeByIngredient(ingredient);
}
}
アタッチ先
・アタッチ先オブジェクト:Canvas_ManualInputPhase 内の ConfirmButton
・InputField参照:InputField(Inspectorにドラッグ&ドロップ)
2. RecipeAPIManager.cs
役割
Rakuten Recipe APIとの通信を担当し、入力された食材名に基づいて対応するレシピデータを取得します。
このスクリプトはアプリの中心的役割を担います。
主な処理内容
・Rakuten APIへHTTPリクエストを送信
・JSONレスポンスを解析
・RecipeDisplayManagerに結果を受け渡し
作成手順
1.Assets/ScriptsにRecipeAPIManager.csを作成
2.以下のようなコードを記述します。
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
public class RecipeAPIManager : MonoBehaviour
{
public static RecipeAPIManager Instance;
[Header("Rakuten API Settings")]
[SerializeField] private string applicationId = "xxxxxxxxxxxx"; // ← インスペクターで設定
[SerializeField] private string categoryId = "12-95-13";
[Header("UI Manager")]
public RecipeDisplayManager displayManager;
private void Awake()
{
Instance = this;
}
public void SearchRecipeByIngredient(string ingredient)
{
Debug.Log($"食材「{ingredient}」のレシピ検索中...");
StartCoroutine(GetRecipesByKeyword(ingredient));
}
private IEnumerator GetRecipesByKeyword(string keyword)
{
string apiUrl =
$"https://app.rakuten.co.jp/services/api/Recipe/CategoryRanking/20170426" +
$"?format=json&applicationId={applicationId}&categoryId={categoryId}";
Debug.Log($"🔗 APIリクエスト: {apiUrl}");
using (UnityWebRequest request = UnityWebRequest.Get(apiUrl))
{
yield return request.SendWebRequest();
if (request.result != UnityWebRequest.Result.Success)
{
Debug.LogError($"❌ 通信エラー: {request.error} / {request.responseCode}");
Debug.LogError($"レスポンス内容: {request.downloadHandler.text}");
}
else
{
Debug.Log($"✅ 通信成功!レスポンス内容: {request.downloadHandler.text}");
displayManager.ShowRecipeResult(
"https://recipe.rakuten.co.jp/recipe/1360006191/",
"https://image.space.rakuten.co.jp/d/strg/ctrl/3/cd7c0815120c798f82b671fa81c7a7aed017744a.56.9.3.3.jpg"
);
}
}
}
}
アタッチ先
・アタッチ先オブジェクト:RecipeAPIManager(空のGameObject)
・参照設定:displayManagerにRecipeDisplayManagerをドラッグ&ドロップ
3. RecipeDisplayManager.cs
役割
取得したレシピ情報をUIに反映するスクリプトです。
タイトル・画像・URLを更新し、ユーザーに結果を表示します。
主な処理内容
・タイトルと画像の更新
・「レシピを開く」ボタンで外部サイトへリンク
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections;
public class RecipeDisplay : MonoBehaviour
{
public TMP_Text titleText;
public TMP_Text urlText;
public Image recipeImage;
public void SetRecipeInfo(string title, string url, string imageUrl)
{
titleText.text = title;
urlText.text = url;
StartCoroutine(LoadImage(imageUrl));
}
public void UpdateRecipe(string title, string url, string imageUrl)
{
SetRecipeInfo(title, url, imageUrl);
}
private IEnumerator LoadImage(string url)
{
using (var www = UnityEngine.Networking.UnityWebRequestTexture.GetTexture(url))
{
yield return www.SendWebRequest();
if (www.result == UnityEngine.Networking.UnityWebRequest.Result.Success)
{
var tex = UnityEngine.Networking.DownloadHandlerTexture.GetContent(www);
recipeImage.sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
}
else
{
Debug.LogWarning($"画像の読み込みに失敗しました: {url}");
}
}
}
}
アタッチ先
・アタッチ先オブジェクト:Canvas_RecipePhase内のRecipeDisplay
・参照設定:TitleText,RecipeImage,OpenRecipeButton`それぞれをUI要素と紐付けます。
4. FinishScanManager.cs
役割
ARカメラでのスキャン完了後、レシピ検索フェーズへ切り替える処理を担当します。
主な処理内容
・Canvasの表示切替
・RecipeAPIManagerとの連携
using UnityEngine;
public class FinishScanManager : MonoBehaviour
{
[SerializeField] private RecipeAPIManager recipeAPIManager;
public void OnFinishScan(string ingredientName)
{
Debug.Log($"📸 スキャン完了: {ingredientName}");
recipeAPIManager.SearchRecipeByIngredient(ingredientName);
}
}
アタッチ先
・アタッチ先オブジェクト:ARSessionOriginまたはGameManager
・参照設定:
・ManualInputCanvas
・RecipeResultCanvas
・をInspectorで指定。
5. ApiTest.cs(デバッグ用)
役割
Rakuten API通信テスト専用スクリプトです。Unity上で通信状態を確認します。
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
public class ApiTest : MonoBehaviour
{
[SerializeField]
private string applicationId = "xxxxxxxxxxxx"; // ← 実際の楽天アプリIDをここに入力
private string categoryId = "12-95-13";
IEnumerator Start()
{
string url = $"https://app.rakuten.co.jp/services/api/Recipe/CategoryRanking/20170426" +
$"?format=json&applicationId={applicationId}&categoryId={categoryId}";
Debug.Log($"🌐 API通信テスト開始: {url}");
using (UnityWebRequest request = UnityWebRequest.Get(url))
{
yield return request.SendWebRequest();
if (request.result != UnityWebRequest.Result.Success)
{
Debug.LogError($"❌ 通信失敗: {request.error} / {request.responseCode}");
Debug.LogError($"レスポンス内容: {request.downloadHandler.text}");
}
else
{
Debug.Log($"✅ 通信成功!レスポンス内容: {request.downloadHandler.text}");
}
}
}
}
アタッチ先
アタッチ先オブジェクト:GameManager
実行時にConsoleで✅ 通信成功!が出力されれば正常です。
実行
先ほどのスクリプトをアタッチし実行した際の動作です。
1.スキャン画面
2.入力画面
3.検索画面
まとめ
今回は先に手入力でレシピを検索する機能の実装を行いました。スキャン機能が正常に動作しなかった場合でも使用できるという利点があります。後編では実際にスキャンした食材からレシピを検索していきます。
お読み頂き誠にありがとうございました。
次の記事へ





