Tutorial: Building Conversational NPCs in Unity 6 with MorVoice SDK (Zero-Latency Setup)
Le Graal du jeu vidéo moderne est le 'PNJ intelligent'. Mais la voix est restée un goulot d'étranglement.
Ce tutoriel vous montre comment implémenter le **SDK MorVoice Streaming** dans Unity 6. Nous atteindrons une latence de réponse vocale inférieure à 200ms.
Prérequis
- Unity 2022.3 LTS or higher (Unity 6 recommended)
- MorVoice SDK (Install via Package Manager: https://npm.morvoice.com)
- An API Key from dashboard.morvoice.com
- A basic NPC GameObject with an AudioSource componentArchitecture : Le pipeline de streaming
Ne sauvegardez PAS l'audio sur le disque. Le flux de données PCM passera directement du buffer WebSocket au buffer AudioSource.
Étape 1 : Le contrôleur vocal du PNJ
Créez un nouveau script `NPCVoiceController.cs` et attachez-le à votre personnage.
using UnityEngine;
using MorVoice.SDK;
using System.Collections;
public class NPCVoiceController : MonoBehaviour
{
[SerializeField] private string voiceId = "orc_warrior_v2";
private MorVoiceClient _client;
private AudioSource _audioSource;
void Start()
{
_client = new MorVoiceClient(ApiKey.LoadFromEnv());
_audioSource = GetComponent<AudioSource>();
}
public async void Speak(string text)
{
// 1. Start the stream. This returns immediately (active connection)
var stream = await _client.StreamSpeechAsync(text, voiceId);
// 2. Prepare a streaming AudioClip (Unity 2022+ feature)
var clip = AudioClip.Create("VoiceStream", 44100 * 60, 1, 44100, true,
(float[] data) => stream.ReadBuffer(data));
_audioSource.clip = clip;
_audioSource.Play();
}
}Étape 2 : Intégration de la synchronisation labiale
L'audio ne suffit pas, la bouche doit bouger. MorVoice envoie des événements 'viseme' pour les formes de bouche.
// Inside Speak() method, subscribe to viseme events
stream.OnViseme += (visemeCode, duration) => {
// Map MorVoice viseme codes to your character's BlendShapes
// Example: Code 4 = 'Ah' sound -> Set BlendShape 'MouthOpen' to 100
float intensity = 100f;
SkinnedMeshRenderer.SetBlendShapeWeight(visemeCode, intensity);
// Auto-close mouth after duration
StartCoroutine(ResetMouth(visemeCode, duration));
};Conseils d'optimisation
1. Pré-chargement de la connexion
Establish the WebSocket connection when the player enters the room, not when they start talking. This saves the initial SSL handshake time (approx 100ms).
2. Mise en cache des phrases courantes
Pour les réponses standards, générez-les une fois et mettez-les en cache localement.
Pièges courants
❌ NEVER call .ToArray() on the stream. That waits for the full audio to download.
✅ ALWAYS use the streaming callback or buffer reader.
❌ WARNING: Don't use standard HTTP requests. They block the main thread in WebGL builds.
✅ Use the async/await pattern shown above.Conclusion
Avec cette configuration, vos PNJ peuvent interrompre les joueurs et réagir aux événements en temps réel.
Download the complete Unity Project example from our GitHub repository.