using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using WebGLSupport;
public class ChatSample : MonoBehaviour
{
///
/// 聊天配置
///
[SerializeField] private ChatSetting m_ChatSettings;
public VoiceWakeUp voiceWakeUp;
#region UI定义
///
/// 聊天UI窗
///
[SerializeField] private GameObject m_ChatPanel;
///
/// 输入的信息
///
[SerializeField] public InputField m_InputWord;
///
/// 返回的信息
///
[SerializeField] private Text m_TextBack;
///
/// 播放声音
///
[SerializeField] private AudioSource m_AudioSource;
///
/// 发送信息按钮
///
[SerializeField] private Button m_CommitMsgBtn;
#endregion
#region 参数定义
///
/// 动画控制器
///
[SerializeField] private CharacterAnimControlBase animControler;
///
/// 语音模式,设置为false,则不通过语音合成
///
[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 消息发送
///
/// webgl时处理,支持中文输入
///
private void InputSettingWhenWebgl()
{
#if UNITY_WEBGL
m_InputWord.gameObject.AddComponent();
#endif
}
///
/// 发送信息
///
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();
}
///
/// 带文字发送
///
///
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();
}
///
/// AI回复的信息的回调
///
///
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 语音输入
///
/// 语音识别返回的文本是否直接发送至LLM
///
[SerializeField] private bool m_AutoSend = true;
[SerializeField] RecordVoiceUI recordVoiceUI;
///
/// 语音输入处理类
///
[SerializeField] private AudioRecorder m_VoiceInputs;
//[SerializeField] private VoiceInputs m_VoiceInputs;
///
/// 注册按钮事件
///
private void RegistButtonEvent()
{
recordVoiceUI.onStartListen += StartRecord;
recordVoiceUI.onStopListen += StopRecord;
}
///
/// 开始录制
///
public void StartRecord()
{
animControler.SayHi();
m_VoiceInputs.StartRecordAudio();
}
///
/// 结束录制
///
public void StopRecord()
{
m_VoiceInputs.StopRecordAudio();
}
///
/// 处理录制的音频数据
///
///
private void AcceptData(byte[] _data)
{
if (m_ChatSettings.m_SpeechToText == null)
return;
m_ChatSettings.m_SpeechToText.SpeechToText(_data, DealingTextCallback);
}
///
/// 处理录制的音频数据
///
///
private void AcceptClip(AudioClip _audioClip,AudioRecorder.StopReason stopReason)
{
if (m_ChatSettings.m_SpeechToText == null)
return;
m_ChatSettings.m_SpeechToText.SpeechToText(_audioClip, DealingTextCallback);
}
///
/// 处理识别到的文本
///
///
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;
///
/// 开始逐个打印
///
///
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 m_ChatHistory;
//缓存已创建的聊天气泡
[SerializeField] private List 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
}