Sẽ mở trong thẻ mới
360VRSố hoá không gian thật
Nhận báo giá

Nº 516 · 05/11/2026

Hướng dẫn xây dựng NPC hội thoại AI trong Unity

Làm NPC AI trong Unity từng bước: kiến trúc STT, LLM, TTS, backend bảo mật API key, code C# gọi máy chủ, điều khiển hoạt ảnh và kiểm soát nội dung.

Hướng dẫn xây dựng NPC hội thoại AI trong Unity

Một NPC AI trong Unity gồm bốn khâu nối tiếp: nhận giọng nói và chuyển thành chữ (STT), gửi tới mô hình ngôn ngữ lớn (LLM) qua một máy chủ trung gian, nhận câu trả lời có cấu trúc, rồi phát giọng nói (TTS) kèm hoạt ảnh và khẩu hình. Điểm mấu chốt là không đặt API key trong ứng dụng, giới hạn phạm vi kiến thức của NPC và thiết kế để che độ trễ.

NPC AI trong Unity gồm những thành phần nào?

Minh hoạ các thành phần của NPC hội thoại AI: bộ não mô hình ngôn ngữ, tai nhận dạng giọng nói, miệng tổng hợp giọng và khung xương hoạt ảnh nối với nhân vật 3D
Bốn khối ghép nên một NPC biết nghe và đáp (minh hoạ AI)

Một NPC AI trong Unity là nhân vật 3D có “bộ não” là LLM, “tai” là STT, “miệng” là TTS và “cơ thể” là hệ thống hoạt ảnh của Unity. Bài NPC thông minh dùng LLM đã giải thích khái niệm và rủi ro; bài này đi vào cách lắp ráp cụ thể.

Định nghĩa — System prompt: Đoạn chỉ dẫn cố định gửi kèm mọi lượt hội thoại, mô tả vai trò, tính cách, phạm vi kiến thức và quy tắc trả lời của NPC. Người chơi không nhìn thấy nhưng nó định hình toàn bộ hành vi nhân vật.

Thành phần Vai trò Lựa chọn phổ biến Chạy ở đâu
STT (Speech-to-Text) Chuyển giọng người chơi thành chữ Dịch vụ đám mây, mô hình họ Whisper Đám mây hoặc trên thiết bị
LLM Hiểu câu hỏi, sinh câu trả lời API thương mại hoặc mô hình mở tự lưu trữ Backend
RAG Tra cứu tài liệu nội bộ Cơ sở dữ liệu vector Backend
TTS (Text-to-Speech) Chuyển chữ thành giọng nói Dịch vụ TTS có giọng tiếng Việt Đám mây hoặc thiết bị
Hoạt ảnh và khẩu hình Cử chỉ, biểu cảm, nhép môi Animator, blendshape, plugin lip-sync Unity

Bước 1: Thiết kế nhân vật và phạm vi hội thoại

Thiết kế nhân vật là trả lời rõ “NPC này là ai, biết gì, được làm gì và không được nói gì” trước khi viết mã.

  1. Mục tiêu:
    NPC giúp người dùng đạt điều gì? Ví dụ: hướng dẫn khách tham quan
    bảo tàng ảo
    , đóng vai khách hàng khó tính trong bài đào tạo bán hàng.
  2. Tính cách và giọng điệu:
    xưng hô thế nào, trang trọng hay thân mật, câu trả lời dài tối đa bao nhiêu.
  3. Phạm vi kiến thức:
    liệt kê chủ đề được nói và tài liệu nguồn.
  4. Danh sách hành động:
    các hoạt ảnh NPC được kích hoạt như chào, chỉ tay, gật đầu, dẫn đường.
  5. Ranh giới:
    chủ đề cấm, câu từ chối lịch sự, khi nào chuyển sang nhân viên thật.
  6. Kịch bản kiểm thử:
    30–50 câu hỏi mẫu, gồm cả câu cố tình “phá” để kiểm tra.

Ví dụ system prompt rút gọn cho một NPC hướng dẫn viên:

