HomeController.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using Unity.Collections.LowLevel.Unsafe;
  5. using Unity.VisualScripting;
  6. using UnityEditor.Animations;
  7. using UnityEngine;
  8. using UnityEngine.Rendering.PostProcessing;
  9. /* 本代码控制室内场景
  10. * 控制宠物在Home场景动画
  11. * !!!特别注意:Dog Initializer 必须挂载在同一个组件下,并且必须在本组价下方。确保比本组件先执行
  12. * 主要调节参数在FixedUpdate代码段里面
  13. */
  14. public class HomeController : MonoBehaviour
  15. {
  16. private List<DogInScene> dogsInScene = new List<DogInScene>();
  17. private List<Coroutine> existCouroutines;
  18. public static bool listenBreak = false; // 当按下说话按键后,所有狗停止行动,立刻切换到监听状态。
  19. private bool isInitialDone = false;
  20. // Start is called once before the first execution of Update after the MonoBehaviour is created
  21. void Start()
  22. {
  23. }
  24. // Update is called once per frame
  25. void FixedUpdate()
  26. {
  27. if (!isInitialDone)
  28. {
  29. InitialScene();
  30. // 判断是否在睡觉时间
  31. DateTime dateTime = DateTime.Now;
  32. foreach (var dog in dogsInScene)
  33. {
  34. if (dateTime.Hour >= 22 || dateTime.Hour <= 5) // 深夜模式,狗默认在睡觉状态
  35. {
  36. dog.Sleep();
  37. }
  38. else
  39. {
  40. dog.StartAnimation();
  41. }
  42. }
  43. isInitialDone = true;
  44. }
  45. // 生成一个数据数用于随机开启动画,如果和狗的randomFactor相同就开启动画
  46. int randomCheck = UnityEngine.Random.Range(0, 101);
  47. foreach (var dog in dogsInScene)
  48. {
  49. if (listenBreak) // 如果用户按下说话按键,立刻切换到监听状态
  50. {
  51. dog.Listen();
  52. }
  53. else if (dog.isMoving)
  54. {
  55. dog.Move();
  56. }
  57. else if (randomCheck == dog.randomFactor) // 当狗自身的随机数和系统随机数相同时候触发。约100秒触发一次。
  58. {
  59. TimeSpan ts = DateTime.Now - dog.animationStartTime;
  60. if (ts.Seconds >= 30) // 如果距离上一个动作超过30秒就可以开始新的动作
  61. {
  62. float r = UnityEngine.Random.Range(0, 1f);
  63. if (r > 0.6) // 随机选择开始动画,或者移动
  64. {
  65. dog.StartAnimation();
  66. }
  67. else // 狗狗开始步行移动
  68. {
  69. dog.SetMoveSpeed(0);
  70. dog.Move();
  71. }
  72. }
  73. }
  74. }
  75. }
  76. //void AniOrWalk(DogInScene dog) // 狗在普通状态下,随机或播放动画,或移动
  77. //{
  78. //}
  79. // 初始化场景,加载所有的狗,并配置components,添加到dogsInScene List里面去
  80. void InitialScene()
  81. {
  82. //
  83. foreach (var dog in UserProperty.dogs)
  84. {
  85. DogInScene dogInScene = new DogInScene(dog);
  86. float x = UnityEngine.Random.Range(-5f, 5f); // 随机生成位置
  87. float z = UnityEngine.Random.Range(-5f, 5f);
  88. float y = UnityEngine.Random.Range(0, 360f);
  89. var initPosition = new Vector3(x, 0, z);
  90. StartCoroutine(DogComponentAdd(dog)); // 加载狗的其他组件
  91. var dogGameObject = GameObject.Find(dog.name);
  92. dogGameObject.transform.position = initPosition;
  93. dogGameObject.transform.rotation = Quaternion.Euler(0, y, 0);
  94. dogGameObject.transform.localScale = new Vector3(2, 2, 2);
  95. dogInScene.SetGameObject(dogGameObject);
  96. dogsInScene.Add(dogInScene);
  97. }
  98. }
  99. // 加载狗的其他组件
  100. IEnumerator DogComponentAdd(DogProperty dogProperty)
  101. {
  102. // 等待一帧,确保所有 Start() 方法都执行完成
  103. yield return null;
  104. // 第一帧以后开始执行
  105. GameObject dog = GameObject.Find(dogProperty.name);
  106. // 加载指定的Animator controller
  107. Animator animator = dog.GetComponent<Animator>();
  108. AnimatorController animatorController = new AnimatorController();
  109. if (dogProperty.breed == "shibaInu") { animatorController = Resources.Load<AnimatorController>("Dog/AnimatorController/shibaInu/HomeDogAnimatorController"); }
  110. animator.runtimeAnimatorController = animatorController;
  111. // 加载bbx collider
  112. BoxCollider boxCollider = dog.AddComponent<BoxCollider>();
  113. boxCollider.isTrigger = true;
  114. boxCollider.center = new Vector3(0, 0.225f, 0);
  115. boxCollider.size = new Vector3(0.2f, 0.45f, 0.6f);
  116. }
  117. }
  118. // 本类用于管理场景中所有狗的状态包括动画状态,随机数分配等
  119. public class DogInScene
  120. {
  121. public DogProperty dogProperty;
  122. //public Vector3 location, rotation, scale;
  123. public int randomFactor = UnityEngine.Random.Range(0, 101); // 生成一个随机整数(0 到 100 之间),用于时间校验
  124. public DateTime animationStartTime; // 记录上一个动画开始时间的,每个动作间隔至少30秒。
  125. private int activeIndex; // 动物的活动指数
  126. private GameObject gameObject { set; get; }
  127. private Animator animator;
  128. private Vector3 moveToLocation;
  129. public bool isMoving;
  130. private float moveSpeed; // 用来控制狗的移动速度 0 0.5跑,0.75快跑,1跳
  131. public void SetGameObject(GameObject gameObject)
  132. {
  133. this.gameObject = gameObject;
  134. this.animator = gameObject.GetComponent<Animator>();
  135. }
  136. public DogInScene(DogProperty property) {
  137. this.dogProperty = property;
  138. this.activeIndex = (int)Math.Round((property.liveliness + property.intimate) * UnityEngine.Random.Range(0.3f, 0.7f));
  139. this.isMoving = false;
  140. }
  141. public void StartAnimation()
  142. {
  143. this.animationStartTime = DateTime.Now;
  144. this.animator.SetInteger("activeIndex", activeIndex);
  145. Debug.Log("activeIndex:" + this.activeIndex);
  146. float randomIndex = UnityEngine.Random.Range(0, 1f);
  147. this.animator.SetFloat("randomIndex", randomIndex);
  148. Debug.Log("randomIndex:" + randomIndex);
  149. }
  150. public void SetMoveSpeed(float speed)
  151. {
  152. this.moveSpeed = speed;
  153. }
  154. public void Move()
  155. {
  156. if (isMoving == false)
  157. {
  158. animationStartTime = DateTime.Now; // 设置动画开始时间
  159. float x = UnityEngine.Random.Range(-5f, 5f);
  160. float z = UnityEngine.Random.Range(-5f, 5f);
  161. this.moveToLocation = new Vector3(x, 0, z);
  162. //Debug.Log("move to location:" + x + ", " + z);
  163. this.isMoving = true;
  164. this.animator.SetTrigger("move");
  165. this.animator.SetBool("isMoving", true);
  166. this.animator.SetFloat("moveSpeed", this.moveSpeed);
  167. }
  168. this.gameObject.transform.LookAt(moveToLocation);
  169. this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, dogProperty.runSpeed * 0.02f * 0.01f); // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整
  170. //Debug.Log("current position:" + gameObject.transform.position.x + "z:" + gameObject.transform.position.z);
  171. // 如果狗距离到达重点就停止跑步动画
  172. float distance = Vector3.Distance(gameObject.transform.position, moveToLocation);
  173. if (distance < 0.1)
  174. {
  175. this.animator.SetBool("isMoving", false);
  176. this.isMoving = false;
  177. StartAnimation();
  178. }
  179. }
  180. public void Sleep()
  181. {
  182. this.animator.SetTrigger("sleep");
  183. this.animator.SetBool("isSleeping", true);
  184. }
  185. public void Listen()
  186. {
  187. //StopCoroutine(movingCoroutine);
  188. this.animator.SetTrigger("listen");
  189. this.animator.SetBool("isListening", true);
  190. this.animator.SetBool("isMoving", false) ;
  191. this.animator.SetBool("isBarking", false);
  192. this.animator.SetBool("isSleeping", false);
  193. this.gameObject.transform.LookAt(new Vector3(0, 0, -6));
  194. }
  195. // 用来出来音频返回结果
  196. public void PostListen(bool result)
  197. {
  198. if (result)
  199. {
  200. // TODO 成功,狗狗跑过来,
  201. }
  202. else
  203. {
  204. this.animator.SetBool("isListening", false);
  205. }
  206. }
  207. }