using System; using System.Collections; using UnityEngine; //using UnityEngine.Rendering.PostProcessing; /* 本类用于管理场景中所有狗的状态包括动画状态,随机数分配等 */ //[CreateAssetMenu(fileName = "DogInScene", menuName = "Scriptable Objects/DogInScene")] public class DogInScene //: ScriptableObject { //通用参数段 public DogProperty dogProperty; public GameObject gameObject { set; get; } public Animator animator; private Vector3 moveToLocation; public float moveSpeed; // 用来控制狗的移动速度 0 0.5跑,0.75快跑,1跳 //public string dogState; // 狗的状态代码分类通道,包括三大类使用道具(itemConsume),闲置(idle),训练(training),自由活动(interact)等 public DogState dogState = DogState.IDLE; // 喝水吃饭参数段 public DateTime drinkStartTime, eatStartTime; // 记录吃喝开始时间 public bool itemConsumeProgress = false; // 是否在吃和喝的进程中。如果是的话,跳过常规动画检测 public bool isMovingToBowl; // 随机动作参数段 public int randomFactor; public DateTime animationStartTime; // 记录上一个动画开始时间的,每个随机动作间隔至少30秒 private int activeIndex; // 动物的活动指数 public bool isMoving; // 动物正在移动,避免其他随机动作发生 public bool isSleeping; // 动物正在正在睡觉,避免触发其他动画 // 固定参数 private const float moveSpeedAdj = 0.025f; // interact training 相关的参数 public DateTime interactLastUpdate; // 上次交互指令时间 public bool isMovingToPlayer; // 是否在向玩家移动 public string interactAnimation = ""; // 交互动画 public DateTime interactAnimationStartTime; // 交互动画开始时间 #region 通用函数段 public void SetGameObject(GameObject gameObject) { this.gameObject = gameObject; this.animator = gameObject.GetComponent(); this.randomFactor = UnityEngine.Random.Range(0, 51); // 生成一个随机整数(0 到 50 之间),用于时间校验 Debug.Log(this.gameObject.name + "random factor is:" + randomFactor); } public DogInScene(DogProperty property) { this.dogProperty = property; this.activeIndex = (int)Math.Round((property.liveliness + property.intimate) * UnityEngine.Random.Range(0.3f, 0.7f)); this.isMoving = false; } public void RemoveZzzParticle(){ // 关闭狗的睡觉粒子特效 var zzzParticle = gameObject.transform.Find("zzzParticle").gameObject; if (zzzParticle != null) { zzzParticle.SetActive(false); } } #endregion #region interact交互函数段 // 启动交互行为准备过程 public void SetupInteract() { // 加载Interact animator controller,避免过于复杂的Animator Controller Animator animator = gameObject.GetComponent(); RuntimeAnimatorController animatorController = Resources.Load("Dog/AnimatorController/shibaInu/HomeDogInteractController"); if (dogProperty.breed == "shibaInu") { animatorController = Resources.Load("Dog/AnimatorController/shibaInu/HomeDogInteractController"); } animator.runtimeAnimatorController = animatorController; //this.dogState = "interact"; this.dogState = DogState.INTERACT; // 设置狗的状态为交互状态 this.interactLastUpdate = DateTime.Now; this.moveToLocation = new Vector3(0f, 0f, -3f); this.isMovingToPlayer = true; // 如果狗距离超出一定范围才开始移动 float distance = Vector3.Distance(gameObject.transform.position, moveToLocation); if (distance > 2.5f) { this.animator.SetTrigger("move"); // 切换为走路动画 this.animator.SetBool("isMoving", true); // 保持为走路动画 this.animator.SetFloat("moveSpeed", 0.5f); } else { this.animator.SetBool("isMoving", false); this.gameObject.transform.LookAt(new Vector3(0f, 1f, -8f)); this.isMovingToPlayer = false; } } public void MovetoPlayer() { // 如果距离目标小于0.5米就把速度调整为零 if (Vector3.Distance(moveToLocation, this.gameObject.transform.position) < 0.5f) { Debug.Log(this.gameObject.name + "current move speed:" + moveSpeed); this.SetMoveSpeed(0); Debug.Log(this.gameObject.name + "reduce move speed:" + moveSpeed); } // 如果狗距离到达重点就停止跑步动画 float distance = Vector3.Distance(gameObject.transform.position, moveToLocation); //Debug.Log(this.gameObject.name + "interact move to player distance:" + distance); if (distance > 2.5f) // 一定距离内就开始停下来,否则刹不住 { this.gameObject.transform.LookAt(moveToLocation); this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, dogProperty.runSpeed * (1 + moveSpeed) * 0.02f * moveSpeedAdj); // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应RM动画this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, dogProperty.runSpeed * (1 + moveSpeed) * 0.02f * moveSpeedAdj); // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应RM动画 } else { this.animator.SetBool("isMoving", false); this.gameObject.transform.LookAt(new Vector3(0f, 1f, -8f)); this.isMovingToPlayer = false; } } // 交互行为计时器 public bool InteractTimeout() { TimeSpan ts = new TimeSpan(); ts = DateTime.Now - this.interactLastUpdate; if (ts.TotalSeconds > 10) { Debug.Log("InteractTimeout:" + this.gameObject.name); //this.dogState = "idle"; this.dogState = DogState.IDLE; return true; } else { return false; } } // 交互动画行为计时器(暂时设定为6秒) // 考虑一下是否需要这个功能,如果不需要就删除 public void InteractAnimationTimeout() { TimeSpan ts = new TimeSpan(); ts = DateTime.Now - this.interactAnimationStartTime; if (ts.TotalSeconds > 6) { Debug.Log("InteractAnimationTimeout:" + this.gameObject.name); var animator = this.gameObject.GetComponent(); animator.SetBool(interactAnimation, false); } } public void ExitInteract() { // 结束交互行为,恢复原有的菜单 //this.dogState = "idle"; this.dogState = DogState.IDLE; // 恢复场景idle对应的Animator Controller Animator animator = gameObject.GetComponent(); RuntimeAnimatorController animatorController = Resources.Load("Dog/AnimatorController/shibaInu/HomeDogAnimatorController"); if (dogProperty.breed == "shibaInu") { animatorController = Resources.Load("Dog/AnimatorController/shibaInu/HomeDogAnimatorController"); } animator.runtimeAnimatorController = animatorController; this.RandomMove(); } // 狗播放问号的表情 public void PlayQuestionMark() { var questionMark = gameObject.transform.Find("QuestionMark").gameObject; if (questionMark != null) { var particleQuestionMark = questionMark.GetComponent(); if (particleQuestionMark != null) { particleQuestionMark.Play(); } } } #endregion #region 随机动作控制函数 // 随机选择宠物动作 public void IdleAnimation() { this.animationStartTime = DateTime.Now; this.animator.SetInteger("activeIndex", activeIndex); //Debug.Log("activeIndex:" + this.activeIndex); float randomIndex = UnityEngine.Random.Range(0, 1f); this.animator.SetFloat("randomIndex", randomIndex); //this.dogState = "idle"; this.dogState = DogState.IDLE; //Debug.Log("randomIndex:" + randomIndex); } public void SetMoveSpeed(float speed) { this.moveSpeed = speed; } // 宠物随机移动 public void RandomMove() { // 如果距离目标小于0.5米就把速度调整为零 if (Vector3.Distance(moveToLocation, this.gameObject.transform.position) < 0.5f) { //Debug.Log(this.gameObject.name + "current move speed:" + moveSpeed); this.SetMoveSpeed(0); //Debug.Log(this.gameObject.name + "reduce move speed:" + moveSpeed); } if (isMoving == false) { animationStartTime = DateTime.Now; // 设置动画开始时间 float x = UnityEngine.Random.Range(-5f, 5f); float z = UnityEngine.Random.Range(0f, 5f); this.moveToLocation = new Vector3(x, 0, z); //Debug.Log("move to location:" + x + ", " + z); this.isMoving = true; this.animator.SetTrigger("move"); this.animator.SetBool("isMoving", true); this.animator.SetFloat("moveSpeed", this.moveSpeed); } this.gameObject.transform.LookAt(moveToLocation); this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, dogProperty.runSpeed * (1 + moveSpeed) * 0.02f * moveSpeedAdj); // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应RM动画 //this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, (100 + dogProperty.runSpeed) * (1 + moveSpeed) * 0.02f * 0.015f); // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应IF动画 //Debug.Log("current position:" + gameObject.transform.position.x + "z:" + gameObject.transform.position.z); // 如果狗距离到达重点就停止跑步动画 float distance = Vector3.Distance(gameObject.transform.position, moveToLocation); if (distance < 0.1) { this.animator.SetBool("isMoving", false); //this.moveSpeed = 0.4f; this.isMoving = false; IdleAnimation(); } } public void Sleep() { this.animator.SetTrigger("sleep"); this.animator.SetBool("isSleeping", true); this.isSleeping = true; //this.dogState = "sleep"; this.dogState = DogState.SLEEP; var zzzParticle = gameObject.transform.Find("zzzParticle").gameObject; if (zzzParticle != null) { zzzParticle.SetActive(true); } } public void Listen() { //StopCoroutine(movingCoroutine); //this.animator.SetTrigger("listen"); this.animator.SetBool("isListening", true); this.animator.SetBool("isMoving", false); this.animator.SetBool("isBarking", false); this.animator.SetBool("isSleeping", false); this.isSleeping = false; // 主人呼叫可以唤醒狗 this.gameObject.transform.LookAt(new Vector3(0, 0, -6)); HomeController.playerCam.Priority = 10; HomeController.dogCam.Priority = 1; HomeController.lastCameraChange = DateTime.Now; //this.dogState = "listen"; this.dogState = DogState.LISTEN; } // 用来出来音频返回结果 //public void PostListenRequest(bool result) //{ // if (result) // { // // TODO 语音信息识别成功,狗狗语音适配得分最高的跑过来 // this.animator.SetBool("isListening", false); // } // else // { // this.animator.SetBool("isListening", false); // } // // TODO 根据返回结果设定focusdog // // focusdog 开启互动模式 // HomeController.dogsInScene[GameData.focusDog].dogState = "interact"; // HomeController.dogsInScene[GameData.focusDog].SetupInteract(); //} #endregion #region 喝水,吃食等道具消费函数 // 开始整个使用道具的流程 public void StartItemConsume(ItemGroup group) { GameObject bowl = GameObject.Find("Bowl_water"); // 先指定一个碗,编译通过 this.itemConsumeProgress = true; // 开启使用道具过程 //this.dogState = "itemConsume"; this.dogState = DogState.ITEM_CONSUME; if (group == ItemGroup.water) { bowl = GameObject.Find("Bowl_water"); // 开启整个喝水的进程 } if (group == ItemGroup.food) { bowl = GameObject.Find("Bowl_food"); // 开启整个吃食物的进程 } this.moveToLocation = bowl.transform.position; this.isMovingToBowl = true; this.animator.SetTrigger("move"); // 切换为走路动画 this.animator.SetBool("isMoving", true); // 保持为走路动画 this.animator.SetFloat("moveSpeed", this.moveSpeed); } public void MovetoBowl() { // 如果距离目标小于0.5米就把速度调整为零 if (Vector3.Distance(moveToLocation, this.gameObject.transform.position) < 0.5f) { Debug.Log(this.gameObject.name + "current move speed:" + moveSpeed); this.SetMoveSpeed(0); Debug.Log(this.gameObject.name + "reduce move speed:" + moveSpeed); } var vamUI = GameObject.Find("VoiceAndMenu"); if (vamUI != null) { vamUI.SetActive(false); } this.gameObject.transform.LookAt(moveToLocation); this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, dogProperty.runSpeed * (1 + moveSpeed) * 0.02f * moveSpeedAdj); // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应RM动画 //this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, (100+dogProperty.runSpeed) * (1 + moveSpeed) * 0.02f * 0.015f); // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应IF动画 //Debug.Log("current position:" + gameObject.transform.position.x + "z:" + gameObject.transform.position.z); // 如果狗距离到达重点就停止跑步动画 float distance = Vector3.Distance(gameObject.transform.position, moveToLocation); if (distance < 0.1) { this.animator.SetBool("isMoving", false); } } public IEnumerator DrinkAnimation() { this.animator.SetBool("isMoving", false); // 关闭移动动画 TimeSpan ts = new TimeSpan(); var targetBowl = GameObject.Find("Bowl_water"); // 摄像头看向水盆位置 HomeController.dogCam.m_LookAt = targetBowl.transform; HomeController.dogCam.Priority = 10; HomeController.playerCam.Priority = 1; while (ts.TotalSeconds < 10) { yield return new WaitForSeconds(0.25f); ts = DateTime.Now - this.drinkStartTime; //Debug.Log("结束饮水过程:" + ts.TotalSeconds); // 狗一致看向谁碰,确保就算被撞击后依然看向水盆 this.gameObject.transform.LookAt(targetBowl.transform.position); } // 播放10秒后结束饮水过程 this.animator.SetBool("isDrinking", false); // 摄像头恢复玩家视角 HomeController.dogCam.Priority = 1; HomeController.playerCam.Priority = 10; // 让水物消失 var water = GameObject.Find("Water"); water.transform.localPosition = new Vector3(-1, -10, -1); //var water = GameObject.Find("Water"); //water.SetActive(false); // 再等待几秒后让水盆消失 while (ts.TotalSeconds < 18) { yield return new WaitForSeconds(0.25f); ts = DateTime.Now - this.drinkStartTime; //Debug.Log("让水盆消失:" + ts.TotalSeconds); } targetBowl.transform.position = new Vector3(-1, -10, -1); // 将喝水碗回归原位 water.transform.localPosition = Vector3.zero; // 将食物回归原位 this.itemConsumeProgress = false; // 关闭整个道具使用的进程 //this.dogState = "idle"; this.dogState = DogState.IDLE; QuitItemConsume(); } public IEnumerator EatAnimation() { this.animator.SetBool("isMoving", false); // 关闭移动动画 TimeSpan ts = new TimeSpan(); var targetBowl = GameObject.Find("Bowl_food"); // 摄像头看向盆位置 HomeController.dogCam.m_LookAt = targetBowl.transform; HomeController.dogCam.Priority = 10; HomeController.playerCam.Priority = 1; while (ts.TotalSeconds < 10) { yield return new WaitForSeconds(0.25f); ts = DateTime.Now - this.eatStartTime; // 狗一致看向谁碰,确保就算被撞击后依然看向水盆 this.gameObject.transform.LookAt(targetBowl.transform.position); } // 播放10秒后结束吃狗粮过程 this.animator.SetBool("isEating", false); //Debug.Log(this.dogProperty.dog_name + "狗吃完了"); // 摄像头恢复玩家视角 HomeController.dogCam.Priority = 1; HomeController.playerCam.Priority = 10; // 让食物消失 var food = GameObject.Find("Food"); food.transform.localPosition = new Vector3(-1, -10, -1); //var water = GameObject.Find("Water"); //water.SetActive(false); // 再等待几秒后让饭盆消失 while (ts.TotalSeconds < 18) { yield return new WaitForSeconds(0.25f); ts = DateTime.Now - this.eatStartTime; //Debug.Log("让水盆消失:" + ts.TotalSeconds); } //Debug.Log(this.dogProperty.dog_name + "把碗放回去了"); targetBowl.transform.position = new Vector3(-1, -10, -1); // 将饭盆回归原位 food.transform.localPosition = Vector3.zero; // 将食物回归原位 this.itemConsumeProgress = false; // 关闭整个道具使用的进程 //this.dogState = "idle"; this.dogState = DogState.IDLE; QuitItemConsume(); } public void QuitItemConsume() { var uiPlaceholder = GameObject.Find("UI Placeholder"); var vamUI = uiPlaceholder.transform.Find("VoiceAndMenu").gameObject; vamUI.SetActive(true); this.moveSpeed = UnityEngine.Random.Range(0.3f, 0.6f); RandomMove(); } #endregion } // Change the accessibility of the DogState enum to public to match the accessibility of the field "dog_state". public enum DogState { ITEM_CONSUME, IDLE, TRAINING, INTERACT, SLEEP, LISTEN }