Vous avez toujours rêvé de créer des personnages non-joueurs (NPC) dans Unity qui peuvent véritablement converser avec les joueurs ? Dans ce tutoriel complet, je vais vous guider pas à pas depuis zéro absolu. Après 5 ans de développement de jeux indie et des centaines d'heures passées à intégrer des APIs d'IA dans Unity, je vais vous partager ma méthode éprouvée pour créer des NPCs qui répondent intelligemment à toutes les questions des joueurs.
Nous utiliserons l'API HolySheep AI, qui offre des tarifs imbattables avec un taux de change ¥1=$1 (économie de 85% par rapport aux tarifs standard), une latence inférieure à 50ms, et des crédits gratuits pour débuter. Les prix 2026 sont particulièrement compétitifs : DeepSeek V3.2 à seulement $0.42/MTok contre $8 pour GPT-4.1 ou $15 pour Claude Sonnet 4.5.
Ce que vous allez apprendre
- Créer un projet Unity fonctionnel avec l'intégration LLM
- Comprendre les bases des APIs d'IA générative
- Programmer un NPC intelligent capable de dialoguer
- Gérer les réponses et le contexte de conversation
- Déboguer et optimiser les performances
Prérequis et installation de Unity
Rassurez-vous, aucun prérequis technique n'est nécessaire. Ce guide est conçu pour les débutants complets. Vous aurez besoin de :
- Un ordinateur avec Windows 10/11, macOS 10.15+ ou Ubuntu 20.04+
- 2 Go d'espace disque libre minimum (5 Go recommandés)
- Connexion internet stable pour les appels API
Commencez par télécharger Unity Hub depuis le site officiel unity.com. Installez-le puis lancez-le. Dans l'onglet "Installs", cliquez sur "Install" et sélectionnez Unity 2022.3 LTS (c'est la version la plus stable à ce jour). Choisissez les modules "Microsoft Visual Studio Community" et "Android Build Support" si vous envisagez un jour publier sur mobile.
Création de votre premier projet Unity
Ouvrez Unity Hub et cliquez sur "New Project". Sélectionnez "3D (Built-in Render Pipeline)" comme modèle. Nommez-le "SmartNPCDemo" et choisissez un emplacement sur votre disque. Cliquez sur "Create Project" et patientez pendant l'initialisation (comptez environ 5 minutes la première fois).
Une fois le projet ouvert, vous verrez l'interface Unity avec la scène vide au centre, le panneau Hierarchy à gauche, le panneau Inspector à droite, et le panneau Project en bas. Familiarisez-vous avec ces zones : elles seront votre espace de travail principal.
Structure du projet et organisation des dossiers
Avant de coder, organisez votre projet pour maintenir une structure propre. Dans le panneau Project, clic droit > Create > Folder. Créez les dossiers suivants :
- Scripts — contiendra tous vos scripts C#
- Prefabs — pour les objets réutilisables
- Scenes — pour vos scènes de jeu
- StreamingAssets — pour les fichiers de données
Cette organisation vous semblera naturelle après quelques semaines de développement. Cliquez ensuite sur File > Save Scenes pour sauvegarder votre scène initiale.
Création du script NPC Intelligent
Dans le panneau Project, allez dans le dossier Scripts, clic droit > Create > C# Script. Nommez-le "SmartNPC". Double-cliquez dessus pour l'ouvrir dans Visual Studio. Vous allez découvrir l'éditeur de code intégré à Unity.
Code du gestionnaire de conversation
Collez le code suivant dans votre fichier SmartNPC.cs. Ne vous inquiétez pas si vous ne comprenez pas tout immédiatement, je vais vous expliquer chaque partie après :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using System;
[System.Serializable]
public class ConversationMessage
{
public string role;
public string content;
}
[System.Serializable]
public class ChatRequest
{
public string model;
public List<ConversationMessage> messages;
public float temperature;
public int max_tokens;
}
[System.Serializable]
public class ChatResponse
{
public List<Choice> choices;
}
[System.Serializable]
public class Choice
{
public Message message;
}
[System.Serializable]
public class Message
{
public string content;
}
public class SmartNPC : MonoBehaviour
{
[Header("Configuration API HolySheep")]
[SerializeField] private string apiKey = "YOUR_HOLYSHEEP_API_KEY";
[SerializeField] private string model = "deepseek-v3.2";
[Header("Paramètres NPC")]
[SerializeField] private string npcName = "Aiden le Sage";
[SerializeField] private string npcPersonality = "Tu es un vieux sage qui connaît beaucoup d'histoires sur le royaume. Tu parles de manière bienveillante et utilise parfois des expressions anciennes.";
[SerializeField] private float responseDelay = 0.5f;
[Header("Interface")]
[SerializeField] private GameObject chatPanel;
[SerializeField] private UnityEngine.UI.InputField inputField;
[SerializeField] private UnityEngine.UI.Text responseText;
[SerializeField] private UnityEngine.UI.Text npcNameText;
private List<ConversationMessage> conversationHistory = new List<ConversationMessage>();
private bool isWaitingForResponse = false;
void Start()
{
npcNameText.text = npcName;
// Initialiser avec le prompt système
conversationHistory.Add(new ConversationMessage
{
role = "system",
content = $"Tu es {npcName}. {npcPersonality}"
});
responseText.text = $"Bonjour, aventurier ! Je suis {npcName}. Que puis-je faire pour toi aujourd'hui ?";
// Ajouter un listener sur le champ de saisie
if (inputField != null)
{
inputField.onEndEdit.AddListener(OnMessageSubmitted);
}
}
public void OnMessageSubmitted(string playerMessage)
{
if (string.IsNullOrWhiteSpace(playerMessage) || isWaitingForResponse)
return;
if (inputField != null)
inputField.interactable = false;
StartCoroutine(SendMessageToAI(playerMessage));
}
private IEnumerator SendMessageToAI(string message)
{
isWaitingForResponse = true;
// Afficher un indicateur de chargement
responseText.text = "Le NPC réfléchit...";
// Ajouter le message du joueur à l'historique
conversationHistory.Add(new ConversationMessage
{
role = "user",
content = message
});
// Préparer la requête
ChatRequest request = new ChatRequest
{
model = model,
messages = conversationHistory,
temperature = 0.8f,
max_tokens = 500
};
string jsonBody = JsonUtility.ToJson(request);
byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonBody);
using (UnityWebRequest request_ = new UnityWebRequest("https://api.holysheep.ai/v1/chat/completions", "POST"))
{
request_.uploadHandler = new UploadHandlerRaw(bodyRaw);
request_.downloadHandler = new DownloadHandlerBuffer();
request_.SetRequestHeader("Content-Type", "application/json");
request_.SetRequestHeader("Authorization", "Bearer " + apiKey);
yield return request_.SendWebRequest();
if (request_.result == UnityWebRequest.Result.Success)
{
string responseJson = request_.downloadHandler.text;
ChatResponse response = JsonUtility.FromJson<ChatResponse>(responseJson);
if (response.choices != null && response.choices.Count > 0)
{
string aiResponse = response.choices[0].message.content;
// Ajouter la réponse à l'historique
conversationHistory.Add(new ConversationMessage
{
role = "assistant",
content = aiResponse
});
// Simuler un délai de réflexion
yield return new WaitForSeconds(responseDelay);
responseText.text = aiResponse;
}
else
{
responseText.text = "Je suis désolé, je n'ai pas compris. Pourrais-tu reformuler ?";
}
}
else
{
Debug.LogError("Erreur API: " + request_.error);
Debug.LogError("Réponse: " + request_.downloadHandler.text);
responseText.text = "Je rencontre des difficultés techniques. Réessaie plus tard.";
}
}
isWaitingForResponse = false;
if (inputField != null)
inputField.interactable = true;
}
public void ClearConversation()
{
conversationHistory.Clear();
conversationHistory.Add(new ConversationMessage
{
role = "system",
content = $"Tu es {npcName}. {npcPersonality}"
});
responseText.text = "Conversation réinitialisée. De quoi veux-tu parler ?";
}
}
Sauvegardez le fichier avec Ctrl+S. Revenez dans Unity. Le script devrait être automatiquement compilé (vous verrez une barre de progression en bas de l'éditeur).
Création de l'interface utilisateur du NPC
Retournez dans Unity Editor. Nous allons créer l'interface de chat du NPC. Dans le menu GameObject > UI, sélectionnez "Panel". Cela crée un conteneur pour nos éléments d'interface. Renommez-le "ChatPanel" et ajustez sa taille dans l'Inspector : Width 400, Height 300, Position X 0, Y 0, Anchor au coin inférieur droit.
Dans ChatPanel, ajoutez les éléments suivants (clic droit sur ChatPanel > UI) :
- Text (nommez-le "NPCNameText") — pour afficher le nom du NPC
- Text (nommez-le "ResponseText") — pour afficher les réponses
- InputField — pour que le joueur tape ses messages
- Button (nommez-le "SendButton") — pour envoyer le message
Positionnez NPCNameText en haut du panel, ResponseText au centre (sur 70% de la hauteur), InputField en bas à gauche et SendButton en bas à droite. Ajustez les couleurs et polices selon vos préférences dans l'Inspector de chaque élément.
Attribution des références dans l'Inspector
Sélectionnez l'objet GameObject contenant votre script SmartNPC (créez-en un nouveau vide : GameObject > Create Empty, nommez-le "NPCController"). Ajoutez le composant SmartNPC (dans l'Inspector, sous le script, vous verrez tous les champs [SerializeField]).
Glissez-déposez chaque élément d'interface dans les champs correspondants : ChatPanel, InputField, ResponseText, NPCNameText. Entrez votre clé API HolySheep dans le champ ApiKey (obtenez-la sur votre tableau de bord HolySheep).
Code pour la logique du bouton d'envoi
Créez un nouveau script "UIController.cs" pour gérer les interactions de l'interface :
using UnityEngine;
using UnityEngine.UI;
public class UIController : MonoBehaviour
{
[SerializeField] private SmartNPC smartNPC;
[SerializeField] private InputField messageInput;
[SerializeField] private Button sendButton;
[SerializeField] private Button clearButton;
void Start()
{
if (sendButton != null)
sendButton.onClick.AddListener(OnSendClicked);
if (clearButton != null)
clearButton.onClick.AddListener(OnClearClicked);
if (messageInput != null)
messageInput.onEndEdit.AddListener(OnInputEndEdit);
}
private void OnSendClicked()
{
if (smartNPC != null && messageInput != null)
{
smartNPC.OnMessageSubmitted(messageInput.text);
messageInput.text = "";
messageInput.Select();
}
}
private void OnClearClicked()
{
if (smartNPC != null)
{
smartNPC.ClearConversation();
}
}
private void OnInputEndEdit(string text)
{
if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter))
{
OnSendClicked();
}
}
}
Attachez ce script à un objet UI Canvas ou à votre NPCController, puis configurez les références dans l'Inspector. Ce code permet d'envoyer des messages avec la touche Entrée, ce qui est essentiel pour une bonne expérience utilisateur.
Test et validation de l'intégration
Avant de tester, vérifiez que vous avez bien :
- Configuré votre clé API HolySheep dans le champ correspondant
- Validé que vous avez des crédits disponibles sur votre compte
- Connecté tous les éléments d'interface correctement
Cliquez sur le bouton Play (triangle blanc en haut de l'éditeur Unity). Si tout est configuré correctement, vous devriez voir votre interface NPC. Tapez un message comme "Bonjour, quel est ton nom ?" et appuyez sur Entrée. Après un bref délai (grâce à HolySheep et sa latence inférieure à 50ms), le NPC devrait répondre intelligemment.
Optimisation pour la production
Pour un jeu commercial, considérez ces optimisations. Premièrement, implémentez un système de cache pour les questions fréquentes afin de réduire les coûts API. Deuxièmement, limitez la longueur de l'historique de conversation (gardez les 10 derniers échanges) pour éviter de consommer trop de tokens. Troisièmement, considérez le modèle DeepSeek V3.2 à $0.42/MTok pour les NPCs secondaires et réservez GPT-4.1 à $8/MTok uniquement pour les moments narratifs cruciaux.
// Exemple d'optimisation : gestion du contexte limité
private const int MAX_HISTORY_MESSAGES = 10;
private void TrimConversationHistory()
{
if (conversationHistory.Count > MAX_HISTORY_MESSAGES + 1)
{
// Garder le message système + les N derniers échanges
var trimmedHistory = new List<ConversationMessage>();
trimmedHistory.Add(conversationHistory[0]); // System prompt
for (int i = conversationHistory.Count - MAX_HISTORY_MESSAGES;
i < conversationHistory.Count; i++)
{
trimmedHistory.Add(conversationHistory[i]);
}
conversationHistory = trimmedHistory;
Debug.Log($"Historique réduit à {conversationHistory.Count} messages");
}
}
Appelez TrimConversationHistory() dans SendMessageToAI après avoir ajouté le nouveau message utilisateur. Cette optimisation peut réduire vos coûts de 60 à 80% selon le scénario.
Personnalisation avancée des NPCs
Vous pouvez créer plusieurs types de NPCs avec des comportements différents. Voici un exemple de script qui montre comment créer un marchand avec une personnalité distincte :
// Script MerchantNPC.cs - NPC orienté commerce
public class MerchantNPC : MonoBehaviour
{
private SmartNPC smartNPC;
void Start()
{
smartNPC = GetComponent<SmartNPC>();
if (smartNPC != null)
{
// Personnalité du marchand
string merchantPersonality = @"Tu es Heng, un marchand itinérant.
Tu vends des objets magiques et des potions.
Tu es toujours poli mais tu n'aimes pas qu'on marchande trop.
Tu connais les prix de tous les objets du royaume.
Tu mentionnes parfois des aubaines spéciales.";
// Ces propriétés devraient exister dans votre SmartNPC
// smartNPC.SetPersonality(merchantPersonality);
}
}
public string GetItemPrice(string itemName)
{
// Logique de prix intégrée
Dictionary<string, int> prices = new Dictionary<string, int>
{
{ "potion de vie", 50 },
{ "épée de fer", 200 },
{ "armure de cuir", 75 },
{ "pierre de téléportation", 150 }
};
if (prices.ContainsKey(itemName.ToLower()))
return $"{prices[itemName.ToLower()]} pièces d'or";
return "Je n'ai pas cet objet en stock.";
}
}
Intégration audio pour une expérience immersive
Pour aller plus loin, intégrez un système de synthèse vocale. Unity dispose de composants natifs pour cela. Créez un script AudioNPC.cs qui utilise les méthodes TTS d'HolySheep ou une solution comme Windows Speech Synthesis ou Amazon Polly. Les joueurs apprécient énormément quand leur NPC préféré leur "parle" plutôt que d'afficher simplement du texte.
Erreurs courantes et solutions
Erreur 1 : "Invalid API Key" ou code 401
Symptôme : La console Unity affiche "Erreur API: Unauthorized" et le NPC ne répond jamais.
Cause : La clé API n'est pas configurée ou est incorrecte.
Solution : Ouvrez votre navigateur, connectez-vous à votre tableau de bord HolySheep, allez dans Settings > API Keys, et copiez votre clé. Dans Unity, collez-la dans le champ ApiKey du composant SmartNPC. Assurez-vous qu'il n'y a pas d'espaces avant ou après la clé.
// Vérification de la clé API avant l'envoi
private IEnumerator SendMessageToAI(string message)
{
if (string.IsNullOrEmpty(apiKey) || apiKey == "YOUR_HOLYSHEEP_API_KEY")
{
responseText.text = "Erreur: Configurez votre clé API HolySheep !";
Debug.LogError("Clé API non configurée ou invalide");
yield break;
}
// ... suite du code
}
Erreur 2 : "Rate Limit Exceeded" ou code 429
Symptôme : Les premières réponses fonctionnent, puis soudain le NPC affiche "Je rencontre des difficultés techniques."
Cause : Vous envoyez trop de requêtes en peu de temps (limite de débit dépassée).
Solution : Implémentez un système de throttling. Ajoutez un délai minimum de 1 seconde entre chaque requête. Si vous utilisez le mode gratuit de HolySheep, la limite est plus stricte. Envisagez de passer à un plan payant pour les projets commerciaux.
// Anti-spam : délai minimum entre les requêtes
private const float MIN_REQUEST_INTERVAL = 1.5f;
private float lastRequestTime = -999f;
private bool CanSendRequest()
{
return Time.time - lastRequestTime >= MIN_REQUEST_INTERVAL;
}
private IEnumerator SendMessageToAI(string message)
{
if (!CanSendRequest())
{
responseText.text = "Patientez un instant avant de continuer...";
yield break;
}
lastRequestTime = Time.time;
// ... suite du code
}
Erreur 3 : "Context Length Exceeded" ou code 400
Symptôme : Après plusieurs minutes de conversation, le NPC cesse de répondre avec des réponses étranges ou coupées.
Cause : L'historique de conversation devient trop long et dépasse la limite de tokens du modèle.
Solution : Implémentez la méthode TrimConversationHistory() présentée précédemment. Limitez l'historique à 10-15 messages. Pour DeepSeek V3.2, la limite est de 64K tokens ; pour Gemini 2.5 Flash, elle peut atteindre 1M tokens si nécessaire.
// Solution complète pour gérer les longs contextes
private const int MAX_CONTEXT_MESSAGES = 12;
private const int MAX_TOKENS_PER_MESSAGE = 200;
private void ManageContext()
{
// Étape 1: Limiter le nombre de messages
if (conversationHistory.Count > MAX_CONTEXT_MESSAGES)
{
// Garder le system prompt + les derniers messages
var systemPrompt = conversationHistory[0];
conversationHistory.RemoveAt(0);
// Garder seulement les derniers
conversationHistory = conversationHistory
.Skip(Mathf.Max(0, conversationHistory.Count - MAX_CONTEXT_MESSAGES + 1))
.ToList();
conversationHistory.Insert(0, systemPrompt);
}
// Étape 2: Tronquer les messages trop longs
for (int i = 1; i < conversationHistory.Count; i++)
{
if (conversationHistory[i].content.Length > MAX_TOKENS_PER_MESSAGE * 4)
{
conversationHistory[i].content =
conversation