Bạn là Lan, hướng dẫn viên ảo của bảo tàng. Xưng "em", gọi khách là "anh/chị".
Chỉ trả lời về hiện vật, lịch sử và dịch vụ của bảo tàng dựa trên TÀI LIỆU được cung cấp.
Nếu không có thông tin, nói rằng em chưa có dữ liệu và gợi ý hỏi nhân viên.
Trả lời tối đa 3 câu. Luôn trả về JSON:
{"say": "...", "emotion": "neutral|happy|thinking|sorry", "action": "none|wave|point|nod"}

Bước 2: Dựng backend trung gian

Backend trung gian là máy chủ nằm giữa ứng dụng Unity và nhà cung cấp LLM, giữ API key, ghép system prompt, tra cứu tài liệu và kiểm tra đầu ra. Đây là bước không được bỏ qua trong sản phẩm thật.

Mọi chuỗi bí mật trong bản build Unity đều có thể bị trích xuất; backend còn cho phép đổi mô hình, chỉnh prompt mà không phải phát hành lại ứng dụng.

Backend tối thiểu cần làm: – Nhận npcId và lịch sử hội thoại từ client. – Ghép system prompt theo npcId, thêm đoạn tài liệu liên quan nếu dùng RAG. Xem cách xây RAG trong ứng dụng XR. – Gọi LLM, yêu cầu định dạng JSON (nhiều nhà cung cấp hỗ trợ chế độ đầu ra có cấu trúc). – Kiểm tra JSON hợp lệ, lọc nội dung, chuẩn hóa action theo danh sách cho phép. – Ghi log ẩn danh để cải thiện prompt.

Bước 3: Kết nối Unity với backend

Unity gửi lượt hội thoại tới backend bằng UnityWebRequest và nhận về JSON chứa lời thoại, cảm xúc và hành động. Script dưới đây dùng JsonUtility có sẵn, chạy được trên các phiên bản Unity phổ biến.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;

[Serializable] public class ChatMessage { public string role; public string content; }
[Serializable] public class ChatRequest { public string npcId; public List<ChatMessage> messages; }
[Serializable] public class NpcReply { public string say; public string emotion; public string action; }

public class NpcBrain : MonoBehaviour
{
    [SerializeField] private string endpoint = "https://api.example.com/npc/chat";
    [SerializeField] private string npcId = "huong-dan-vien-lan";
    [SerializeField] private int maxHistory = 10;

    private readonly List<ChatMessage> history = new List<ChatMessage>();
    public event Action<NpcReply> OnReply;

    public void Ask(string playerText)
    {
        StartCoroutine(SendRoutine(playerText));
    }

    private IEnumerator SendRoutine(string playerText)
    {
        history.Add(new ChatMessage { role = "user", content = playerText });
        if (history.Count > maxHistory)
            history.RemoveRange(0, history.Count - maxHistory);

        string body = JsonUtility.ToJson(new ChatRequest { npcId = npcId, messages = history });

        using (var req = new UnityWebRequest(endpoint, "POST"))
        {
            req.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(body));
            req.downloadHandler = new DownloadHandlerBuffer();
            req.SetRequestHeader("Content-Type", "application/json");
            req.timeout = 15;

            yield return req.SendWebRequest();

            if (req.result != UnityWebRequest.Result.Success)
            {
                OnReply?.Invoke(new NpcReply { say = "Xin lỗi, em chưa nghe rõ. Anh/chị hỏi lại giúp em nhé?", emotion = "sorry", action = "none" });
                yield break;
            }

            NpcReply reply = JsonUtility.FromJson<NpcReply>(req.downloadHandler.text);
            history.Add(new ChatMessage { role = "assistant", content = reply.say });
            OnReply?.Invoke(reply);
        }
    }
}

Một script khác lắng nghe OnReply để hiển thị phụ đề, gọi TTS và kích hoạt hoạt ảnh. Chỉ chấp nhận action nằm trong danh sách đã định nghĩa:

private static readonly HashSet<string> AllowedActions = new HashSet<string> { "wave", "point", "nod" };

