Health/Assets/_VoiceAssistant/AIChatTookit/Scripts/Chat/ChatSample.cs

380 lines
9.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using WebGLSupport;
public class ChatSample : MonoBehaviour
{
/// <summary>
/// 聊天配置
/// </summary>
[SerializeField] private ChatSetting m_ChatSettings;
public VoiceWakeUp voiceWakeUp;
#region UI定义
/// <summary>
/// 聊天UI窗
/// </summary>
[SerializeField] private GameObject m_ChatPanel;
/// <summary>
/// 输入的信息
/// </summary>
[SerializeField] public InputField m_InputWord;
/// <summary>
/// 返回的信息
/// </summary>
[SerializeField] private Text m_TextBack;
/// <summary>
/// 播放声音
/// </summary>
[SerializeField] private AudioSource m_AudioSource;
/// <summary>
/// 发送信息按钮
/// </summary>
[SerializeField] private Button m_CommitMsgBtn;
#endregion
#region
/// <summary>
/// 动画控制器
/// </summary>
[SerializeField] private CharacterAnimControlBase animControler;
/// <summary>
/// 语音模式设置为false,则不通过语音合成
/// </summary>
[Header("设置是否通过语音合成播放文本")]
[SerializeField] private bool m_IsVoiceMode = true;
#endregion
private void Awake()
{
m_CommitMsgBtn.onClick.AddListener(delegate { SendData(); });
RegistButtonEvent();
InputSettingWhenWebgl();
m_VoiceInputs.onRecordOver += AcceptClip;
}
private IEnumerator Start()
{
while (!voiceWakeUp.IsEnable)
{
yield return null;
}
voiceWakeUp.StartRecgnition(OnRecgnizedKeyWord);
}
void OnRecgnizedKeyWord(bool successed)
{
if(successed)
{
StartRecord();
}
}
#region
/// <summary>
/// webgl时处理支持中文输入
/// </summary>
private void InputSettingWhenWebgl()
{
#if UNITY_WEBGL
m_InputWord.gameObject.AddComponent<WebGLSupport.WebGLInput>();
#endif
}
/// <summary>
/// 发送信息
/// </summary>
public void SendData()
{
if (m_InputWord.text.Equals(""))
return;
//添加记录聊天
m_ChatHistory.Add(m_InputWord.text);
//提示词
string _msg = m_InputWord.text;
//发送数据
m_ChatSettings.m_ChatModel.PostMsg(_msg, CallBack);
m_InputWord.text = "";
m_TextBack.text = "正在思考中...";
//切换思考动作
animControler.Thinking();
}
/// <summary>
/// 带文字发送
/// </summary>
/// <param name="_postWord"></param>
public void SendData(string _postWord)
{
if (_postWord.Equals(""))
return;
//添加记录聊天
m_ChatHistory.Add(_postWord);
//提示词
string _msg = _postWord;
Debug.Log("玩家说:" + _postWord);
//发送数据
m_ChatSettings.m_ChatModel.PostMsg(_msg, CallBack);
m_InputWord.text = "";
m_TextBack.text = "正在思考中...";
//切换思考动作
animControler.Thinking();
}
/// <summary>
/// AI回复的信息的回调
/// </summary>
/// <param name="_response"></param>
private void CallBack(string _response)
{
_response = _response.Trim();
m_TextBack.text = "";
Debug.Log("收到AI回复"+ _response);
//记录聊天
m_ChatHistory.Add(_response);
if (!m_IsVoiceMode||m_ChatSettings.m_TextToSpeech == null)
{
//开始逐个显示返回的文本
StartTypeWords(_response);
return;
}
m_ChatSettings.m_TextToSpeech.Speak(_response, PlayVoice);
}
#endregion
#region
/// <summary>
/// 语音识别返回的文本是否直接发送至LLM
/// </summary>
[SerializeField] private bool m_AutoSend = true;
[SerializeField] RecordVoiceUI recordVoiceUI;
/// <summary>
/// 语音输入处理类
/// </summary>
[SerializeField] private AudioRecorder m_VoiceInputs;
//[SerializeField] private VoiceInputs m_VoiceInputs;
/// <summary>
/// 注册按钮事件
/// </summary>
private void RegistButtonEvent()
{
recordVoiceUI.onStartListen += StartRecord;
recordVoiceUI.onStopListen += StopRecord;
}
/// <summary>
/// 开始录制
/// </summary>
public void StartRecord()
{
animControler.SayHi();
m_VoiceInputs.StartRecordAudio();
}
/// <summary>
/// 结束录制
/// </summary>
public void StopRecord()
{
m_VoiceInputs.StopRecordAudio();
}
/// <summary>
/// 处理录制的音频数据
/// </summary>
/// <param name="_data"></param>
private void AcceptData(byte[] _data)
{
if (m_ChatSettings.m_SpeechToText == null)
return;
m_ChatSettings.m_SpeechToText.SpeechToText(_data, DealingTextCallback);
}
/// <summary>
/// 处理录制的音频数据
/// </summary>
/// <param name="_data"></param>
private void AcceptClip(AudioClip _audioClip,AudioRecorder.StopReason stopReason)
{
if (m_ChatSettings.m_SpeechToText == null)
return;
m_ChatSettings.m_SpeechToText.SpeechToText(_audioClip, DealingTextCallback);
}
/// <summary>
/// 处理识别到的文本
/// </summary>
/// <param name="_msg"></param>
private void DealingTextCallback(string _msg)
{
recordVoiceUI.SetRecordTips(_msg);
//自动发送
if (m_AutoSend)
{
SendData(_msg);
return;
}
m_InputWord.text = _msg;
}
#endregion
#region
private void PlayVoice(AudioClip _clip, string _response)
{
m_AudioSource.clip = _clip;
m_AudioSource.Play();
Debug.Log("音频时长:" + _clip.length);
//开始逐个显示返回的文本
StartTypeWords(_response);
//切换到说话动作
animControler.StartSpeek();
}
#endregion
#region
//逐字显示的时间间隔
[SerializeField] private float m_WordWaitTime = 0.2f;
//是否显示完成
[SerializeField] private bool m_WriteState = false;
/// <summary>
/// 开始逐个打印
/// </summary>
/// <param name="_msg"></param>
private void StartTypeWords(string _msg)
{
if (_msg == "")
return;
m_WriteState = true;
StartCoroutine(SetTextPerWord(_msg));
}
private IEnumerator SetTextPerWord(string _msg)
{
int currentPos = 0;
while (m_WriteState)
{
yield return new WaitForSeconds(m_WordWaitTime);
currentPos++;
//更新显示的内容
m_TextBack.text = _msg.Substring(0, currentPos);
m_WriteState = currentPos < _msg.Length;
}
//切换到等待动作
animControler.Idle();
}
#endregion
#region
//保存聊天记录
[SerializeField] private List<string> m_ChatHistory;
//缓存已创建的聊天气泡
[SerializeField] private List<GameObject> m_TempChatBox;
//聊天记录显示层
[SerializeField] private GameObject m_HistoryPanel;
//聊天文本放置的层
[SerializeField] private RectTransform m_rootTrans;
//发送聊天气泡
[SerializeField] private ChatPrefab m_PostChatPrefab;
//回复的聊天气泡
[SerializeField] private ChatPrefab m_RobotChatPrefab;
//滚动条
[SerializeField] private ScrollRect m_ScroTectObject;
//获取聊天记录
public void OpenAndGetHistory()
{
m_ChatPanel.SetActive(false);
m_HistoryPanel.SetActive(true);
ClearChatBox();
StartCoroutine(GetHistoryChatInfo());
}
//返回
public void BackChatMode()
{
m_ChatPanel.SetActive(true);
m_HistoryPanel.SetActive(false);
}
//清空已创建的对话框
private void ClearChatBox()
{
while (m_TempChatBox.Count != 0)
{
if (m_TempChatBox[0])
{
Destroy(m_TempChatBox[0].gameObject);
m_TempChatBox.RemoveAt(0);
}
}
m_TempChatBox.Clear();
}
//获取聊天记录列表
private IEnumerator GetHistoryChatInfo()
{
yield return new WaitForEndOfFrame();
for (int i = 0; i < m_ChatHistory.Count; i++)
{
if (i % 2 == 0)
{
ChatPrefab _sendChat = Instantiate(m_PostChatPrefab, m_rootTrans.transform);
_sendChat.SetText(m_ChatHistory[i]);
m_TempChatBox.Add(_sendChat.gameObject);
continue;
}
ChatPrefab _reChat = Instantiate(m_RobotChatPrefab, m_rootTrans.transform);
_reChat.SetText(m_ChatHistory[i]);
m_TempChatBox.Add(_reChat.gameObject);
}
//重新计算容器尺寸
LayoutRebuilder.ForceRebuildLayoutImmediate(m_rootTrans);
StartCoroutine(TurnToLastLine());
}
private IEnumerator TurnToLastLine()
{
yield return new WaitForEndOfFrame();
//滚动到最近的消息
m_ScroTectObject.verticalNormalizedPosition = 0;
}
#endregion
}