DogInScene.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. using System;
  2. using System.Collections;
  3. using UnityEngine;
  4. using UnityEngine.Rendering.PostProcessing;
  5. /* 本类用于管理场景中所有狗的状态包括动画状态,随机数分配等
  6. */
  7. //[CreateAssetMenu(fileName = "DogInScene", menuName = "Scriptable Objects/DogInScene")]
  8. public class DogInScene : ScriptableObject
  9. {
  10. //}
  11. //public class DogInScene
  12. //{
  13. //通用参数段
  14. public DogProperty dogProperty;
  15. public GameObject gameObject { set; get; }
  16. public Animator animator;
  17. private Vector3 moveToLocation;
  18. public float moveSpeed; // 用来控制狗的移动速度 0 0.5跑,0.75快跑,1跳
  19. public string dogState; // 狗的状态代码分类通道,包括三大类使用道具(itemConsume),闲置(idle),和主人交互(interact)等
  20. // 喝水吃饭参数段
  21. public DateTime drinkStartTime, eatStartTime; // 记录吃喝开始时间
  22. public bool itemConsumeProgress=false; // 是否在吃和喝的进程中。如果是的话,跳过常规动画检测
  23. public bool isMovingToBowl;
  24. // 随机动作参数段
  25. public int randomFactor;
  26. public DateTime animationStartTime; // 记录上一个动画开始时间的,每个随机动作间隔至少30秒
  27. private int activeIndex; // 动物的活动指数
  28. public bool isMoving; // 动物正在移动,避免其他随机动作发生
  29. public bool isSleeping; // 动物正在正在睡觉,避免触发其他动画
  30. // 固定参数
  31. private const float moveSpeedAdj = 0.025f;
  32. // interact相关的参数
  33. public DateTime interactLastUpdate; // 上次交互指令时间
  34. private bool isMovingToPlayer; // 是否在向玩家移动
  35. #region 通用函数段
  36. public void SetGameObject(GameObject gameObject)
  37. {
  38. this.gameObject = gameObject;
  39. this.animator = gameObject.GetComponent<Animator>();
  40. this.randomFactor = UnityEngine.Random.Range(0, 51); // 生成一个随机整数(0 到 50 之间),用于时间校验
  41. Debug.Log(this.gameObject.name + "random factor is:" + randomFactor);
  42. }
  43. public DogInScene(DogProperty property)
  44. {
  45. this.dogProperty = property;
  46. this.activeIndex = (int)Math.Round((property.liveliness + property.intimate) * UnityEngine.Random.Range(0.3f, 0.7f));
  47. this.isMoving = false;
  48. }
  49. #endregion
  50. #region interact交互函数段
  51. // 启动交互行为准备过程
  52. public void SetupInteract()
  53. {
  54. // 加载Interact animator controller,避免过于复杂的Animator Controller
  55. Animator animator = gameObject.GetComponent<Animator>();
  56. RuntimeAnimatorController animatorController = Resources.Load<RuntimeAnimatorController>("Dog/AnimatorController/shibaInu/HomeDogInteractController");
  57. if (dogProperty.breed == "shibaInu") { animatorController = Resources.Load<RuntimeAnimatorController>("Dog/AnimatorController/shibaInu/HomeDogInteractController"); }
  58. animator.runtimeAnimatorController = animatorController;
  59. this.dogState = "interact";
  60. this.interactLastUpdate = DateTime.Now;
  61. this.moveToLocation = new Vector3(0f, 0f, -4.75f);
  62. this.isMovingToPlayer = true;
  63. MovetoPlayer();
  64. }
  65. public void MovetoPlayer()
  66. {
  67. // 如果距离目标小于0.5米就把速度调整为零
  68. if (Vector3.Distance(moveToLocation, this.gameObject.transform.position) < 0.5f)
  69. {
  70. this.SetMoveSpeed(0);
  71. }
  72. this.gameObject.transform.LookAt(new Vector3(0f, 1f, -8f));
  73. this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, dogProperty.runSpeed * (1 + moveSpeed) * 0.02f * moveSpeedAdj); // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应RM动画
  74. // 如果狗距离到达重点就停止跑步动画
  75. float distance = Vector3.Distance(gameObject.transform.position, moveToLocation);
  76. if (distance < 0.1)
  77. {
  78. this.animator.SetBool("isMoving", false);
  79. this.isMovingToPlayer = false;
  80. }
  81. }
  82. // 交互行为计时器
  83. public bool InteractTimeout()
  84. {
  85. TimeSpan ts = new TimeSpan();
  86. ts = DateTime.Now - this.interactLastUpdate;
  87. if (ts.TotalSeconds > 10) { return true; }
  88. else { return false; }
  89. }
  90. public void ExitInteract()
  91. {
  92. // 结束交互行为,恢复原有的菜单
  93. this.dogState = "idle";
  94. }
  95. #endregion
  96. #region 随机动作控制函数
  97. // 随机选择宠物动作
  98. public void IdleAnimation()
  99. {
  100. this.animationStartTime = DateTime.Now;
  101. this.animator.SetInteger("activeIndex", activeIndex);
  102. //Debug.Log("activeIndex:" + this.activeIndex);
  103. float randomIndex = UnityEngine.Random.Range(0, 1f);
  104. this.animator.SetFloat("randomIndex", randomIndex);
  105. this.dogState = "idle";
  106. //Debug.Log("randomIndex:" + randomIndex);
  107. }
  108. public void SetMoveSpeed(float speed)
  109. {
  110. this.moveSpeed = speed;
  111. }
  112. // 宠物随机移动
  113. public void RandomMove()
  114. {
  115. // 如果距离目标小于0.5米就把速度调整为零
  116. if (Vector3.Distance(moveToLocation, this.gameObject.transform.position) < 0.5f)
  117. {
  118. //Debug.Log(this.gameObject.name + "current move speed:" + moveSpeed);
  119. this.SetMoveSpeed(0);
  120. //Debug.Log(this.gameObject.name + "reduce move speed:" + moveSpeed);
  121. }
  122. if (isMoving == false)
  123. {
  124. animationStartTime = DateTime.Now; // 设置动画开始时间
  125. float x = UnityEngine.Random.Range(-5f, 5f);
  126. float z = UnityEngine.Random.Range(0f, 5f);
  127. this.moveToLocation = new Vector3(x, 0, z);
  128. //Debug.Log("move to location:" + x + ", " + z);
  129. this.isMoving = true;
  130. this.animator.SetTrigger("move");
  131. this.animator.SetBool("isMoving", true);
  132. this.animator.SetFloat("moveSpeed", this.moveSpeed);
  133. }
  134. this.gameObject.transform.LookAt(moveToLocation);
  135. this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, dogProperty.runSpeed * (1 + moveSpeed) * 0.02f * moveSpeedAdj); // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应RM动画
  136. //this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, (100 + dogProperty.runSpeed) * (1 + moveSpeed) * 0.02f * 0.015f); // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应IF动画
  137. //Debug.Log("current position:" + gameObject.transform.position.x + "z:" + gameObject.transform.position.z);
  138. // 如果狗距离到达重点就停止跑步动画
  139. float distance = Vector3.Distance(gameObject.transform.position, moveToLocation);
  140. if (distance < 0.1)
  141. {
  142. this.animator.SetBool("isMoving", false);
  143. //this.moveSpeed = 0.4f;
  144. this.isMoving = false;
  145. IdleAnimation();
  146. }
  147. }
  148. public void Sleep()
  149. {
  150. this.animator.SetTrigger("sleep");
  151. this.animator.SetBool("isSleeping", true);
  152. this.isSleeping = true;
  153. this.dogState = "sleep";
  154. }
  155. public void Listen()
  156. {
  157. //StopCoroutine(movingCoroutine);
  158. //this.animator.SetTrigger("listen");
  159. this.animator.SetBool("isListening", true);
  160. this.animator.SetBool("isMoving", false);
  161. this.animator.SetBool("isBarking", false);
  162. this.animator.SetBool("isSleeping", false);
  163. this.isSleeping = false; // 主人呼叫可以唤醒狗
  164. this.gameObject.transform.LookAt(new Vector3(0, 0, -6));
  165. HomeController.playerCam.Priority = 10;
  166. HomeController.dogCam.Priority = 1;
  167. HomeController.lastCameraChange = DateTime.Now;
  168. this.dogState = "listen";
  169. }
  170. // 用来出来音频返回结果
  171. //public void PostListenRequest(bool result)
  172. //{
  173. // if (result)
  174. // {
  175. // // TODO 语音信息识别成功,狗狗语音适配得分最高的跑过来
  176. // this.animator.SetBool("isListening", false);
  177. // }
  178. // else
  179. // {
  180. // this.animator.SetBool("isListening", false);
  181. // }
  182. // // TODO 根据返回结果设定focusdog
  183. // // focusdog 开启互动模式
  184. // HomeController.dogsInScene[GameData.focusDog].dogState = "interact";
  185. // HomeController.dogsInScene[GameData.focusDog].SetupInteract();
  186. //}
  187. #endregion
  188. #region 喝水,吃食等道具消费函数
  189. // 开始整个使用道具的流程
  190. public void StartItemConsume(ItemGroup group)
  191. {
  192. GameObject bowl = GameObject.Find("Bowl_water"); // 先指定一个碗,编译通过
  193. this.itemConsumeProgress = true; // 开启使用道具过程
  194. this.dogState = "itemConsume";
  195. if (group == ItemGroup.water)
  196. {
  197. bowl = GameObject.Find("Bowl_water"); // 开启整个喝水的进程
  198. }
  199. if (group == ItemGroup.food)
  200. {
  201. bowl = GameObject.Find("Bowl_food"); // 开启整个吃食物的进程
  202. }
  203. this.moveToLocation = bowl.transform.position;
  204. this.isMovingToBowl = true;
  205. this.animator.SetTrigger("move"); // 切换为走路动画
  206. this.animator.SetBool("isMoving", true); // 保持为走路动画
  207. this.animator.SetFloat("moveSpeed", this.moveSpeed);
  208. }
  209. public void MovetoBowl()
  210. {
  211. // 如果距离目标小于0.5米就把速度调整为零
  212. if (Vector3.Distance(moveToLocation, this.gameObject.transform.position) < 0.5f)
  213. {
  214. Debug.Log(this.gameObject.name + "current move speed:" + moveSpeed);
  215. this.SetMoveSpeed(0);
  216. Debug.Log(this.gameObject.name + "reduce move speed:" + moveSpeed);
  217. }
  218. var vamUI = GameObject.Find("VoiceAndMenu");
  219. if (vamUI != null)
  220. {
  221. vamUI.SetActive(false);
  222. }
  223. this.gameObject.transform.LookAt(moveToLocation);
  224. this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, dogProperty.runSpeed * (1 + moveSpeed) * 0.02f * moveSpeedAdj); // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应RM动画
  225. //this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, (100+dogProperty.runSpeed) * (1 + moveSpeed) * 0.02f * 0.015f); // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应IF动画
  226. //Debug.Log("current position:" + gameObject.transform.position.x + "z:" + gameObject.transform.position.z);
  227. // 如果狗距离到达重点就停止跑步动画
  228. float distance = Vector3.Distance(gameObject.transform.position, moveToLocation);
  229. if (distance < 0.1)
  230. {
  231. this.animator.SetBool("isMoving", false);
  232. }
  233. }
  234. public IEnumerator DrinkAnimation()
  235. {
  236. this.animator.SetBool("isMoving", false); // 关闭移动动画
  237. TimeSpan ts = new TimeSpan();
  238. var targetBowl = GameObject.Find("Bowl_water");
  239. // 摄像头看向水盆位置
  240. HomeController.dogCam.m_LookAt = targetBowl.transform;
  241. HomeController.dogCam.Priority = 10;
  242. HomeController.playerCam.Priority = 1;
  243. while (ts.TotalSeconds < 10)
  244. {
  245. yield return new WaitForSeconds(0.25f);
  246. ts = DateTime.Now - this.drinkStartTime;
  247. //Debug.Log("结束饮水过程:" + ts.TotalSeconds);
  248. // 狗一致看向谁碰,确保就算被撞击后依然看向水盆
  249. this.gameObject.transform.LookAt(targetBowl.transform.position);
  250. }
  251. // 播放10秒后结束饮水过程
  252. this.animator.SetBool("isDrinking", false);
  253. // 摄像头恢复玩家视角
  254. HomeController.dogCam.Priority = 1;
  255. HomeController.playerCam.Priority = 10;
  256. // 让水物消失
  257. var water = GameObject.Find("Water");
  258. water.transform.localPosition = new Vector3(-1, -10, -1);
  259. //var water = GameObject.Find("Water");
  260. //water.SetActive(false);
  261. // 再等待几秒后让水盆消失
  262. while (ts.TotalSeconds < 18)
  263. {
  264. yield return new WaitForSeconds(0.25f);
  265. ts = DateTime.Now - this.drinkStartTime;
  266. //Debug.Log("让水盆消失:" + ts.TotalSeconds);
  267. }
  268. targetBowl.transform.position = new Vector3(-1, -10, -1); // 将喝水碗回归原位
  269. water.transform.localPosition = Vector3.zero; // 将食物回归原位
  270. this.itemConsumeProgress = false; // 关闭整个道具使用的进程
  271. this.dogState = "idle";
  272. QuitItemConsume();
  273. }
  274. public IEnumerator EatAnimation()
  275. {
  276. this.animator.SetBool("isMoving", false); // 关闭移动动画
  277. TimeSpan ts = new TimeSpan();
  278. var targetBowl = GameObject.Find("Bowl_food");
  279. // 摄像头看向盆位置
  280. HomeController.dogCam.m_LookAt = targetBowl.transform;
  281. HomeController.dogCam.Priority = 10;
  282. HomeController.playerCam.Priority = 1;
  283. while (ts.TotalSeconds < 10)
  284. {
  285. yield return new WaitForSeconds(0.25f);
  286. ts = DateTime.Now - this.eatStartTime;
  287. // 狗一致看向谁碰,确保就算被撞击后依然看向水盆
  288. this.gameObject.transform.LookAt(targetBowl.transform.position);
  289. }
  290. // 播放10秒后结束吃狗粮过程
  291. this.animator.SetBool("isEating", false);
  292. //Debug.Log(this.dogProperty.dog_name + "狗吃完了");
  293. // 摄像头恢复玩家视角
  294. HomeController.dogCam.Priority = 1;
  295. HomeController.playerCam.Priority = 10;
  296. // 让食物消失
  297. var food = GameObject.Find("Food");
  298. food.transform.localPosition = new Vector3(-1, -10, -1);
  299. //var water = GameObject.Find("Water");
  300. //water.SetActive(false);
  301. // 再等待几秒后让饭盆消失
  302. while (ts.TotalSeconds < 18)
  303. {
  304. yield return new WaitForSeconds(0.25f);
  305. ts = DateTime.Now - this.eatStartTime;
  306. //Debug.Log("让水盆消失:" + ts.TotalSeconds);
  307. }
  308. //Debug.Log(this.dogProperty.dog_name + "把碗放回去了");
  309. targetBowl.transform.position = new Vector3(-1, -10, -1); // 将饭盆回归原位
  310. food.transform.localPosition = Vector3.zero; // 将食物回归原位
  311. this.itemConsumeProgress = false; // 关闭整个道具使用的进程
  312. this.dogState = "idle";
  313. QuitItemConsume();
  314. }
  315. public void QuitItemConsume()
  316. {
  317. var uiPlaceholder = GameObject.Find("UI Placeholder");
  318. var vamUI = uiPlaceholder.transform.Find("VoiceAndMenu").gameObject;
  319. vamUI.SetActive(true);
  320. this.moveSpeed = UnityEngine.Random.Range(0.3f, 0.6f);
  321. RandomMove();
  322. }
  323. #endregion
  324. }