private void HandleReply(NpcReply r)
{
    subtitle.text = r.say;
    if (AllowedActions.Contains(r.action)) animator.SetTrigger(r.action);
    animator.SetInteger("Emotion", EmotionToIndex(r.emotion));
}

Bước 4: Giọng nói, hoạt ảnh và xử lý độ trễ

Lập trình viên đeo tai nghe có micro thử nhấn để nói với NPC trong cảnh 3D, màn hình bên cạnh hiển thị dạng sóng và thanh thời gian để đo độ trễ phản hồi
Độ trễ quyết định người dùng có kiên nhẫn trò chuyện hay không

Giọng nói và hoạt ảnh quyết định NPC có “sống” hay không, còn độ trễ quyết định người dùng có kiên nhẫn trò chuyện hay không.

Thu giọng nói

Dùng chế độ nhấn-để-nói (push-to-talk) để tránh thu nhầm tạp âm. Lớp Microphone của Unity cho phép ghi âm, ví dụ Microphone.Start(null, false, 10, 16000) ghi tối đa 10 giây ở 16 kHz, tần số mẫu phổ biến cho STT. Sau đó chuyển dữ liệu âm thanh sang WAV và gửi tới dịch vụ STT. Trên kính VR, cần khai báo quyền micro theo yêu cầu của nền tảng.

Phát giọng và khẩu hình

Chọn giọng TTS tiếng Việt phù hợp vùng miền và tính cách nhân vật; bài AI giọng nói cho nhân vật ảo so sánh các hướng lựa chọn. Khẩu hình có thể dựa trên phân tích âm thanh thời gian thực (các plugin lip-sync) hoặc dữ liệu viseme do dịch vụ TTS trả về. Chi tiết xem AI lip-sync và biểu cảm khuôn mặt.

Che độ trễ

Kỹ thuật Cách làm Hiệu quả
Hoạt ảnh “đang nghĩ” NPC nghiêng đầu, gật nhẹ ngay khi người dùng dừng nói Người dùng biết hệ thống đang xử lý
Câu đệm Phát sẵn “Để em xem nào…” từ file âm thanh có sẵn Lấp khoảng lặng đầu tiên
Streaming Nhận câu trả lời theo từng đoạn, TTS câu đầu tiên ngay Giảm thời gian chờ cảm nhận
Câu trả lời ngắn Giới hạn 2–3 câu trong system prompt Giảm thời gian sinh và phát
Bộ nhớ đệm Lưu sẵn câu trả lời cho câu hỏi phổ biến Gần như tức thì

Góc kỹ thuật cho đội phát triển

Phần này tổng hợp các quyết định kiến trúc khi đưa NPC AI từ bản demo sang sản phẩm.

Quản lý ngữ cảnh: giữ cửa sổ N lượt gần nhất như mã mẫu, để backend tóm tắt lượt cũ thành “bộ nhớ dài hạn” ngắn gọn.

Đầu ra có cấu trúc: JsonUtility không hỗ trợ dictionary và yêu cầu khớp tên trường. Nếu cần JSON linh hoạt hơn, dùng gói Newtonsoft Json cho Unity. Luôn có nhánh xử lý khi JSON hỏng: hiển thị câu dự phòng thay vì để NPC “đơ”.

Streaming: để phát giọng sớm, backend có thể trả dữ liệu dạng Server-Sent Events hoặc WebSocket; phía Unity cần DownloadHandlerScript tùy biến hoặc thư viện WebSocket. Hãy cắt câu theo dấu chấm để gửi TTS từng câu.

Chạy trên thiết bị: với yêu cầu ngoại tuyến hoặc riêng tư cao, có thể chạy mô hình nhỏ ngay trên máy qua gói suy luận AI của Unity (Sentis, tên gọi có thể thay đổi theo phiên bản) hoặc thư viện bên thứ ba. Đánh đổi là chất lượng hội thoại và nhiệt độ thiết bị; tham khảo AI chạy trên kính XR.

Kiểm thử: chạy bộ câu hỏi mẫu tự động mỗi lần đổi prompt hoặc mô hình; giới hạn tần suất gọi theo người dùng để tránh lạm dụng chi phí.

