OpenAI Unity 연동

JJW·2025년 4월 14일

Unity

목록 보기
27/34

오늘은 OpenAI인 ChatGPT를 Unity에 연동하여 NPC와의 대화를 구현해보았습니다.


구현

1. API 키 생성

API 키 생성

OpenAPI Platform에 들어가서 Key를 생성한 뒤 비밀키를 복사합니다.


2. 코드 작성

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using TMPro;
using UnityEngine.UI;

public class ChatGPTConnector : MonoBehaviour
{
    public TMP_InputField inputField;
    public TMP_Text chatOutput;
    public Button sendButton;

    // OpenAPI 비밀 키
    [SerializeField] private string apiKey = "API-KEY";

    // NPC 성격
    [SerializeField] private NPCPersonality npcType;

    public enum NPCPersonality
    {
        Friendly,        // 친절한 성격
        Blunt,           // 무뚝뚝한 성격
        Humorous,        // 유머러스한 성격
        Wise             // 지혜로운 성격
    }

    void Start()
    {
        sendButton.onClick.AddListener(() => SendMessageToNPC(inputField.text));
    }

    public void SendMessageToNPC(string userMessage)
    {
        StartCoroutine(SendToOpenAI(userMessage));
    }

    /// <summary>
    /// OpenAPI 호출 
    /// </summary>
    /// <param name="message"></param>
    /// <returns></returns>
    IEnumerator SendToOpenAI(string message)
    {
        // https://api.openai.com/v1/chat/completions -> OpenAI의 최신 GPT 모델을 사용하여 채팅을 할 수 있는 엔드포인트
        string apiUrl = "https://api.openai.com/v1/chat/completions";

        // NPC 성격에 맞는 시스템 메시지 생성
        string systemMessage = GetNPCPersonalityMessage(npcType);

        // JSON 데이터 생성
        // GPT-4는 유료만 가능한 듯함
        string json = "{\"model\": \"gpt-3.5-turbo\", \"messages\": [{\"role\": \"system\", \"content\": \"" + systemMessage + "\"}, {\"role\": \"user\", \"content\": \"" + message + "\"}]}";

        using (UnityWebRequest request = new UnityWebRequest(apiUrl, "POST"))
        {
            byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(json);
            request.uploadHandler = new UploadHandlerRaw(bodyRaw);
            request.downloadHandler = new DownloadHandlerBuffer();

            // Content Type -> JSON 형식
            request.SetRequestHeader("Content-Type", "application/json");

            // Authorization -> API 키
            request.SetRequestHeader("Authorization", "Bearer " + apiKey);

            yield return request.SendWebRequest();

            if (request.result == UnityWebRequest.Result.Success)
            {
                var responseJson = request.downloadHandler.text;
                var response = JsonUtility.FromJson<ChatResponseWrapper>(responseJson);
                string npcReply = response.choices[0].message.content.Trim();
                chatOutput.text = $"\n{GetNpcName(npcType)} NPC: {npcReply}";
            }
            else
            {
                chatOutput.text += $"\nError: {request.responseCode} - {request.error}\n{request.downloadHandler.text}";
            }
        }
    }

    // NPC 성격에 따른 특징 반환
    private string GetNpcName(NPCPersonality personality)
    {
        switch (personality)
        {
            case NPCPersonality.Friendly:
                return "친절한";
            case NPCPersonality.Blunt:
                return "무뚝뚝한";
            case NPCPersonality.Humorous:
                return "유머러스한";
            case NPCPersonality.Wise:
                return "지혜로운";
            default:
                return "";
        }
    }

    // NPC 성격에 맞는 메세지 반환
    private string GetNPCPersonalityMessage(NPCPersonality personality)
    {
        switch (personality)
        {
            case NPCPersonality.Friendly:
                return "당신은 친절하고 도움이 되는 NPC입니다. 항상 공손하고 정중한 언어를 사용하세요.";
            case NPCPersonality.Blunt:
                return "당신은 직설적이고 무뚝뚝한 NPC입니다. 불필요한 인사 없이 간결하고 직설적인 방식으로 대답하세요.";
            case NPCPersonality.Humorous:
                return "당신은 유머러스한 NPC입니다. 상황이 진지하더라도 대답에 항상 유머를 섞어주세요.";
            case NPCPersonality.Wise:
                return "당신은 지혜로운 NPC입니다. 대답은 항상 깊고 사려 깊은 내용이어야 합니다.";
            default:
                return "당신은 중립적인 NPC입니다.";
        }
    }

    [System.Serializable]
    public class ChatResponseWrapper
    {
        public Choice[] choices;
    }

    [System.Serializable]
    public class Choice
    {
        public Message message;
    }

    [System.Serializable]
    public class Message
    {
        // 메세지를 보낸 주체 (시스템인지 유저인지 AI인지)
        public string role;
        public string content;
    }
}
  • 위 코드를 작성하고 빈 오브젝트에 추가해줍니다.
  • 저는 미리 성격을 설정하여 System으로 지정하였습니다.

3. 결제

"error":
{
"message": "You exceeded your current quota, please check your plan and billing details.",
"type": "insufficient_quota",
"param": null,
"code": "insufficient_quota"
}

CHAT GPT API 결제

  • 만약 이런 오류가 발생한다면 현재 할당량을 초과하였다는 의미인데
  • 저는 사용한 적이 없는데 해당 오류가 발생하여 찾아보니 CHAT GPT AI를 사용하려면 카드를 등록해야한다고 합니다.
  • 위 링크로 들어가셔서 결제하시면 됩니다. 기본 5달러는 들어갑니다.

4. 결과

친절한 NPC

무뚝뚝한 NPC

유머러스한 NPC

지혜로운 NPC

  • 각 성격에 맞게 메세지를 보내주고 OpenAIPlatform에서도 요청이 정상적으로 처리된 걸 확인할수 있습니다.

느낀 점

  • 대화형 NPC를 설정하려면 많이 다듬어야 하겠지만
    기본적인 연동 방법에 대해서는 알게된 것 같습니다.
    좀 더 다듬어서 게임의 설정에 맞는 NPC의 대화기능을 구현하고 싶네요
profile
Unity 게임 개발자를 준비하는 취업준비생입니다..

0개의 댓글