using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class RTChatSample : MonoBehaviour
{
///
/// 聊天配置
///
[SerializeField] private ChatSetting m_ChatSettings;
#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 Animator m_Animator;
///
/// 语音模式,设置为false,则不通过语音合成
///
[Header("设置是否通过语音合成播放文本")]
[SerializeField] private bool m_IsVoiceMode = true;
///
/// AI回复结束之后,回调
///
public Action OnAISpeakDone;
#endregion
private void Awake()
{
m_CommitMsgBtn.onClick.AddListener(delegate { SendData(); });
InputSettingWhenWebgl();
}
#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 = "正在思考中...";
//切换思考动作
SetAnimator("state", 1);
}
///
/// 带文字发送
///
///
public void SendData(string _postWord)
{
if (_postWord.Equals(""))
return;
//添加记录聊天
m_ChatHistory.Add(_postWord);
//提示词
string _msg = _postWord;
//发送数据
m_ChatSettings.m_ChatModel.PostMsg(_msg, CallBack);
m_InputWord.text = "";
m_TextBack.text = "正在思考中...";
//切换思考动作
SetAnimator("state", 1);
}
///
/// 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] private GameObject m_VoiceTipPanel;
///
/// 录音的提示信息
///
[SerializeField] private Text m_RecordTips;
///
/// 处理录制的音频数据
///
///
public void AcceptClip(AudioClip _audioClip)
{
if (m_ChatSettings.m_SpeechToText == null)
return;
m_RecordTips.text = "正在进行语音识别...";
m_ChatSettings.m_SpeechToText.SpeechToText(_audioClip, DealingTextCallback);
}
///
/// 处理识别到的文本
///
///
private void DealingTextCallback(string _msg)
{
m_RecordTips.text = _msg;
StartCoroutine(SetTextVisible(m_RecordTips));
//自动发送
if (m_AutoSend)
{
SendData(_msg);
return;
}
m_InputWord.text = _msg;
}
private IEnumerator SetTextVisible(Text _textbox)
{
yield return new WaitForSeconds(3f);
_textbox.text = "";
}
#endregion
#region 语音合成
private void PlayVoice(AudioClip _clip, string _response)
{
m_AudioSource.clip = _clip;
m_AudioSource.Play();
Debug.Log("音频时长:" + _clip.length);
//开始逐个显示返回的文本
StartTypeWords(_response);
//切换到说话动作
SetAnimator("state", 2);
}
#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;
}
//切换到等待动作
SetAnimator("state", 0);
//回复结束
if (OnAISpeakDone != null)
{
OnAISpeakDone();
}
}
#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
private void SetAnimator(string _para, int _value)
{
if (m_Animator == null)
return;
m_Animator.SetInteger(_para, _value);
}
}