Ứng dụng thực tế tại Việt Nam

Nhân viên ngân hàng đeo kính VR luyện xử lý khiếu nại với NPC đóng vai khách hàng, người hướng dẫn theo dõi trên máy tính, kịch bản đào tạo bằng NPC AI
Kịch bản minh hoạ: luyện tình huống khó với khách hàng ảo

NPC AI trong Unity đặc biệt hữu ích cho đào tạo và trải nghiệm thương hiệu tại Việt Nam, nơi nội dung cần tiếng Việt tự nhiên và kiến thức đặc thù. Các ví dụ dưới đây là kịch bản minh họa.

Đào tạo nhân viên ngân hàng, bán lẻ: NPC đóng vai khách hàng với nhiều tính cách khác nhau để nhân viên luyện xử lý khiếu nại. Sau mỗi phiên, backend chấm điểm theo tiêu chí do bộ phận đào tạo định nghĩa.

Bảo tàng và điểm du lịch ảo: NPC hướng dẫn viên trả lời câu hỏi về hiện vật trong tour ảo, có thể kết hợp với tour 360 như một lớp tương tác.

Lưu ý bối cảnh: cần thử nghiệm kỹ với giọng nói vùng miền và cách nói pha tiếng Anh, vì độ chính xác STT có thể khác nhau. Nếu dữ liệu hội thoại chứa thông tin cá nhân, hãy tham vấn chuyên gia pháp lý về quy định bảo vệ dữ liệu hiện hành.

Câu hỏi thường gặp (FAQ)

Có thể gọi API LLM trực tiếp từ Unity không?

Về kỹ thuật thì được, nhưng không nên cho sản phẩm phát hành vì API key có thể bị trích xuất từ bản build. Chỉ làm vậy trong bản thử nghiệm nội bộ.

NPC AI có chạy được trên kính VR độc lập không?

Có, theo mô hình client gọi backend qua mạng. Chạy toàn bộ trên kính khả thi với mô hình nhỏ nhưng chất lượng hội thoại hạn chế hơn và cần tối ưu nhiệt, pin.

Chi phí vận hành NPC AI tính thế nào?

Chủ yếu theo lượng token LLM, số phút STT và số ký tự TTS, cộng chi phí máy chủ. Mức cụ thể tùy nhà cung cấp và lưu lượng, chỉ nên coi ước tính ban đầu là tham khảo.

Làm sao để NPC không bịa thông tin?

Giới hạn phạm vi trong system prompt, cung cấp tài liệu nguồn qua RAG, yêu cầu NPC thừa nhận khi không biết và kiểm thử bằng bộ câu hỏi mẫu. Không có cách nào loại bỏ hoàn toàn rủi ro, nên cần giám sát định kỳ.

Nên dùng Unity hay Unreal cho NPC AI?

Cả hai đều làm được vì phần AI nằm chủ yếu ở backend. Chọn engine theo đội ngũ và nền tảng mục tiêu.

Kết luận

Xây NPC AI trong Unity không khó ở khâu gọi API, mà ở thiết kế nhân vật, kiến trúc backend an toàn, kiểm soát đầu ra và che độ trễ. Bắt đầu với một NPC, một phạm vi hẹp và bộ câu hỏi kiểm thử rõ ràng, rồi mở rộng dần. Nếu bạn đang cân nhắc đưa nhân vật hội thoại vào dự án đào tạo hay trải nghiệm thương hiệu, hãy liên hệ đội ngũ tư vấn để được đánh giá nhu cầu.

Tư vấn dự án · miễn phí

Kể cho chúng tôi về không gian của bạn.

Đội ngũ 360VR đánh giá nhu cầu, mục tiêu và ngữ cảnh sử dụng trước khi đề xuất giải pháp. Gói VR Tour hoàn thiện chỉ từ 10 triệu.

Nhận tư vấn

Chia sẻ

Biên soạn

· Ban biên tập 360VR · đội ngũ kỹ sư VR Tour, flycam 360° và bản đồ số với hơn 100 công trình. Thông tin thiết bị, giá chỉ mang tính tham khảo tại thời điểm đăng.