123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969 |
- using Cinemachine;
- using Newtonsoft.Json;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using Unity.Collections.LowLevel.Unsafe;
- using Unity.VisualScripting;
- using UnityEngine;
- using UnityEngine.InputSystem;
- using UnityEngine.Animations;
- /* 本代码控制室内场景
- * 控制宠物在Home场景动画
- * !!!特别注意:Dog Initializer 必须挂载在同一个组件下,并且必须在本组价下方。确保比本组件先执行
- * 主要调节参数在FixedUpdate代码段里面
- * 提示用户注册
- * SetDogsIsTrigger 正常模式下为true。交互模式和进食模式下为false。
- */
- public class HomeController : MonoBehaviour
- {
- public static HomeController Instance;
- public static List<DogInScene> dogsInScene = new List<DogInScene>();
- public static bool listenBreak = false; // 当按下说话按键后,所有狗停止行动,立刻切换到监听状态。
- public static CinemachineVirtualCamera playerCam, dogCam;
- public static DateTime lastCameraChange;
- private bool isSleepChecked = false; // 用于检测第一次睡眠检测是否执行完成
- // Start is called once before the first execution of Update after the MonoBehaviour is created
- private GameObject centerOfDogs;
- private SceneMode sceneMode = SceneMode.NORMAL; // 当前场景处在的模式
- //private bool isInteractMode = false; // 场景是否在交互状态
- private Vector2 previousPointerPosition = Vector2.zero; // 前一帧鼠标位置
- private GameObject interactDog; // 交互的狗
- float interactTime = 0f; // 交互时间
- //private bool isTrainingMode = false; // 是否在训练状态
- private string trainingContent = String.Empty; // 训练内容 _xx 对于language.json 0x开始提示 1x成功提示 2x失败提示
- private int totalTrainingTimes = 2; // 训练总次数
- private int currentTrainingTimes = 0; // 当前训练次数
- private string trainingDogId = ""; // 训练的狗id
- private bool isTrainingMsgShowed_1 = false; // 第一条是否已经显示训练提示
- private bool isTrainingMsgShowed_2 = false; // 第二条是否已经显示训练提示
- private bool isTrainingAnimationPlayed = false; // 训练动画是否已经播放
- private void Awake()
- {
- if (Instance == null)
- {
- Instance = this;
- //DontDestroyOnLoad(gameObject); // 必须关掉否则会导致原场景destroy不能执行
- }
- else
- {
- Destroy(gameObject);
- }
- }
- void Start()
- {
- Time.timeScale = 1; // 确保时间流逝正常
- dogsInScene.Clear(); // dogsInScene 是静态,每次启动要清空
- lastCameraChange = DateTime.Now;
- playerCam = GameObject.Find("VCam Player").GetComponent<CinemachineVirtualCamera>();
- dogCam = GameObject.Find("VCam Dog").GetComponent<CinemachineVirtualCamera>();
- centerOfDogs = GameObject.Find("CenterOfDogs");
- //InitialScene();
- StartCoroutine(InitialScene());
- }
- // Update is called once per frame
- void FixedUpdate()
- {
- if (SceneInitialCheck()) // 确保狗读取成功后执行代码
- {
- // 计算多只狗的中心位置,用于主摄像机瞄准
- centerOfDogs.transform.position = CenterOfDogs();
- if (!isSleepChecked) // 每次启动检测只进行一次是否进入睡眠
- {
- // 判断是否在睡觉时间
- DateTime dateTime = DateTime.Now;
- foreach (var dog in dogsInScene)
- {
- if (dateTime.Hour >= 22 || dateTime.Hour <= 5) // 深夜模式,狗默认在睡觉状态
- {
- dog.Sleep();
- }
- else if (dog.dogProperty.stamina <= 10) { dog.Sleep(); } // 狗体力太低了,进入睡觉模式
- else
- {
- dog.IdleAnimation();
- }
- }
- isSleepChecked = true;
- }
- #region 场景动画主循环
- // 检测狗是否被撞翻,如果是,立刻翻回来
- foreach (var dog in dogsInScene)
- {
- Quaternion curRotation = dog.gameObject.transform.rotation;
- if (curRotation.x != 0)
- {
- curRotation.x = 0;
- }
- if (curRotation.z != 0)
- {
- curRotation.z = 0;
- }
- dog.gameObject.transform.rotation = curRotation;
- }
- // 生成一个数据数用于随机开启动画,如果和狗的randomFactor相同就开启动画
- int sceneRandomFactor = UnityEngine.Random.Range(0, 51);
- // 检测是否有狗没有通过voiceCall训练,如果有,立刻进入训练模式
- if (sceneMode == SceneMode.NORMAL) // 这段代码用于在NORMAL场景下检测是否有狗进入训练模式
- {
- trainingContent = String.Empty;
- foreach (var dog in dogsInScene)
- {
- if (trainingContent != String.Empty) { break; } // 如果已经有狗进入训练模式,跳出循环
- if (!dog.dogProperty.voiceCallEnable)
- {
- trainingContent = "voiceCall";
- }
-
- if (trainingContent != String.Empty)
- {
- sceneMode = SceneMode.TRAINING;
- dog.RemoveZzzParticle();
- trainingDogId = dog.dogProperty.d_id;
- totalTrainingTimes = 2;
- currentTrainingTimes = 0;
- GameData.focusDog = dogsInScene.IndexOf(dog);
- //GameData.focusDog = UserProperty.GetDogIndexById(dog.dogProperty.d_id);
- dogsInScene[GameData.focusDog].SetupInteract();
- interactDog = dogsInScene[GameData.focusDog].gameObject;
- GameData.isVoiceTrainingToday = true;
- VoiceButtonOnlySwitch(true); // 交互模式下关闭其他菜单
- }
- }
- foreach (var dog in dogsInScene)
- {
- if (trainingContent != String.Empty) { break; } // 如果已经有狗进入训练模式,跳出循环
- if (dog.dogProperty.voiceCallEnable && !GameData.isVoiceTrainingToday)
- {
- if (dog.dogProperty.voiceCall >= 40 && dog.dogProperty.CommandTrainingPhase() < 4)
- {
- // 当狗的voiceCall大于等于40,进入第一阶段指令训练模式
- int random = UnityEngine.Random.Range(0, 100);
- if (GameTool.IntBetween(0, 25, random) && !dog.dogProperty.commandSit)
- {
- trainingContent = "commandSit";
- }
- else if (GameTool.IntBetween(25, 50, random) && !dog.dogProperty.commandStand)
- {
- trainingContent = "commandStand";
- }
- else if (GameTool.IntBetween(50, 75, random) && !dog.dogProperty.commandBark)
- {
- trainingContent = "commandBark";
- }
- else if (GameTool.IntBetween(75, 100, random) && !dog.dogProperty.commandLieDown)
- {
- trainingContent = "commandLieDown";
- }
- else
- {
- GameData.isVoiceTrainingToday = true;
- }
- }
- else if (dog.dogProperty.voiceCommand >= 40 && dog.dogProperty.CommandTrainingPhase() >= 4)
- {
- // 当狗的voiceCommand大于等于40并且完成第一阶段所有训练,进入第二阶段指令训练模式
- int random = UnityEngine.Random.Range(0, 100);
- if (GameTool.IntBetween(0, 20, random) && !dog.dogProperty.commandShake)
- {
- trainingContent = "commandShake";
- }
- else if (GameTool.IntBetween(20, 40, random) && !dog.dogProperty.commandTouch)
- {
- trainingContent = "commandTouch";
- }
- else if (GameTool.IntBetween(40, 60, random) && !dog.dogProperty.commandDeath)
- {
- trainingContent = "commandDeath";
- }
- else if (GameTool.IntBetween(60, 80, random) && !dog.dogProperty.commandTurnL)
- {
- trainingContent = "commandTurnL";
- }
- else if (GameTool.IntBetween(80, 100, random) && !dog.dogProperty.commandTurnR)
- {
- trainingContent = "commandTurnR";
- }
- }
- }
- if (trainingContent != String.Empty)
- {
- sceneMode = SceneMode.TRAINING;
- dog.RemoveZzzParticle();
- trainingDogId = dog.dogProperty.d_id;
- totalTrainingTimes = 2;
- currentTrainingTimes = 0;
- GameData.focusDog = dogsInScene.IndexOf(dog);
- //GameData.focusDog = UserProperty.GetDogIndexById(dog.dogProperty.d_id);
- dogsInScene[GameData.focusDog].SetupInteract();
- interactDog = dogsInScene[GameData.focusDog].gameObject;
- GameData.isVoiceTrainingToday = true;
- VoiceButtonOnlySwitch(true); // 交互模式下关闭其他菜单
- }
- }
- }
- if (this.sceneMode == SceneMode.TRAINING) // 这段代码控制场景进入训练模式
- {
- foreach (var dog in dogsInScene)
- {
- if (dog.dogState == DogState.INTERACT || dog.dogState == DogState.TRAINING)
- {
- dogCam.m_LookAt = dog.gameObject.transform; // 摄像机看向交互的狗
- dogCam.Priority = 10;
- // 单只狗在交互的状态控制代码
- if (dog.isMovingToPlayer)
- {
- dog.MovetoPlayer();
- }
- else
- {
- // 开始训练时让狗播放动画
- if (trainingContent != "voiceCall" && !isTrainingAnimationPlayed)
- {
- string command = trainingContent.Substring(7);
- dog.animator.SetTrigger(command);
- dog.animator.SetBool(command + "_status", true);
- isTrainingAnimationPlayed = true;
- }
- // 狗完成移动后,开始进入正式训练交互模式
- dog.dogState = DogState.TRAINING;
- if (!isTrainingMsgShowed_1 && !isTrainingMsgShowed_2 && currentTrainingTimes == 0)
- {
- string msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", trainingContent + "_00", EnviromentSetting.languageCode });
- if (msg.Contains("<<dog_name>>"))
- {
- msg = msg.Replace("<<dog_name>>", dog.dogProperty.dog_name);
- }
- MessageBoxController.ShowMessage(msg);
- var BGM = GameObject.Find("BGM");
- if (BGM != null)
- {
- FadeBGM(BGM.GetComponent<AudioSource>(), false);
- }
- isTrainingMsgShowed_1 = true;
- }
- else if (!isTrainingMsgShowed_2 && isTrainingMsgShowed_1 && currentTrainingTimes == 1)
- {
- string msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", trainingContent + "_01", EnviromentSetting.languageCode });
- if (msg.Contains("<<dog_name>>"))
- {
- msg = msg.Replace("<<dog_name>>", dog.dogProperty.dog_name);
- }
- MessageBoxController.ShowMessage(msg);
- isTrainingMsgShowed_2 = true;
- }
- }
- }
- else
- {
- // 暂时将其他非训练状态的狗game object隐藏
- //dog.gameObject.SetActive(false);
- }
- }
- }
- else if (sceneMode == SceneMode.INACTIVE) // 这段代码控制场景在交互模式
- {
- foreach (var dog in dogsInScene)
- {
- if (dog.dogState == DogState.INTERACT)
- {
- dogCam.m_LookAt = dog.gameObject.transform; // 摄像机看向交互的狗
- dogCam.Priority = 10;
- // 单只狗在交互的状态控制代码
- if (dog.isMovingToPlayer)
- {
- dog.MovetoPlayer();
- }
- else if (dog.InteractTimeout()) // 如果交互时间结束,结束交互状态
- {
- dog.ExitInteract();
- sceneMode = SceneMode.NORMAL; // 交互结束,退出交互状态
- //isInteractMode = false; // 交互结束,退出交互状态
- VoiceButtonOnlySwitch(false); // 交互结束,打开其他菜单
- }
- else
- {
- PointerOnDog(); // 检测是否点击在狗上
- }
- }
- }
- }
- else
- {
- // 普通场景下的控制代码
- foreach (var dog in dogsInScene)
- {
- // 如果在eat drink进程结束前不执行随机场景代码
- // 恢复因为交互,训练模式隐藏的狗
- //if (dog.gameObject.activeSelf == false)
- //{
- // dog.gameObject.SetActive(true);
- //}
- if (dog.dogState == DogState.ITEM_CONSUME)
- {
- if (dog.isMovingToBowl)
- {
- dog.MovetoBowl();
- }
- }
- else
- {
- // 随机动作控制控制
- RandomCameraChange();
- if (listenBreak) // 如果用户按下说话按键,立刻切换到监听状态
- {
- // dog.Listen();
- StartCoroutine(dog.RotationToPlayerAndListen());
- }
- else if (dog.isMoving)
- {
- dog.RandomMove();
- }
- else if (sceneRandomFactor == dog.randomFactor && !dog.isSleeping) // 当狗自身的随机数和系统随机数相同时候触发。约100秒触发一次。
- {
- TimeSpan ts = DateTime.Now - dog.animationStartTime;
- if (ts.Seconds >= 30) // 如果距离上一个动作超过30秒就可以开始新的动作
- {
- float r = UnityEngine.Random.Range(0, 1f);
- if (r > 0.6) // 随机选择开始动画,或者移动
- {
- dog.IdleAnimation();
- }
- else // 狗狗开始步行移动
- {
- dog.SetMoveSpeed(0);
- dog.moveSpeed = 0;
- dog.RandomMove();
- }
- }
- }
- }
- }
- }
- #endregion
- }
- }
- private void OnDestroy()
- {
- Debug.Log("Home scene is destoried.");
- }
- IEnumerator InitialScene()
- {
- yield return null; // 跳过三帧,初始化最多三只狗
- //Debug.Log(isInitialDone);
- foreach (var dog in UserProperty.dogs)
- {
- DogInScene dogInScene = new DogInScene(dog);
- float x = UnityEngine.Random.Range(-1f, 1f); // 随机生成位置,考虑到手机评估宽度限制宽度
- float z = UnityEngine.Random.Range(0f, 5f); // 随机生成位置,考虑且保持和用户距离
- float y = UnityEngine.Random.Range(90f, 270f); // 随机生成朝向,且面向用户
- var initPosition = new Vector3(x, 0, z);
- StartCoroutine(DogComponentInstaller(dog)); // 加载狗的其他组件
- var dogGameObject = GameObject.Find(dog.dog_name);
- if (dogGameObject == null)
- {
- Debug.Log(dog.dog_name + "is not found in Home Controller");
- }
- dogGameObject.transform.position = initPosition;
- dogGameObject.transform.rotation = Quaternion.Euler(0, y, 0);
- dogGameObject.transform.localScale = new Vector3(2, 2, 2);
- dogInScene.SetGameObject(dogGameObject);
- dogsInScene.Add(dogInScene);
- }
- }
- // 加载狗的其他组件
- IEnumerator DogComponentInstaller(DogProperty dogProperty)
- {
- // 等待一帧,确保所有 Start() 方法都执行完成
- yield return null;
- // 第一帧以后开始执行
- GameObject dog = GameObject.Find(dogProperty.dog_name);
- // 加载指定的Animator controller
- Animator animator = dog.GetComponent<Animator>();
- RuntimeAnimatorController animatorController = Resources.Load<RuntimeAnimatorController>("Dog/AnimatorController/shibaInu/HomeDogAnimatorController");
- if (dogProperty.breed == "shibaInu") { animatorController = Resources.Load<RuntimeAnimatorController>("Dog/AnimatorController/shibaInu/HomeDogAnimatorController"); }
- animator.runtimeAnimatorController = animatorController;
- // 加载Rigidbody
- Rigidbody rigidbody = dog.AddComponent<Rigidbody>();
- //rigidbody.isKinematic = true;
- rigidbody.mass = 10;
- rigidbody.linearDamping = 10;
- rigidbody.angularDamping = 10;
- //rigidbody.freezeRotation = true;
- rigidbody.constraints = RigidbodyConstraints.FreezePositionY | RigidbodyConstraints.FreezeRotation;
- rigidbody.interpolation = RigidbodyInterpolation.Interpolate;
- rigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;
- // 加载box collider
- BoxCollider boxCollider = dog.AddComponent<BoxCollider>();
- boxCollider.isTrigger = false;
- boxCollider.center = new Vector3(0, 0.25f, 0);
- boxCollider.size = new Vector3(0.12f, 0.45f, 0.54f);
- boxCollider.isTrigger = true;
- // 加载Particle Question Mark
- ParticleSystem questionMarkParticle = Resources.Load<ParticleSystem>("Home/Particle_QuestionMark");
- questionMarkParticle = Instantiate(questionMarkParticle);
- questionMarkParticle.name = "QuestionMarkParticle";
- questionMarkParticle.transform.SetParent(dog.transform);
- questionMarkParticle.transform.localPosition = new Vector3(0, 0.4f, 0.4f);
- questionMarkParticle.transform.localRotation = Quaternion.Euler(-90, 0, 0);
- ParticleSystem ps = questionMarkParticle.GetComponent<ParticleSystem>();
- ps.Stop();
- // 加载sleep particle
- ParticleSystem zzzParticle = Resources.Load<ParticleSystem>("Home/Particle_Z");
- zzzParticle = Instantiate(zzzParticle);
- zzzParticle.name = "zzzParticle";
- zzzParticle.transform.SetParent(dog.gameObject.transform);
- zzzParticle.transform.localPosition = new Vector3(0.05f, 0.2f, 0.2f);
- zzzParticle.transform.localRotation = Quaternion.Euler(-90, 0, 0);
- zzzParticle.gameObject.SetActive(false); // 默认关闭
- // 添加DogCollisionController
- DogCollisionController dogCollisionController = dog.AddComponent<DogCollisionController>();
- //yield return null;
- }
-
- #region 语音控制区
- // 用户语音呼唤上传,Voice call指令用于呼唤所有的狗,得分最高的过来进入交互模式
- public void VoiceCallRequest(string filePath)
- {
- Debug.Log("Voice Call Post request");
- string url = "/api/voice/call/";
- WWWForm form = new();
- form.AddField("user_id", UserProperty.userId);
- StartCoroutine(WebController.PostRequest(url, form, filePath, callback: VoiceCallCallback));
- }
- // 语音呼唤上传回调函数
- void VoiceCallCallback(string json)
- {
- Debug.Log("Voice call callback");
- var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
- if (data != null && data["status"].ToString() == "success")
- {
- // 刷新狗的数据
- string dogJson = data["dogs"].ToString();
- UserProperty.FreshDogInfo(dogJson);
- // TODO 根据返回结果设定focusdog
- float highestScore = 0;
- string highestScoreDogId = String.Empty;
- var scores = data["call Score MFCC"].ToString();
- var scoresList = JsonConvert.DeserializeObject<Dictionary<string, float>>(scores);
- foreach (var score in scoresList)
- {
- // 根据狗的数量度修正得分。计算方式为狗的voiceCall属性值/1000
- int dogIndex = UserProperty.GetDogIndexById(score.Key);
- if (dogIndex < 0)
- {
- continue;
- }
- float scoreFactor = UserProperty.dogs[dogIndex].voiceCall / 1000f;
- float adjScore = score.Value + scoreFactor;
- if (adjScore > 1)
- {
- adjScore = 1;
- }
- if (adjScore > highestScore)
- {
- highestScore = adjScore;
- highestScoreDogId = score.Key;
- }
- }
- if (highestScore >= EnviromentSetting.voiceRecognitionScore) // 60分以上才可以进入交互模式
- {
- GameData.focusDog = UserProperty.GetDogIndexById(highestScoreDogId);
- sceneMode = SceneMode.INACTIVE; // 交互模式
- VoiceButtonOnlySwitch(true); // 交互模式下关闭其他菜单
- foreach (var dog in dogsInScene)
- {
- if (dog.dogProperty.d_id == highestScoreDogId)
- {
- // if (GameTool.Random100Check(dog.dogProperty.voiceCall))
- // {
- // dog.SetupInteract();
- interactDog = dog.gameObject;
- // focusdog 开启互动模式
- // HomeController.dogsInScene[GameData.focusDog].dogState = DogState.INTERACT;
- HomeController.dogsInScene[GameData.focusDog].SetupInteract();
- // 其他狗进入隐藏模式(先保留代码)
- //foreach (var otherDog in dogsInScene)
- //{
- // if (otherDog.dogProperty.d_id != highestScoreDogId)
- // {
- // otherDog.gameObject.SetActive(false);
- // }
- //}
- }
- }
- HomeSoundEffectController.Instance.PlaySoundEffect(5);
- }
- else
- {
- HomeSoundEffectController.Instance.PlaySoundEffect(4);
- }
- }
- else
- {
- Debug.Log(data["message"]);
- }
- }
- // 用户语音呼唤上传,Voice call指令用于呼唤所有的狗,得分最高的过来进入交互模式
- public void VoiceCommandRequest(string filePath)
- {
- //Debug.Log("Voice Command Post request");
- if (sceneMode == SceneMode.INACTIVE)
- {
- Debug.Log("Voice Command Post request");
- string url = "/api/voice/command/";
- WWWForm form = new();
- form.AddField("dog_id", UserProperty.dogs[GameData.focusDog].d_id);
- form.AddField("user_id", UserProperty.userId);
- StartCoroutine(WebController.PostRequest(url, form, filePath, callback: VoiceCommandCallback));
- }
- else if (sceneMode == SceneMode.TRAINING)
- {
- //Debug.Log("current times before ++:" + this.currentTrainingTimes.ToString());
- this.currentTrainingTimes++;
- string url = "/api/voice/training/";
- WWWForm form = new();
- form.AddField("dog_id", UserProperty.dogs[GameData.focusDog].d_id);
- form.AddField("user_id", UserProperty.userId);
- form.AddField("voice_type", trainingContent);
- form.AddField("current_times", this.currentTrainingTimes);
- //Debug.Log("current times after ++:" + this.currentTrainingTimes.ToString());
- form.AddField("total_times", totalTrainingTimes);
- StartCoroutine(WebController.PostRequest(url, form, filePath, callback: VoiceCommandCallback));
- }
- }
- // 语音呼唤上传回调函数
- void VoiceCommandCallback(string json)
- {
- if (sceneMode == SceneMode.INACTIVE)
- {
- Debug.Log("Voice command callback");
- var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
- if (data != null && data["status"].ToString() == "success")
- {
- // 刷新狗的数据
- string dogJson = data["dogs"].ToString();
- UserProperty.FreshDogInfo(dogJson);
- // 找到得分最高的指令
- float highestScore = 0;
- string highestScoreCommand = "";
- string scores = data["commandScoreMFCC"].ToString();
- var scoresList = JsonConvert.DeserializeObject<Dictionary<string, float>>(scores);
- foreach (var score in scoresList)
- {
- if (score.Value > highestScore)
- {
- highestScore = score.Value;
- highestScoreCommand = score.Key;
- }
- }
- // 根据狗的voiceCommand属性值修正得分。计算方式为狗的voiceCommand属性值/1000
- highestScore += UserProperty.dogs[GameData.focusDog].voiceCommand / 1000f;
- if (highestScore > 1)
- {
- highestScore = 1;
- }
- Debug.Log("Highest score:" + highestScore.ToString());
- Debug.Log("Highest command:" + highestScoreCommand);
- dogsInScene[GameData.focusDog].ResetAnimationStatus(); // 重置狗的动画状态
- if (highestScore >= EnviromentSetting.voiceRecognitionScore)
- {
- string animationTrigger = highestScoreCommand.Substring(7);
- string animationBool = animationTrigger + "_status";
- var animator = dogsInScene[GameData.focusDog].gameObject.GetComponent<Animator>();
- if (highestScoreCommand == "commandBark")
- {
- DogBarkController.Instance.PlayDogBarkWithDelay(3); // 狗叫相应一下
- }
- else
- {
- HomeSoundEffectController.Instance.PlaySoundEffect(5);
- }
- //animator.SetTrigger(animationTrigger);
- animator.Play(animationTrigger);
- animator.SetBool(animationBool, true);
- // 交互动画执行一段时间后停止
- StartCoroutine(dogsInScene[GameData.focusDog].InteractAnimationCountDown());
- }
- else
- {
- HomeSoundEffectController.Instance.PlaySoundEffect(4);
- dogsInScene[GameData.focusDog].PlayQuestionMark();
- }
- }
- else
- {
- Debug.Log(data["message"]);
- }
- }
- else if (sceneMode == SceneMode.TRAINING)
- {
- Debug.Log("Voice training Callback");
- var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
- if (data != null && data["status"].ToString().ToLower() == "success")
- {
- if (data["message"].ToString().ToLower() == "pass")
- {
- // 刷新狗的数据,包含dogsInScene
- string dogJson = data["dogs"].ToString();
- UserProperty.FreshDogInfo(dogJson);
- var trainingDog = dogsInScene[GameData.focusDog];
- trainingDog.ReloadDogProperty(); // 刷新狗的数据
- // 成功后让狗子播放训练的动画
- if (trainingContent != "voiceCall")
- {
- string command = trainingContent.Substring(7);
- trainingDog.animator.SetTrigger(command);
- trainingDog.animator.SetBool(command + "_status", true);
- }
- string msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", trainingContent + "_10", EnviromentSetting.languageCode });
- if (msg.Contains("<<dog_name>>"))
- {
- msg = msg.Replace("<<dog_name>>", interactDog.name);
- }
- GameTool.PauseGameTime();
- MessageBoxController.ShowMessage(msg, ExitTrainingMode);
- this.sceneMode = SceneMode.NORMAL;
- VoiceButtonOnlySwitch(false); // 交互结束,打开其他菜单
- GameData.isVoiceTrainingToday = true; // 训练完成,设置为true
- string todayDate = System.DateTime.Now.ToString("yyyy-MM-dd");
- PlayerPrefs.SetString("lastTrainingDate", todayDate);
- PlayerPrefs.Save();
- }
- else if (data["message"].ToString() == "fail")
- {
- HomeSoundEffectController.Instance.PlaySoundEffect(4);
- string msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", trainingContent + "_20", EnviromentSetting.languageCode });
- if (msg.Contains("<<dog_name>>"))
- {
- msg = msg.Replace("<<dog_name>>", interactDog.name);
- }
- GameTool.PauseGameTime();
- MessageBoxController.ShowMessage(msg, RestartTraining);
- }
- }
- else
- {
- Debug.Log(data["message"]);
- if (EnviromentSetting.runEnv == "Release")
- {
- HomeSoundEffectController.Instance.PlaySoundEffect(4);
- string msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", trainingContent + "_20", EnviromentSetting.languageCode });
- if (msg.Contains("<<dog_name>>"))
- {
- msg = msg.Replace("<<dog_name>>", interactDog.name);
- }
- GameTool.PauseGameTime();
- MessageBoxController.ShowMessage(msg, RestartTraining);
- }
- }
- SetDogsIsTrigger(true);
- }
- }
- #endregion
- #region interact mode
- // 重置training相关参数
- private void ExitTrainingMode()
- {
- foreach (var dog in dogsInScene)
- {
- if (dog.dogProperty.d_id == trainingDogId)
- {
- dog.ExitInteract();
- }
- }
- trainingContent = String.Empty;
- totalTrainingTimes = 2;
- currentTrainingTimes = 0;
- trainingDogId = "";
- isTrainingMsgShowed_1 = false;
- isTrainingMsgShowed_2 = false;
- isTrainingAnimationPlayed = false;
- sceneMode = SceneMode.NORMAL; // 交互模式
- Debug.Log("Reset Training Mode Parameters");
- GameTool.ResumeGameTime();
- GameData.isVoiceTrainingToday = true; // 训练完成,设置为true
- var BGM = GameObject.Find("BGM");
- if (BGM != null)
- {
- FadeBGM(BGM.GetComponent<AudioSource>(), true);
- }
- }
- private void RestartTraining()
- {
- currentTrainingTimes = 0;
- isTrainingMsgShowed_1 = false;
- isTrainingMsgShowed_2 = false;
- Time.timeScale = 1f;
- }
- // 改变Voice And Menu 菜单形态
- public void VoiceButtonOnlySwitch(bool state)
- {
- // 交互时候关闭其他菜单
- var vamUI = GameObject.Find("VoiceAndMenu");
- if (vamUI != null)
- {
- var UIdocument = vamUI.transform.Find("UIDocument").gameObject;
- var voiceController = UIdocument.GetComponent<VoiceController>();
- voiceController.isCommandMode = state;
- }
- }
- // 检测是否点击在狗上
- void PointerOnDog()
- {
- //DetectTouchMethod();
- // 检查当前指针是否有效
- if (Pointer.current == null) return;
- // 获取当前指针的悬浮位置
- Vector2 pointerPosition = Pointer.current.position.ReadValue();
- var mainCamera = GameObject.Find("Camera").GetComponent<Camera>();
- Ray ray = mainCamera.ScreenPointToRay(pointerPosition);
- if (Physics.Raycast(ray, out RaycastHit hit))
- {
- //Debug.Log($"Clicked on: {hit.collider.gameObject.name}");
- // 射线检测起始点击是否在狗上
- if (hit.collider.gameObject == interactDog)
- {
- if (previousPointerPosition != pointerPosition)
- {
- interactTime += Time.deltaTime;
- Debug.Log("interactTime:" + interactTime);
- foreach (var dog in dogsInScene)
- {
- if (dog.gameObject == interactDog)
- {
- dog.interactLastUpdate = DateTime.Now;
- }
- }
- previousPointerPosition = pointerPosition;
- }
- }
- if (interactTime > 2.5) // 如果交互时间超过1秒,播放心形粒子效果
- {
- HeartParticlePlay();
- DogBarkController.Instance.PlayDogBarkWithDelay(1); // 狗叫相应一下
- }
- }
- }
- void HeartParticlePlay()
- {
- // 播放心形粒子效果
- var heartParticle = GameObject.Find("Particle Heart");
- heartParticle.GetComponent<ParticleSystem>().Play();
- interactTime = 0;
- }
- public void SetInteractDog(GameObject dog)
- {
- interactDog = dog;
- }
- #endregion
- #region 场景环境控制
- // 淡入或淡出背景音乐
- private void FadeBGM(AudioSource bgmSource, bool fadeIn, float duration = 2f)
- {
- // fadeIn: true表示淡入 false表示淡出
- if (bgmSource == null) return; // 如果没有 AudioSource,则直接返回
- StartCoroutine(FadeBGMCoroutine(bgmSource, fadeIn, duration));
- }
- private IEnumerator FadeBGMCoroutine(AudioSource bgmSource, bool fadeIn, float duration)
- {
- float elapsedTime = 0f;
- float startVolume = bgmSource.volume;
- float targetVolume = fadeIn ? 0.4f : 0f; // 淡入目标音量为1,淡出目标音量为0
- while (elapsedTime < duration)
- {
- bgmSource.volume = Mathf.Lerp(startVolume, targetVolume, elapsedTime / duration);
- elapsedTime += Time.deltaTime;
- yield return null;
- }
- bgmSource.volume = targetVolume; // 确保音量达到目标值
- if (!fadeIn)
- {
- bgmSource.Stop(); // 如果是淡出,停止播放
- }
- else
- {
- bgmSource.Play(); // 如果是淡入,开始播放
- }
- }
- // 设置场景模式
- public void SetSceneMode(SceneMode mode)
- {
- this.sceneMode = mode;
- }
- // 刷新dogInScene的狗数据
- public void RefreshDogInScene()
- {
- foreach (var dog in dogsInScene)
- {
- dog.ReloadDogProperty();
- }
- }
- // 场景随机切换镜头看向不同的狗
- void RandomCameraChange()
- {
- int delay = 10; // 延迟10秒执行一次
- TimeSpan ts = DateTime.Now - lastCameraChange;
- if (ts.TotalSeconds < delay) { return; }
- int dogCount = dogsInScene.Count;
- int r = UnityEngine.Random.Range(0, dogCount + 1);
- if (r < dogCount)
- {
- dogCam.m_LookAt = dogsInScene[r].gameObject.transform;
- dogCam.Priority = 10;
- playerCam.Priority = 1;
- }
- else
- {
- dogCam.Priority = 1;
- playerCam.Priority = 10;
- }
- lastCameraChange = DateTime.Now;
- }
- // 检测场景是否初始化完成
- bool SceneInitialCheck()
- {
- bool initDone = true;
- if (dogsInScene.Count == UserProperty.dogs.Count) // 检测是否所有狗都被加载
- {
- foreach (var dog in dogsInScene)
- {
- if (dog.gameObject.GetComponent<Animator>().runtimeAnimatorController == null)
- {
- initDone = false;
- }
- }
- }
- else
- {
- initDone = false;
- }
- //Debug.Log("Home scene initial status:"+initDone);
- return initDone;
- }
- // 计算多只狗的中心位置,用于主摄像机瞄准
- private Vector3 CenterOfDogs()
- {
- if (dogsInScene.Count == 0)
- {
- return Vector3.zero;
- }
- Vector3 center = Vector3.zero;
- foreach (var dog in dogsInScene)
- {
- center += dog.gameObject.transform.position;
- }
- center /= dogsInScene.Count;
- return center;
- }
- // 设置所有狗is trigger属性
- public void SetDogsIsTrigger(bool triggerSetting)
- {
- foreach ( var dog in dogsInScene)
- {
- BoxCollider boxCollider = dog.gameObject.GetComponent<BoxCollider>();
- if (boxCollider != null)
- {
- boxCollider.isTrigger = triggerSetting;
- }
- }
- }
- #endregion
- }
- public enum ItemGroup
- {
- FOOD,
- WATER
- }
- public enum SceneMode
- {
- TRAINING,
- INACTIVE,
- NORMAL,
- }
|