🐷

UnityでChatGPTレスポンスを1文字ずつ取得する方法

2025/01/24に公開

UnityでChatGPTレスポンスを1文字ずつ取得する方法

Unityゲームやアプリケーションを開発していると、テキストの動的な表示にこだわりたくなる場面があります。

とくにChatGPTのようなAIチャットサービスからの返答をリアルタイムに演出できれば、インタラクティブで魅力的なUX(ユーザー体験)を提供できるでしょう。

しかし、ChatGPTのAPIをただ呼び出すだけでは、一度にまとまったテキストを受け取ることになりがちです。「ちょっとずつ文字が出てくる」演出をUnityでどう実装するのか、意外と情報が少なく、つまずくことも多いかもしれません。

そこで本記事では、ChatGPT APIのストリーミング機能を活用し、Unityで1文字ずつ返答を受け取って表示する方法をご紹介します。

なぜストリーミング表示が必要なのか

ゲームやアプリでAIが回答を返してくれるとき、つい連想するのはRPGでの会話ウィンドウのように、徐々にテキストが打ち出されていく効果かもしれません。

これによってドラマチックな演出が可能となり、ユーザーの没入感を高めることができます。ですが、従来のChatGPT API(Completion APIやChat APIなど)を普通に呼び出すと、以下のような問題が生じる可能性があります。

  • 文字列を一括で受信してしまう
    「文字が打ち出されている最中」のような体験が得られない。
  • 長い文章の処理時間が分かりづらい
    一度に大量の文章を生成する場合、ユーザーは“待ち時間”を持て余し、体感的に長く感じる。
  • ユーザー体験の向上が難しい
    インタラクティブ性を高めたいのに、メッセージが突然表示されるため演出のタイミングを操作しづらい。

こうした問題を解決する方法として、OpenAIが提供するストリーミングAPI(Streamモード)が注目されています。これを利用することで、ChatGPTの出力を細かい分割データ(チャンク)として受け取り、受け取るたびに少しずつ画面へ反映させることができます。

Unityでストリーミングを実装するには

1. ChatGPT APIのストリーミングモードを使う

OpenAIのChat API(ChatCompletion)には、stream=true というパラメータを設定できるオプションがあります。これを有効にすると、サーバーから一度にバッチリまとめたテキストを返すのではなく、複数のチャンクとして順次メッセージを受信できます。これを使うと、ネットワーク通信のタイミングでイベントを受け取りながら、テキストを一文字ずつ、または適当なサイズごとに表示することが可能となります。

2. Unity C#でのHTTP通信

ストリーミングを受け取るためには、まずUnityからHTTPリクエストを送り、レスポンスを逐次的に読み込める仕組みが必要です。主な選択肢としては以下があります。

  • UnityWebRequest を使う方法
    Unity標準のUnityWebRequestには、ストリーミングダウンロードに対応する機能があります。DownloadHandlerScriptを拡張したクラスを作って、バイト単位で受信したタイミングを取得し、テキストに変換していく方法です。
  • 外部ライブラリ(HttpClient等)を使う方法
    .NET標準のHttpClientを使うか、あるいは外部アセットを利用することで、サーバーからのHTTPレスポンスをストリーミング的に処理できます。
    ただしUnityエディタバージョンや.NETの互換性に依存する場合もあるため注意が必要です。

3. コルーチンまたはasync/awaitで処理を管理する

Unityで長時間にわたる処理を扱うには、コルーチン(IEnumerator)を活用するか、あるいはC#のasync/awaitを用いる方法が代表的です。ストリーミング取得の場合、レスポンスの読み取り文字列の組み立て+UI反映を逐次行う必要があるため、フレームごとに進捗管理できるコルーチンがわかりやすいことが多いです。

コルーチン実装例

以下はUnityWebRequestを使った非常に簡略化したサンプルイメージです。実際にはAPIキーやエラーハンドリングなどを追加する必要があります。

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class ChatGPTStream : MonoBehaviour
{
    [SerializeField] private string openAIApiKey;
    [SerializeField] private string url = "https://api.openai.com/v1/chat/completions";
    
    public IEnumerator GetChatGPTResponse(string prompt)
    {
        // JSONボディの用意(model、messagesなどを含む)
        // stream=trueを必ず指定
        string requestBody = "{\"model\":\"gpt-3.5-turbo\",\"stream\":true,\"messages\":[{\"role\":\"user\",\"content\":\"" + prompt + "\"}]}";
        
        // リクエスト生成
        UnityWebRequest request = new UnityWebRequest(url, "POST");
        byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(requestBody);
        request.uploadHandler = new UploadHandlerRaw(bodyRaw);
        request.downloadHandler = new DownloadHandlerStream(); // カスタムのDownloadHandlerで継承実装
        request.SetRequestHeader("Content-Type", "application/json");
        request.SetRequestHeader("Authorization", "Bearer " + openAIApiKey);
        
        // リクエスト送信
        yield return request.SendWebRequest();
        
        if(request.result == UnityWebRequest.Result.ConnectionError || 
           request.result == UnityWebRequest.Result.ProtocolError)
        {
            Debug.LogError("Error: " + request.error);
            yield break;
        }

        // ダウンロードしたバイトデータを随時読み込む処理
        // ここを継続的に走らせ、1文字ずつテキスト化してUIに追加表示などを行う
        // 実装詳細はDownloadHandlerScriptを継承したクラスで行う
    }
}

DownloadHandlerScriptを継承するクラス内で、ReceiveDataなどをオーバーライドし、そこに受信したバイナリデータをテキストに変換・パースするロジックを組み込みます。ストリーミングAPIから届くJSONは、返答の途中にもチャンクが届くため、JSONパースのロジックを適切に組み込む必要があります。たとえば、中途半端に分割された文字列を繋ぎ合わせて完全なJSONオブジェクトを取得するしくみを自前で実装するケースもあるでしょう。

4. 表示するUIのデザイン

ストリーミングで1文字ずつ(あるいは単語ごと)テキストを更新するには、以下のような工夫が必要です。

  • UIテキストを随時更新
    TextTextMeshProtextプロパティをループで更新すると、タイピングのような効果を実現できる。
  • 音やアニメーション演出
    文字が出るたびにSEを再生したり、カーソル(>)アイコンを点滅させたりすると演出効果がアップ。
  • 一定のタイミングで改行やポーズを入れる
    ユーザーが読みやすい形で文章を表示したり、読み上げなどがあるなら文章単位で区切るなど工夫を加える。

5. 開発・デバッグ時のポイント

  • APIキーの管理
    リポジトリにAPIキーをハードコーディングしない。環境変数やScriptableObjectなどで安全に管理する。
  • タイムアウト・エラー処理
    ストリーミングが途中で途切れた場合にリトライするか、そのまま終了するかの設計を決めておく。
  • ログ出力でデバッグ
    とくにJSONが分割されて届くことに慣れていない場合、レスポンスをログに出すなどして状態を確認しよう。

こうした実装をしっかり行うことで、ユーザーはChatGPTが「まるで今考えながら答えているかのように」テキストがスラスラと流れてくる体験を得られます。
この技術を応用すれば、RPGの会話シーンやチュートリアル画面など、ゲームへの没入感を高める演出に役立てられるでしょう。

この記事を読んでもっと実践したいと感じたあなたへ

Unity開発を効率よく進めるためには、実践的なスキルと仲間との交流が欠かせません。
そんな方におすすめのステップが、下記の3つです。

1. 有料教材「どこでもUnity教室」でゲーム制作を短期マスター

  • 5日でシンプルなFPS完成
  • C#や最新のInputSystem、FPS実装まで網羅
  • Discord招待+サンプルプロジェクトDLもセット

Unity初心者でも最短5日で3D FPSが完成!今すぐ始める入門チュートリアルはこちら

https://zenn.dev/ryuryu_game/books/fd28de9d8e963a

2. 無料コミュニティで、疑問をすぐに解消&モチベーションUP

  • 初心者~中級者までOK
  • 質問サポートが充実
  • 学習仲間と切磋琢磨

Discordサーバー参加はこちら

https://discord.gg/5FwuKCacNy

3. “ゲーム開発所RYURYU”がトータルサポート

  • コナラ総販売200件超
  • VR/AR/AIなど最新技術にも精通
  • 多数の出展実績

ご相談・お問い合わせはこちら

https://coconala.com/users/1772507

本記事では、UnityでChatGPTからのレスポンスを1文字ずつ(あるいはチャンク単位で)受け取りながら表示するためのテクニックをご紹介しました。ゲーム要素の演出に組み込んだり、ユーザーが体感的に「チャットの相手(AI)が考えながら答えている」ように見せる効果を演出したり、さまざまなシチュエーションで活用できます。ぜひこの記事を参考に、ストリーミング技術を取り入れた魅力的なアプリやゲームを開発してみてください。

Discussion