Ver código fonte

4/29更新

2025/4/29
完成客户端狗command训练功能。修复训练其他动作时候动画播放的问题
修改messagebox 重复显示错误
完成前端指令交互,待后端开发完成后测试
完成用户反馈页面的外观部分
Jees 2 meses atrás
pai
commit
e776797dc6
28 arquivos alterados com 1055 adições e 219 exclusões
  1. 4 3
      Assets/Packages/Red_Deer/Cartoon_Animals/Cartoon_Dogs/Cartoon_ShibaInu/FBX/Anim/Cartoon_ShibaInu_anim_IP.fbx.meta
  2. 50 2
      Assets/Resources/Data/languages.json
  3. 154 104
      Assets/Resources/Dog/AnimatorController/shibaInu/HomeDogInteractController.controller
  4. 1 1
      Assets/Resources/Dog/Skin/shibaInu/amber.mat
  5. 1 1
      Assets/Resources/Home/Particle_QuestionMark.prefab
  6. 12 1
      Assets/Resources/MessageBox/MessageBoxController.cs
  7. 38 2
      Assets/Resources/Status/StatusController.cs
  8. 1 1
      Assets/Resources/Status/StatusStyle.uss
  9. 7 4
      Assets/Resources/Status/StatusUI.uxml
  10. 5 1
      Assets/Resources/VoiceAndManu/VoiceController.cs
  11. 318 0
      Assets/Scenes/Home.unity
  12. 8 0
      Assets/Scenes/Home_Profiles/User Feedback UI.meta
  13. 11 0
      Assets/Scenes/Home_Profiles/User Feedback UI/User Feedback.uxml
  14. 10 0
      Assets/Scenes/Home_Profiles/User Feedback UI/User Feedback.uxml.meta
  15. 45 0
      Assets/Scenes/Login.unity
  16. 1 0
      Assets/Scripts/Develop Script/TestSetup.cs
  17. 15 0
      Assets/Scripts/EnviromentController.cs
  18. 53 0
      Assets/Scripts/Functions/LogSystem.cs
  19. 2 0
      Assets/Scripts/Functions/LogSystem.cs.meta
  20. 1 1
      Assets/Scripts/GameControllers/GameData.cs
  21. 13 0
      Assets/Scripts/GameControllers/GameTool.cs
  22. 41 0
      Assets/Scripts/Home/DogBarkController.cs
  23. 2 0
      Assets/Scripts/Home/DogBarkController.cs.meta
  24. 36 15
      Assets/Scripts/Home/DogInScene.cs
  25. 150 82
      Assets/Scripts/Home/HomeController.cs
  26. 2 1
      Assets/Scripts/Home/HomeSoundEffectController.cs
  27. 72 0
      Assets/Scripts/Home/UserFeedbackController.cs
  28. 2 0
      Assets/Scripts/Home/UserFeedbackController.cs.meta

+ 4 - 3
Assets/Packages/Red_Deer/Cartoon_Animals/Cartoon_Dogs/Cartoon_ShibaInu/FBX/Anim/Cartoon_ShibaInu_anim_IP.fbx.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
 guid: 0faf4e66268a11e4d982d9a0163734ca
 ModelImporter:
-  serializedVersion: 21300
+  serializedVersion: 22200
   internalIDToNameTable: []
   externalObjects:
   - first:
@@ -21,8 +21,6 @@ ModelImporter:
     optimizeGameObjects: 0
     removeConstantScaleCurves: 1
     motionNodeName: 
-    rigImportErrors: 
-    rigImportWarnings: 
     animationImportErrors: 
     animationImportWarnings: 
     animationRetargetingWarnings: 
@@ -3322,6 +3320,7 @@ ModelImporter:
     addColliders: 0
     useSRGBMaterialColor: 1
     sortHierarchyByName: 0
+    importPhysicalCameras: 1
     importVisibility: 0
     importBlendShapes: 0
     importCameras: 0
@@ -3349,6 +3348,7 @@ ModelImporter:
     secondaryUVMinObjectScale: 1
     secondaryUVPackMargin: 4
     useFileScale: 1
+    strictVertexDataChecks: 0
   tangentSpace:
     normalSmoothAngle: 60
     normalImportMode: 0
@@ -3381,6 +3381,7 @@ ModelImporter:
   humanoidOversampling: 1
   avatarSetup: 2
   addHumanoidExtraRootOnlyWhenUsingAvatar: 1
+  importBlendShapeDeformPercent: 0
   remapMaterialsIfMaterialImportModeIsNone: 0
   additionalBone: 0
   userData: 

+ 50 - 2
Assets/Resources/Data/languages.json

@@ -223,8 +223,8 @@
             "zh-cn": "把<<dog name>>送给你的好友吗?"
         },
         "voiceCall_00": {
-            "en": "Are you ready? Please hold record and say the puppy's name.",
-            "zh-cn": "准备好了吗?按住下面的录音按键说出狗狗的名字。"
+            "en": "Are you ready? Please hold record button and say <<dog_name>>'s name.",
+            "zh-cn": "准备好了吗?按住下面的录音按键说出<<dog_name>>的名字。"
         },
         "voiceCall_01": {
             "en": "Record again. Ensure that the two recordings are consistent.",
@@ -382,6 +382,10 @@
             "en": "Record fail. Please try again.",
             "zh-cn": "录音失败。请再试一次。"
         },
+        "first_touch_interactive": {
+            "en": "Try to touch the dog. He will be very happy.",
+            "zh-cn": "尝试抚摸一下狗狗吧。他会很开心。"
+        },
 
 
 
@@ -424,6 +428,10 @@
         "spin_trainng": {
             "en": "Are you ready? Now you can train <dog name> to spin. Press and hold the recording button below to say the command.",
             "zh-cn": "准备好了吗?现在可以训练<dog name>转圈了。按住下面的录音按键说出指令。"
+        },
+        "reset_voice_reminder":{
+            "en": "Are you sure to reset <<dog name>> voice training data?",
+            "zh-cn": "确定要重置<<dog name>>语音训练数据吗?"
         }
     },
     "canvas": {
@@ -507,6 +515,10 @@
             "command": {
                 "en": "He can understand:",
                 "zh-cn": "可以听懂的口令:"
+            },
+            "resetVoice":{
+                "en": "Re-train voice",
+                "zh-cn": "重新语音训练"
             }
         },
         "button": {
@@ -885,6 +897,42 @@
             }
         }
     },
+    "FeedbackUI": {
+        "button": {
+            "submit": {
+                "en": "Submit",
+                "zh-cn": "提交"
+            },
+            "cancel": {
+                "en": "Cancel",
+                "zh-cn": "取消"
+            }
+        },
+        "label": {
+            "type": {
+                "en": "Type:",
+                "zh-cn": "类别:"
+            },
+            "option_0": {
+                "en": "Comments",
+                "zh-cn": "建议"
+            },
+            "option_1": {
+                "en": "Bug",
+                "zh-cn": "Bug"
+            },
+            "feedback": {
+                "en": "Feedback:",
+                "zh-cn": "反馈:"
+            }
+        },
+        "message":{
+            "thanks for feedback":{
+                "en": "Thanks for your feedback. We will response as soon as possible.",
+                "zh-cn": "感谢你的反馈,我们会尽快处理。"
+            }
+        }
+    },
     "item": {
         "food": {
             "food_00001": {

+ 154 - 104
Assets/Resources/Dog/AnimatorController/shibaInu/HomeDogInteractController.controller

@@ -58,7 +58,7 @@ AnimatorStateTransition:
   m_CorrespondingSourceObject: {fileID: 0}
   m_PrefabInstance: {fileID: 0}
   m_PrefabAsset: {fileID: 0}
-  m_Name: 
+  m_Name: to Sit
   m_Conditions:
   - m_ConditionMode: 1
     m_ConditionEvent: Sit
@@ -126,6 +126,31 @@ AnimatorState:
   m_MirrorParameter: 
   m_CycleOffsetParameter: 
   m_TimeParameter: 
+--- !u!1101 &-6952508641186958566
+AnimatorStateTransition:
+  m_ObjectHideFlags: 1
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_Name: 
+  m_Conditions:
+  - m_ConditionMode: 1
+    m_ConditionEvent: Shake
+    m_EventTreshold: 0
+  m_DstStateMachine: {fileID: 0}
+  m_DstState: {fileID: -2450543374366050217}
+  m_Solo: 0
+  m_Mute: 0
+  m_IsExit: 0
+  serializedVersion: 3
+  m_TransitionDuration: 0.88157994
+  m_TransitionOffset: 0.00000008339813
+  m_ExitTime: 1.5978219e-10
+  m_HasExitTime: 0
+  m_HasFixedDuration: 1
+  m_InterruptionSource: 0
+  m_OrderedInterruption: 1
+  m_CanTransitionToSelf: 1
 --- !u!1101 &-6578774210054145230
 AnimatorStateTransition:
   m_ObjectHideFlags: 1
@@ -135,7 +160,7 @@ AnimatorStateTransition:
   m_Name: 
   m_Conditions:
   - m_ConditionMode: 2
-    m_ConditionEvent: isDieing
+    m_ConditionEvent: Die_status
     m_EventTreshold: 0
   m_DstStateMachine: {fileID: 0}
   m_DstState: {fileID: 533779715773965248}
@@ -143,9 +168,9 @@ AnimatorStateTransition:
   m_Mute: 0
   m_IsExit: 0
   serializedVersion: 3
-  m_TransitionDuration: 0.25
-  m_TransitionOffset: 0
-  m_ExitTime: 0.8
+  m_TransitionDuration: 1.1192349
+  m_TransitionOffset: 0.007821141
+  m_ExitTime: 0.080458455
   m_HasExitTime: 1
   m_HasFixedDuration: 1
   m_InterruptionSource: 0
@@ -185,7 +210,7 @@ AnimatorStateTransition:
   m_Name: 
   m_Conditions:
   - m_ConditionMode: 2
-    m_ConditionEvent: isLieDowning
+    m_ConditionEvent: LieDown_status
     m_EventTreshold: 0
   m_DstStateMachine: {fileID: 0}
   m_DstState: {fileID: 533779715773965248}
@@ -262,6 +287,9 @@ AnimatorStateMachine:
   - serializedVersion: 1
     m_State: {fileID: 605629613261180730}
     m_Position: {x: 710, y: 350, z: 0}
+  - serializedVersion: 1
+    m_State: {fileID: -2450543374366050217}
+    m_Position: {x: 460, y: 740, z: 0}
   m_ChildStateMachines:
   - serializedVersion: 1
     m_StateMachine: {fileID: -4310704879323197233}
@@ -274,17 +302,16 @@ AnimatorStateMachine:
     m_Position: {x: 600, y: 670, z: 0}
   m_AnyStateTransitions:
   - {fileID: 8206564768075581269}
-  - {fileID: 8331535787116983140}
   - {fileID: 8949881451646535694}
-  - {fileID: 7658456728552812019}
   - {fileID: -8879138944245576174}
   - {fileID: -8140731904463588801}
   - {fileID: -3654118028524020105}
   - {fileID: -3298209393076701864}
   - {fileID: -3978327597696489592}
   - {fileID: -6112286787422867255}
-  - {fileID: -3939263286608137731}
   - {fileID: -601727430303711784}
+  - {fileID: -2781770849813265970}
+  - {fileID: -6952508641186958566}
   m_EntryTransitions: []
   m_StateMachineTransitions: {}
   m_StateMachineBehaviours: []
@@ -318,32 +345,32 @@ AnimatorStateTransition:
   m_InterruptionSource: 0
   m_OrderedInterruption: 1
   m_CanTransitionToSelf: 1
---- !u!1101 &-3939263286608137731
+--- !u!1101 &-3654118028524020105
 AnimatorStateTransition:
   m_ObjectHideFlags: 1
   m_CorrespondingSourceObject: {fileID: 0}
   m_PrefabInstance: {fileID: 0}
   m_PrefabAsset: {fileID: 0}
-  m_Name: to Death
+  m_Name: 
   m_Conditions:
   - m_ConditionMode: 1
-    m_ConditionEvent: Die
+    m_ConditionEvent: Stand
     m_EventTreshold: 0
   m_DstStateMachine: {fileID: 0}
-  m_DstState: {fileID: -961187681864823423}
+  m_DstState: {fileID: 605629613261180730}
   m_Solo: 0
   m_Mute: 0
   m_IsExit: 0
   serializedVersion: 3
-  m_TransitionDuration: 1.2688694
-  m_TransitionOffset: 0
-  m_ExitTime: 0.052229445
+  m_TransitionDuration: 1.1460252
+  m_TransitionOffset: 0.037049755
+  m_ExitTime: 0.049399685
   m_HasExitTime: 0
   m_HasFixedDuration: 1
   m_InterruptionSource: 0
   m_OrderedInterruption: 1
   m_CanTransitionToSelf: 1
---- !u!1101 &-3654118028524020105
+--- !u!1101 &-3298209393076701864
 AnimatorStateTransition:
   m_ObjectHideFlags: 1
   m_CorrespondingSourceObject: {fileID: 0}
@@ -352,47 +379,74 @@ AnimatorStateTransition:
   m_Name: 
   m_Conditions:
   - m_ConditionMode: 1
-    m_ConditionEvent: Stand
+    m_ConditionEvent: Hug
     m_EventTreshold: 0
   m_DstStateMachine: {fileID: 0}
-  m_DstState: {fileID: 605629613261180730}
+  m_DstState: {fileID: -1898261574974550075}
   m_Solo: 0
   m_Mute: 0
   m_IsExit: 0
   serializedVersion: 3
-  m_TransitionDuration: 1.1903933
-  m_TransitionOffset: 0.037049755
-  m_ExitTime: 0.049399685
+  m_TransitionDuration: 0.5865151
+  m_TransitionOffset: 0.08413017
+  m_ExitTime: 0.026492938
   m_HasExitTime: 0
   m_HasFixedDuration: 1
   m_InterruptionSource: 0
   m_OrderedInterruption: 1
   m_CanTransitionToSelf: 1
---- !u!1101 &-3298209393076701864
+--- !u!1101 &-2781770849813265970
 AnimatorStateTransition:
   m_ObjectHideFlags: 1
   m_CorrespondingSourceObject: {fileID: 0}
   m_PrefabInstance: {fileID: 0}
   m_PrefabAsset: {fileID: 0}
-  m_Name: 
+  m_Name: to Death
   m_Conditions:
   - m_ConditionMode: 1
-    m_ConditionEvent: Hug
+    m_ConditionEvent: Die
     m_EventTreshold: 0
   m_DstStateMachine: {fileID: 0}
-  m_DstState: {fileID: -1898261574974550075}
+  m_DstState: {fileID: -961187681864823423}
   m_Solo: 0
   m_Mute: 0
   m_IsExit: 0
   serializedVersion: 3
-  m_TransitionDuration: 0.5865151
-  m_TransitionOffset: 0.08413017
-  m_ExitTime: 0.026492938
+  m_TransitionDuration: 1.9529201
+  m_TransitionOffset: 0
+  m_ExitTime: 0.05520874
   m_HasExitTime: 0
   m_HasFixedDuration: 1
   m_InterruptionSource: 0
   m_OrderedInterruption: 1
   m_CanTransitionToSelf: 1
+--- !u!1102 &-2450543374366050217
+AnimatorState:
+  serializedVersion: 6
+  m_ObjectHideFlags: 1
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_Name: Shake
+  m_Speed: 1
+  m_CycleOffset: 0
+  m_Transitions:
+  - {fileID: 5640930357459101007}
+  m_StateMachineBehaviours: []
+  m_Position: {x: 50, y: 50, z: 0}
+  m_IKOnFeet: 0
+  m_WriteDefaultValues: 1
+  m_Mirror: 0
+  m_SpeedParameterActive: 0
+  m_MirrorParameterActive: 0
+  m_CycleOffsetParameterActive: 0
+  m_TimeParameterActive: 0
+  m_Motion: {fileID: 5672872838960103031, guid: 1a349bfe663f8a848a567303e35c613a, type: 3}
+  m_Tag: 
+  m_SpeedParameter: 
+  m_MirrorParameter: 
+  m_CycleOffsetParameter: 
+  m_TimeParameter: 
 --- !u!1102 &-1898261574974550075
 AnimatorState:
   serializedVersion: 6
@@ -477,7 +531,10 @@ AnimatorStateTransition:
   m_PrefabInstance: {fileID: 0}
   m_PrefabAsset: {fileID: 0}
   m_Name: 
-  m_Conditions: []
+  m_Conditions:
+  - m_ConditionMode: 2
+    m_ConditionEvent: Listen_status
+    m_EventTreshold: 0
   m_DstStateMachine: {fileID: 0}
   m_DstState: {fileID: 533779715773965248}
   m_Solo: 0
@@ -532,19 +589,19 @@ AnimatorController:
     m_DefaultInt: 0
     m_DefaultBool: 0
     m_Controller: {fileID: 9100000}
-  - m_Name: isSiting
+  - m_Name: Sit_status
     m_Type: 4
     m_DefaultFloat: 0
     m_DefaultInt: 0
     m_DefaultBool: 0
     m_Controller: {fileID: 9100000}
-  - m_Name: isLieDowning
+  - m_Name: LieDown_status
     m_Type: 4
     m_DefaultFloat: 0
     m_DefaultInt: 0
     m_DefaultBool: 0
     m_Controller: {fileID: 9100000}
-  - m_Name: isDieing
+  - m_Name: Die_status
     m_Type: 4
     m_DefaultFloat: 0
     m_DefaultInt: 0
@@ -556,13 +613,19 @@ AnimatorController:
     m_DefaultInt: 0
     m_DefaultBool: 0
     m_Controller: {fileID: 9100000}
-  - m_Name: isStanding
+  - m_Name: Stand_status
     m_Type: 4
     m_DefaultFloat: 0
     m_DefaultInt: 0
     m_DefaultBool: 0
     m_Controller: {fileID: 9100000}
-  - m_Name: isBarking
+  - m_Name: Bark_status
+    m_Type: 4
+    m_DefaultFloat: 0
+    m_DefaultInt: 0
+    m_DefaultBool: 0
+    m_Controller: {fileID: 9100000}
+  - m_Name: Shake_status
     m_Type: 4
     m_DefaultFloat: 0
     m_DefaultInt: 0
@@ -646,6 +709,12 @@ AnimatorController:
     m_DefaultInt: 0
     m_DefaultBool: 0
     m_Controller: {fileID: 9100000}
+  - m_Name: Shake
+    m_Type: 4
+    m_DefaultFloat: 0
+    m_DefaultInt: 0
+    m_DefaultBool: 0
+    m_Controller: {fileID: 9100000}
   m_AnimatorLayers:
   - serializedVersion: 5
     m_Name: Base Layer
@@ -707,7 +776,7 @@ AnimatorState:
   m_MirrorParameterActive: 0
   m_CycleOffsetParameterActive: 0
   m_TimeParameterActive: 0
-  m_Motion: {fileID: 3858329934085553762, guid: 1a349bfe663f8a848a567303e35c613a, type: 3}
+  m_Motion: {fileID: 3858329934085553762, guid: 0faf4e66268a11e4d982d9a0163734ca, type: 3}
   m_Tag: 
   m_SpeedParameter: 
   m_MirrorParameter: 
@@ -747,16 +816,19 @@ AnimatorStateTransition:
   m_PrefabInstance: {fileID: 0}
   m_PrefabAsset: {fileID: 0}
   m_Name: 
-  m_Conditions: []
+  m_Conditions:
+  - m_ConditionMode: 2
+    m_ConditionEvent: Sit_status
+    m_EventTreshold: 0
   m_DstStateMachine: {fileID: 0}
   m_DstState: {fileID: 533779715773965248}
   m_Solo: 0
   m_Mute: 0
   m_IsExit: 0
   serializedVersion: 3
-  m_TransitionDuration: 0.25
-  m_TransitionOffset: 0
-  m_ExitTime: 0.76
+  m_TransitionDuration: 0.69210476
+  m_TransitionOffset: 0.04912278
+  m_ExitTime: 0.22554438
   m_HasExitTime: 1
   m_HasFixedDuration: 1
   m_InterruptionSource: 0
@@ -779,9 +851,9 @@ AnimatorStateTransition:
   m_Mute: 0
   m_IsExit: 0
   serializedVersion: 3
-  m_TransitionDuration: 0.25
-  m_TransitionOffset: 0
-  m_ExitTime: 0.1
+  m_TransitionDuration: 0.25000003
+  m_TransitionOffset: 0.020301713
+  m_ExitTime: 0.009911636
   m_HasExitTime: 1
   m_HasFixedDuration: 1
   m_InterruptionSource: 0
@@ -933,9 +1005,9 @@ AnimatorStateTransition:
   m_Mute: 0
   m_IsExit: 0
   serializedVersion: 3
-  m_TransitionDuration: 0.25
-  m_TransitionOffset: 0
-  m_ExitTime: 0.8
+  m_TransitionDuration: 0.9434768
+  m_TransitionOffset: 0.013531265
+  m_ExitTime: 0.08284372
   m_HasExitTime: 1
   m_HasFixedDuration: 1
   m_InterruptionSource: 0
@@ -958,9 +1030,9 @@ AnimatorStateTransition:
   m_Mute: 0
   m_IsExit: 0
   serializedVersion: 3
-  m_TransitionDuration: 0.25
-  m_TransitionOffset: 0
-  m_ExitTime: 0.1
+  m_TransitionDuration: 0.25000003
+  m_TransitionOffset: 0.0000001341104
+  m_ExitTime: 0.008642785
   m_HasExitTime: 1
   m_HasFixedDuration: 1
   m_InterruptionSource: 0
@@ -1018,6 +1090,31 @@ AnimatorStateMachine:
   m_ExitPosition: {x: 800, y: 120, z: 0}
   m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
   m_DefaultState: {fileID: 5934876067920876819}
+--- !u!1101 &5640930357459101007
+AnimatorStateTransition:
+  m_ObjectHideFlags: 1
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_Name: 
+  m_Conditions:
+  - m_ConditionMode: 2
+    m_ConditionEvent: Shake_status
+    m_EventTreshold: 0
+  m_DstStateMachine: {fileID: 0}
+  m_DstState: {fileID: 533779715773965248}
+  m_Solo: 0
+  m_Mute: 0
+  m_IsExit: 0
+  serializedVersion: 3
+  m_TransitionDuration: 3.4844563
+  m_TransitionOffset: 0
+  m_ExitTime: 0.04851382
+  m_HasExitTime: 1
+  m_HasFixedDuration: 1
+  m_InterruptionSource: 0
+  m_OrderedInterruption: 1
+  m_CanTransitionToSelf: 1
 --- !u!1102 &5770380076500164988
 AnimatorState:
   serializedVersion: 6
@@ -1214,9 +1311,9 @@ AnimatorStateTransition:
   m_Mute: 0
   m_IsExit: 0
   serializedVersion: 3
-  m_TransitionDuration: 0.25
-  m_TransitionOffset: 0
-  m_ExitTime: 0.95
+  m_TransitionDuration: 1.5725398
+  m_TransitionOffset: 0.03778664
+  m_ExitTime: 0.053911936
   m_HasExitTime: 1
   m_HasFixedDuration: 1
   m_InterruptionSource: 0
@@ -1263,8 +1360,8 @@ AnimatorStateTransition:
   m_Mute: 0
   m_IsExit: 0
   serializedVersion: 3
-  m_TransitionDuration: 0.2500001
-  m_TransitionOffset: 0.01198141
+  m_TransitionDuration: 0.8848174
+  m_TransitionOffset: 0.03314199
   m_ExitTime: 0.06973055
   m_HasExitTime: 1
   m_HasFixedDuration: 1
@@ -1298,28 +1395,6 @@ AnimatorState:
   m_MirrorParameter: 
   m_CycleOffsetParameter: 
   m_TimeParameter: 
---- !u!1101 &7658456728552812019
-AnimatorStateTransition:
-  m_ObjectHideFlags: 1
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_Name: 
-  m_Conditions: []
-  m_DstStateMachine: {fileID: 0}
-  m_DstState: {fileID: 5934876067920876819}
-  m_Solo: 0
-  m_Mute: 0
-  m_IsExit: 0
-  serializedVersion: 3
-  m_TransitionDuration: 0.25
-  m_TransitionOffset: 0
-  m_ExitTime: 0.75
-  m_HasExitTime: 0
-  m_HasFixedDuration: 1
-  m_InterruptionSource: 0
-  m_OrderedInterruption: 1
-  m_CanTransitionToSelf: 1
 --- !u!1101 &8206564768075581269
 AnimatorStateTransition:
   m_ObjectHideFlags: 1
@@ -1345,31 +1420,6 @@ AnimatorStateTransition:
   m_InterruptionSource: 0
   m_OrderedInterruption: 1
   m_CanTransitionToSelf: 1
---- !u!1101 &8331535787116983140
-AnimatorStateTransition:
-  m_ObjectHideFlags: 1
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_Name: 
-  m_Conditions:
-  - m_ConditionMode: 1
-    m_ConditionEvent: LieDown
-    m_EventTreshold: 0
-  m_DstStateMachine: {fileID: 0}
-  m_DstState: {fileID: 533779715773965248}
-  m_Solo: 0
-  m_Mute: 0
-  m_IsExit: 0
-  serializedVersion: 3
-  m_TransitionDuration: 0.33827028
-  m_TransitionOffset: 0
-  m_ExitTime: 0
-  m_HasExitTime: 0
-  m_HasFixedDuration: 1
-  m_InterruptionSource: 0
-  m_OrderedInterruption: 1
-  m_CanTransitionToSelf: 1
 --- !u!1101 &8560810817448496124
 AnimatorStateTransition:
   m_ObjectHideFlags: 1
@@ -1379,7 +1429,7 @@ AnimatorStateTransition:
   m_Name: 
   m_Conditions:
   - m_ConditionMode: 2
-    m_ConditionEvent: isSiting
+    m_ConditionEvent: Sit_status
     m_EventTreshold: 0
   m_DstStateMachine: {fileID: 0}
   m_DstState: {fileID: 5770380076500164988}
@@ -1401,7 +1451,7 @@ AnimatorStateTransition:
   m_CorrespondingSourceObject: {fileID: 0}
   m_PrefabInstance: {fileID: 0}
   m_PrefabAsset: {fileID: 0}
-  m_Name: 
+  m_Name: to LieDown
   m_Conditions:
   - m_ConditionMode: 1
     m_ConditionEvent: LieDown
@@ -1413,7 +1463,7 @@ AnimatorStateTransition:
   m_IsExit: 0
   serializedVersion: 3
   m_TransitionDuration: 0.25000012
-  m_TransitionOffset: 0
+  m_TransitionOffset: 0.61014867
   m_ExitTime: 0.00607838
   m_HasExitTime: 0
   m_HasFixedDuration: 1

+ 1 - 1
Assets/Resources/Dog/Skin/shibaInu/amber.mat

@@ -66,7 +66,7 @@ Material:
         m_Scale: {x: 1, y: 1}
         m_Offset: {x: 0, y: 0}
     - _MainTex:
-        m_Texture: {fileID: 0}
+        m_Texture: {fileID: 2800000, guid: fadfc0dbee889ef4f90de36af00fb606, type: 3}
         m_Scale: {x: 1, y: 1}
         m_Offset: {x: 0, y: 0}
     - _MetallicGlossMap:

+ 1 - 1
Assets/Resources/Home/Particle_QuestionMark.prefab

@@ -50,7 +50,7 @@ ParticleSystem:
   emitterVelocityMode: 1
   looping: 0
   prewarm: 0
-  playOnAwake: 1
+  playOnAwake: 0
   useUnscaledTime: 0
   autoRandomSeed: 1
   startDelay:

+ 12 - 1
Assets/Resources/MessageBox/MessageBoxController.cs

@@ -26,7 +26,18 @@ public class MessageBoxController : MonoBehaviour
     public static void ShowMessage(string msg, Action callbackAction = null)
     {
         GameObject messageBox = Resources.Load<GameObject>("MessageBox/MessageBox");
-        Instantiate(messageBox);
+        // 检测是否存在MessageBox(Clone) gameobject 是否已经存在了
+        GameObject existingMessageBox = GameObject.Find("MessageBox(Clone)");
+        if (existingMessageBox == null)
+        {
+            Instantiate(messageBox);
+        }
+        else
+        {
+            //Debug.Log("MessageBox already exists, destroying the old one.");
+            Debug.Log("MessageBox already exists, destroying the old one.");
+        }
+
         if (messageBox != null)
         {
             GameObject msgBodyObject = GameObject.Find("msgBody");

+ 38 - 2
Assets/Resources/Status/StatusController.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using Newtonsoft.Json;
 using UnityEngine;
 using UnityEngine.SceneManagement;
 using UnityEngine.UIElements;
@@ -12,7 +13,7 @@ using UnityEngine.UIElements;
 public class StatusController : MonoBehaviour
 {
     private Button backButton, cancelButton;
-    private Label nameLabel, genderLabel, breedLabel, hostLabel, hostnameLabel, ageLabel, ageValueLabel,commandLabel, commandValueLabel, statusLabel, statusValueLabel;
+    private Label nameLabel, genderLabel, breedLabel, hostLabel, hostnameLabel, ageLabel, ageValueLabel,commandLabel, commandValueLabel, statusLabel, statusValueLabel, resetVoice;
     private Label leftArrow, rightArrow;
     private Label addLabel, transfer, remove, callback;
     private Label transferMsgLabel;
@@ -37,7 +38,8 @@ public class StatusController : MonoBehaviour
         ageLabel = root.Q<Label>("age");
         ageValueLabel = root.Q<Label>("ageValue");
         commandLabel = root.Q<Label>("command");
-        commandValueLabel = root.Q<Label>("commandValue");   
+        commandValueLabel = root.Q<Label>("commandValue");
+        resetVoice = root.Q<Label>("resetVoice");
         statusLabel = root.Q<Label>("status");
         statusValueLabel = root.Q<Label>("statusValue");
         selectElement = root.Q("selectElement");
@@ -57,6 +59,7 @@ public class StatusController : MonoBehaviour
         addLabel.RegisterCallback<ClickEvent>(e => AddClick(e));
         remove.RegisterCallback<ClickEvent>(e => RemoveClick(e));
         transfer.RegisterCallback<ClickEvent>(e => TransferClick(e));
+        resetVoice.RegisterCallback<ClickEvent>(e => ResetVoiceClick(e));
 
         // 箭头是否显示
         if (UserProperty.dogs.Count > 1)
@@ -192,6 +195,8 @@ public class StatusController : MonoBehaviour
         statusLabel.text = textValue;
         textValue = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "statusUI", "label", "command", EnviromentSetting.languageCode });
         commandLabel.text = textValue;
+        textValue = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "statusUI", "label", "resetVoice", EnviromentSetting.languageCode });
+        resetVoice.text = textValue;
         textValue = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "statusUI", "message", "scan_QRcode", EnviromentSetting.languageCode });
         transferMsgBasic = textValue;
     }
@@ -381,6 +386,37 @@ public class StatusController : MonoBehaviour
             GameData.focusDog = UserProperty.dogs.Count - 1;
         }
     }
+    void ResetVoiceClick(ClickEvent e)
+    {
+        // todo 重置狗的语音训练数据提示
+        string msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", "reset_voice_reminder", EnviromentSetting.languageCode });
+        msg = msg.Replace("<<dog name>>", UserProperty.dogs[GameData.focusDog].dog_name);
+        MessageBoxController.YorN_Message(msg, ResetVoiceRequest);
+    }
+    void ResetVoiceRequest()
+    {
+        // todo 重置狗的声音提交
+        string url = "/api/voice/reset/";
+        Dictionary<string, string> formData = new();
+        WWWForm form = new();
+        form.AddField("user_id", UserProperty.userId);
+        form.AddField("dog_id", UserProperty.GetDogIdByIndex(GameData.focusDog));
+        form.AddField("type", "all");
+        StartCoroutine(WebController.PostRequest(url, form, callback: ResetVoiceCallback));
+    }
+
+    void ResetVoiceCallback(string json)
+    {
+        // todo 重置狗的声音提交成功
+        var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
+        if (data != null && data["status"].ToString() == "success"){
+            // 跳转login场景,重新登录
+            MaskTransitions.TransitionManager.Instance.LoadLevel("Login");
+        }else{
+            Debug.Log(data["message"]);
+        }
+    }
+    // 点击返回按钮
     void BackBtnClick()
     {
         var uiPlaceholder = GameObject.Find("UI Placeholder");

+ 1 - 1
Assets/Resources/Status/StatusStyle.uss

@@ -16,7 +16,7 @@
     width: auto;
     left: auto;
     position: absolute;
-    -unity-font-style: bold;
+    -unity-font-style: normal;
     align-self: auto;
     justify-content: flex-start;
     align-items: auto;

+ 7 - 4
Assets/Resources/Status/StatusUI.uxml

@@ -9,10 +9,13 @@
         <ui:Label tabindex="-1" text="&lt;Host name&gt;" parse-escape-sequences="true" display-tooltip-when-elided="true" name="hostname" class="Labels" style="top: 82px; left: 101px; height: 40px; width: auto; -unity-text-align: middle-left; right: 5px;" />
         <ui:Label tabindex="-1" text="陪伴天数" parse-escape-sequences="true" display-tooltip-when-elided="true" name="age" class="Labels" style="position: absolute; top: 118px; left: 5px; height: 40px; width: 100px; align-self: auto; align-items: center; justify-content: center; -unity-text-align: middle-left; color: rgb(255, 162, 11);" />
         <ui:Label tabindex="-1" text="&lt;YY:MM:DD&gt;" parse-escape-sequences="true" display-tooltip-when-elided="true" name="ageValue" class="Labels" style="top: 118px; left: 101px; height: 40px; width: auto; -unity-text-align: middle-left; right: 5px;" />
-        <ui:Label tabindex="-1" text="   &lt;command&gt;" parse-escape-sequences="false" display-tooltip-when-elided="true" name="command" class="Labels" style="position: relative; top: 180px; left: auto; height: auto; width: 100%; align-self: flex-start; align-items: center; justify-content: center; -unity-text-align: lower-left; border-top-width: 0; border-right-width: 0; border-bottom-width: 4px; border-left-width: 0; right: auto; padding-bottom: 0; padding-right: 0; padding-top: 0; padding-left: 10px; color: rgb(255, 162, 11);" />
-        <ui:Label tabindex="-1" text="&lt;To summarize command&gt; voiceCommandSkillvoiceCommandSkill" parse-escape-sequences="true" display-tooltip-when-elided="true" name="commandValue" class="Labels" style="top: 200px; left: auto; height: 40px; width: 100%; -unity-text-align: upper-left; right: auto; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0; margin-right: 10px; margin-left: auto; margin-top: auto; margin-bottom: auto; position: absolute; white-space: normal;" />
-        <ui:Label tabindex="-1" text="   状态" parse-escape-sequences="true" display-tooltip-when-elided="true" name="status" class="Labels" style="position: absolute; top: 250px; left: auto; height: auto; width: 100%; align-self: auto; align-items: center; justify-content: center; -unity-text-align: lower-left; border-top-width: 0; border-right-width: 0; border-bottom-width: 4px; border-left-width: 0; right: auto; padding-bottom: 0; padding-right: 0; padding-top: 0; padding-left: 10px; color: rgb(255, 162, 11);" />
-        <ui:Label tabindex="-1" text="&lt;To summarize status here&gt;" parse-escape-sequences="true" display-tooltip-when-elided="true" name="statusValue" class="Labels" style="top: 270px; left: auto; height: auto; width: 100%; -unity-text-align: upper-left; right: auto; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0; margin-right: auto; margin-left: auto; margin-top: auto; margin-bottom: auto; position: absolute;" />
+        <ui:VisualElement name="summaryArea" style="flex-grow: initial; flex-shrink: initial; width: 100%; top: 177px; flex-wrap: wrap;">
+            <ui:Label tabindex="-1" text="   &lt;command&gt;" parse-escape-sequences="false" display-tooltip-when-elided="true" name="command" class="Labels" style="position: relative; top: auto; left: auto; height: auto; width: 100%; align-self: flex-start; align-items: center; justify-content: center; -unity-text-align: lower-left; border-top-width: 0; border-right-width: 0; border-bottom-width: 4px; border-left-width: 0; right: auto; padding-bottom: 0; padding-right: 0; padding-top: 0; padding-left: 10px; color: rgb(255, 162, 11);" />
+            <ui:Label tabindex="-1" text="&lt;To summarize command&gt; voiceCommandSkillvoiceCommandSkill" parse-escape-sequences="true" display-tooltip-when-elided="true" name="commandValue" class="Labels" style="top: auto; left: auto; height: 40px; width: 100%; -unity-text-align: upper-left; right: auto; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0; margin-right: 10px; margin-left: auto; margin-top: auto; margin-bottom: auto; position: relative; white-space: normal;" />
+            <ui:Label text="&lt;reset coice&gt;" name="resetVoice" enabled="true" class="Labels" style="border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0; top: auto; align-self: flex-end; padding-right: 14px; -unity-font-style: italic; font-size: 10px; position: relative; color: rgb(255, 0, 0);" />
+            <ui:Label tabindex="-1" text="   状态" parse-escape-sequences="true" display-tooltip-when-elided="true" name="status" class="Labels" style="top: auto; left: auto; height: auto; width: 100%; align-self: auto; align-items: center; justify-content: center; -unity-text-align: lower-left; border-top-width: 0; border-right-width: 0; border-bottom-width: 4px; border-left-width: 0; right: auto; padding-bottom: 0; padding-right: 0; padding-top: 0; padding-left: 10px; color: rgb(255, 162, 11); position: relative;" />
+            <ui:Label tabindex="-1" text="&lt;To summarize status here&gt;" parse-escape-sequences="true" display-tooltip-when-elided="true" name="statusValue" class="Labels" style="top: auto; left: auto; height: auto; width: 100%; -unity-text-align: upper-left; right: auto; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0; margin-right: auto; margin-left: auto; margin-top: auto; margin-bottom: auto; position: relative;" />
+        </ui:VisualElement>
         <ui:Button text="Back" parse-escape-sequences="true" display-tooltip-when-elided="true" name="back" style="position: relative; bottom: -90%; -unity-text-align: middle-center; white-space: nowrap; top: auto; left: auto; background-color: rgba(22, 131, 245, 0.78); border-left-color: rgba(149, 149, 149, 0); border-right-color: rgba(149, 149, 149, 0); border-top-color: rgba(149, 149, 149, 0); border-bottom-color: rgba(149, 149, 149, 0); border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; width: 100px; height: 30px; -unity-font: resource(&apos;Font/MaoKenZhuYuanTi-MaokenZhuyuanTi-2&apos;); font-size: 16px; color: rgb(255, 255, 255); -unity-font-style: bold; -unity-font-definition: url(&quot;project://database/Assets/Font/MaoKenZhuYuanTi-MaokenZhuyuanTi-2.ttf?fileID=12800000&amp;guid=50a63638b44907e46a3fa871d63b7d39&amp;type=3#MaoKenZhuYuanTi-MaokenZhuyuanTi-2&quot;);" />
         <ui:VisualElement name="subMenu" style="flex-grow: initial; position: absolute; height: 5%; top: auto; width: 60%; background-color: rgba(116, 116, 116, 0); border-top-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; align-items: center; justify-content: space-around; flex-direction: row; bottom: 8%; flex-shrink: initial;">
             <ui:Label name="add" class="subMenu" />

+ 5 - 1
Assets/Resources/VoiceAndManu/VoiceController.cs

@@ -93,7 +93,7 @@ public class VoiceController : MonoBehaviour
         // 狗动作变化注释镜头
         foreach (var dog in HomeController.dogsInScene)
         {
-            if (dog.dogState == DogState.IDLE)
+            if (dog.dogState == DogState.IDLE || dog.dogState == DogState.SLEEP)
             {
                 dog.RemoveZzzParticle();
                 dog.animator.SetTrigger("listen");
@@ -179,6 +179,10 @@ public class VoiceController : MonoBehaviour
         Debug.Log("录音已保存到: " + filePathWav);
         ZipFileController.ZipFile(filePathWav, filePathZip);
 
+        // 打印zip文件大小
+        FileInfo fileInfo = new FileInfo(filePathZip);
+        Debug.Log("zip文件大小: " + fileInfo.Length / 1024 + "KB");
+
         if (isCommandMode)
         {
             // command模式,调用Home Controller Command的方法上传音频文件

+ 318 - 0
Assets/Scenes/Home.unity

@@ -889,8 +889,111 @@ Transform:
   - {fileID: 1754269584}
   - {fileID: 2552538754956261542}
   - {fileID: 218172245}
+  - {fileID: 325322583}
   m_Father: {fileID: 0}
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &325322582
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 325322583}
+  - component: {fileID: 325322586}
+  - component: {fileID: 325322585}
+  - component: {fileID: 325322584}
+  m_Layer: 0
+  m_Name: Feedback
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &325322583
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 325322582}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 0, y: 0, z: 0}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 926608350}
+  m_Father: {fileID: 289564902}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 0, y: 0}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0, y: 0}
+--- !u!114 &325322584
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 325322582}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_IgnoreReversedGraphics: 1
+  m_BlockingObjects: 0
+  m_BlockingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+--- !u!114 &325322585
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 325322582}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_UiScaleMode: 0
+  m_ReferencePixelsPerUnit: 100
+  m_ScaleFactor: 1
+  m_ReferenceResolution: {x: 800, y: 600}
+  m_ScreenMatchMode: 0
+  m_MatchWidthOrHeight: 0
+  m_PhysicalUnit: 3
+  m_FallbackScreenDPI: 96
+  m_DefaultSpriteDPI: 96
+  m_DynamicPixelsPerUnit: 1
+  m_PresetInfoIsWorld: 0
+--- !u!223 &325322586
+Canvas:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 325322582}
+  m_Enabled: 1
+  serializedVersion: 3
+  m_RenderMode: 0
+  m_Camera: {fileID: 0}
+  m_PlaneDistance: 100
+  m_PixelPerfect: 0
+  m_ReceivesEvents: 1
+  m_OverrideSorting: 0
+  m_OverridePixelPerfect: 0
+  m_SortingBucketNormalizedSize: 0
+  m_VertexColorAlwaysGammaSpace: 0
+  m_AdditionalShaderChannelsFlag: 0
+  m_UpdateRectTransformForStandalone: 0
+  m_SortingLayerID: 0
+  m_SortingOrder: 0
+  m_TargetDisplay: 0
 --- !u!1001 &466008848
 PrefabInstance:
   m_ObjectHideFlags: 0
@@ -1145,6 +1248,7 @@ MonoBehaviour:
   - {fileID: 8300000, guid: 2734284e366ce1b46b0c68d77c7cc6cc, type: 3}
   - {fileID: 8300000, guid: 5987681976a7b354d8e20218e529a194, type: 3}
   - {fileID: 8300000, guid: a5736db3e0483874baa9cdc52752f7d8, type: 3}
+  - {fileID: 8300000, guid: f8ec1ba43d286d74aa414e8e863134ce, type: 3}
 --- !u!82 &481637091
 AudioSource:
   m_ObjectHideFlags: 0
@@ -12136,6 +12240,70 @@ MonoBehaviour:
   m_LightCookieSize: {x: 1, y: 1}
   m_LightCookieOffset: {x: 0, y: 0}
   m_SoftShadowQuality: 0
+--- !u!1 &926608349
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 926608350}
+  - component: {fileID: 926608352}
+  - component: {fileID: 926608351}
+  m_Layer: 0
+  m_Name: UIDocument
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &926608350
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 926608349}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 325322583}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &926608351
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 926608349}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: ac67974180f864edb845fb446a042844, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+--- !u!114 &926608352
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 926608349}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 19102, guid: 0000000000000000e000000000000000, type: 0}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_PanelSettings: {fileID: 11400000, guid: 7ca44f0cc21b574428c09a7b6ce95659, type: 2}
+  m_ParentUI: {fileID: 0}
+  sourceAsset: {fileID: 9197481963319205126, guid: 0b273dee47ec64c16bd0f42928bdba86, type: 3}
+  m_SortingOrder: 0
+  m_WorldSpaceSizeMode: 1
+  m_WorldSpaceWidth: 1920
+  m_WorldSpaceHeight: 1080
 --- !u!1001 &943629538
 PrefabInstance:
   m_ObjectHideFlags: 0
@@ -13862,6 +14030,155 @@ RectTransform:
   m_CorrespondingSourceObject: {fileID: 8435704930564478781, guid: 00b97733408f83840b44ba387e9ae31b, type: 3}
   m_PrefabInstance: {fileID: 1754269583}
   m_PrefabAsset: {fileID: 0}
+--- !u!1 &1870212737
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1870212740}
+  - component: {fileID: 1870212739}
+  - component: {fileID: 1870212738}
+  m_Layer: 0
+  m_Name: Dog Bark Player
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &1870212738
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1870212737}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 1138d19d967b04638903c1710eace1db, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  audioSource: {fileID: 1870212739}
+  soundEffect:
+  - {fileID: 8300000, guid: 185b50e3eb2688c47aea9fe78d00e373, type: 3}
+  - {fileID: 8300000, guid: da2d13d15f67c0441911b49ba211baf5, type: 3}
+  - {fileID: 8300000, guid: 682acbad74a855744820758a3cd35060, type: 3}
+  - {fileID: 8300000, guid: e18660fd2dbeb1a4fb409444c343ed67, type: 3}
+  - {fileID: 8300000, guid: 429c5a09e49eadf43bf9c2a3322f5c7f, type: 3}
+--- !u!82 &1870212739
+AudioSource:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1870212737}
+  m_Enabled: 1
+  serializedVersion: 4
+  OutputAudioMixerGroup: {fileID: 0}
+  m_audioClip: {fileID: 0}
+  m_Resource: {fileID: 0}
+  m_PlayOnAwake: 1
+  m_Volume: 1
+  m_Pitch: 1
+  Loop: 0
+  Mute: 0
+  Spatialize: 0
+  SpatializePostEffects: 0
+  Priority: 128
+  DopplerLevel: 1
+  MinDistance: 1
+  MaxDistance: 500
+  Pan2D: 0
+  rolloffMode: 0
+  BypassEffects: 0
+  BypassListenerEffects: 0
+  BypassReverbZones: 0
+  rolloffCustomCurve:
+    serializedVersion: 2
+    m_Curve:
+    - serializedVersion: 3
+      time: 0
+      value: 1
+      inSlope: 0
+      outSlope: 0
+      tangentMode: 0
+      weightedMode: 0
+      inWeight: 0.33333334
+      outWeight: 0.33333334
+    - serializedVersion: 3
+      time: 1
+      value: 0
+      inSlope: 0
+      outSlope: 0
+      tangentMode: 0
+      weightedMode: 0
+      inWeight: 0.33333334
+      outWeight: 0.33333334
+    m_PreInfinity: 2
+    m_PostInfinity: 2
+    m_RotationOrder: 4
+  panLevelCustomCurve:
+    serializedVersion: 2
+    m_Curve:
+    - serializedVersion: 3
+      time: 0
+      value: 0
+      inSlope: 0
+      outSlope: 0
+      tangentMode: 0
+      weightedMode: 0
+      inWeight: 0.33333334
+      outWeight: 0.33333334
+    m_PreInfinity: 2
+    m_PostInfinity: 2
+    m_RotationOrder: 4
+  spreadCustomCurve:
+    serializedVersion: 2
+    m_Curve:
+    - serializedVersion: 3
+      time: 0
+      value: 0
+      inSlope: 0
+      outSlope: 0
+      tangentMode: 0
+      weightedMode: 0
+      inWeight: 0.33333334
+      outWeight: 0.33333334
+    m_PreInfinity: 2
+    m_PostInfinity: 2
+    m_RotationOrder: 4
+  reverbZoneMixCustomCurve:
+    serializedVersion: 2
+    m_Curve:
+    - serializedVersion: 3
+      time: 0
+      value: 1
+      inSlope: 0
+      outSlope: 0
+      tangentMode: 0
+      weightedMode: 0
+      inWeight: 0.33333334
+      outWeight: 0.33333334
+    m_PreInfinity: 2
+    m_PostInfinity: 2
+    m_RotationOrder: 4
+--- !u!4 &1870212740
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1870212737}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 8.210003, y: 8.961659, z: 16.81742}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
 --- !u!1 &1886356400
 GameObject:
   m_ObjectHideFlags: 0
@@ -14759,3 +15076,4 @@ SceneRoots:
   - {fileID: 571881222}
   - {fileID: 652255264}
   - {fileID: 723885005}
+  - {fileID: 1870212740}

+ 8 - 0
Assets/Scenes/Home_Profiles/User Feedback UI.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c6b2779f0cd4c4b54a784bd0f9d7fed1
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 11 - 0
Assets/Scenes/Home_Profiles/User Feedback UI/User Feedback.uxml

@@ -0,0 +1,11 @@
+<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
+    <Style src="project://database/Assets/UI%20Toolkit/Style/rootStyle.uss?fileID=7433441132597879392&amp;guid=b30eb17a0ca8bf64087af4e59d565fdd&amp;type=3#rootStyle" />
+    <ui:VisualElement class="rootStyle" style="flex-grow: 1;">
+        <ui:DropdownField label="&lt;type&gt;" name="type" class="dropdownField" />
+        <ui:TextField label="&lt;feedback&gt;" name="feedback" class="textField__multiline" />
+        <ui:VisualElement style="flex-grow: initial; flex-direction: row; flex-shrink: initial; justify-content: space-evenly;">
+            <ui:Button text="&lt;submit&gt;" name="submit" class="button" style="align-self: center; background-color: rgba(0, 0, 255, 0.78); color: rgb(255, 255, 255);" />
+            <ui:Button text="&lt;cancel&gt;" name="cancel" class="button" style="align-self: center; background-color: rgba(255, 255, 255, 0.78);" />
+        </ui:VisualElement>
+    </ui:VisualElement>
+</ui:UXML>

+ 10 - 0
Assets/Scenes/Home_Profiles/User Feedback UI/User Feedback.uxml.meta

@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 0b273dee47ec64c16bd0f42928bdba86
+ScriptedImporter:
+  internalIDToNameTable: []
+  externalObjects: {}
+  serializedVersion: 2
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
+  script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

+ 45 - 0
Assets/Scenes/Login.unity

@@ -2588,6 +2588,50 @@ MonoBehaviour:
     m_MipBias: 0
     m_VarianceClampScale: 0.9
     m_ContrastAdaptiveSharpening: 0
+--- !u!1 &967734711
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 967734713}
+  - component: {fileID: 967734712}
+  m_Layer: 0
+  m_Name: SystemLoader
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &967734712
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 967734711}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: b0882e3ae4ff64b0a8906472d57e16d9, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+--- !u!4 &967734713
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 967734711}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 8.210003, y: 8.961659, z: 16.81742}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
 --- !u!1 &972508926
 GameObject:
   m_ObjectHideFlags: 0
@@ -5305,3 +5349,4 @@ SceneRoots:
   - {fileID: 1043721802}
   - {fileID: 332222583}
   - {fileID: 385225560}
+  - {fileID: 967734713}

+ 1 - 0
Assets/Scripts/Develop Script/TestSetup.cs

@@ -22,6 +22,7 @@ public class TestSetup : MonoBehaviour
         if (SceneManager.GetActiveScene().name == "Home")
         {
             GameData.isVoiceTrainingToday = false;
+            // GameData.isFirstInteraction = true;
         }
 
         if (SceneManager.GetActiveScene().name == "Playground")

+ 15 - 0
Assets/Scripts/EnviromentController.cs

@@ -100,12 +100,27 @@ public class EnviromentController : MonoBehaviour
                 GameData.isVoiceTrainingToday = true;
             }
         }
+        
         if (PlayerPrefs.HasKey("lastFeedbackTime"))
         {
             // 读取存储的日期
             string lastFeedbackTime = PlayerPrefs.GetString("lastFeedbackTime");
             GameData.lastFeedbackTime = DateTime.Parse(lastFeedbackTime);
         }
+
+        // if (PlayerPrefs.HasKey("isFirstInteraction"))
+        // {
+        //     string isFirstInteraction = PlayerPrefs.GetString("isFirstInteraction");
+        //     if (isFirstInteraction == "true")
+        //     {
+        //         GameData.isFirstInteraction = true;
+        //     }
+        //     else
+        //     {
+        //         GameData.isFirstInteraction = false;
+        //     }
+        // }
+
     }
     // Update is called once per frame
     //void Update()

+ 53 - 0
Assets/Scripts/Functions/LogSystem.cs

@@ -0,0 +1,53 @@
+using System;
+using System.IO;
+using UnityEngine;
+
+/* 本文件为日志系统的实现
+ * 该系统用于记录游戏运行时的日志信息,包括普通日志、错误日志和警告日志
+ * 日志信息将被保存到指定路径的文件中,便于后续查看和分析
+ */
+ 
+public class LogSystem : MonoBehaviour
+{
+    public static LogSystem Instance { get; private set; }
+
+    private string logFilePath;
+
+    private void Awake()
+    {
+        if (Instance == null)
+        {
+            Instance = this;
+            DontDestroyOnLoad(gameObject);
+        }
+        else
+        {
+            Destroy(gameObject);
+        }
+
+        // 设置日志文件路径
+        logFilePath = Application.persistentDataPath + "/logs/" + UserProperty.userId + ".log";
+        Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
+    }
+
+    public void Log(string message)
+    {
+        string logMessage = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " - " + message;
+        Debug.Log(logMessage);
+        File.AppendAllText(logFilePath, logMessage + Environment.NewLine);
+    }
+
+    public void LogError(string message)
+    {
+        string logMessage = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " - ERROR: " + message;
+        Debug.LogError(logMessage);
+        File.AppendAllText(logFilePath, logMessage + Environment.NewLine);
+    }
+
+    public void LogWarning(string message)
+    {
+        string logMessage = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " - WARNING: " + message;
+        Debug.LogWarning(logMessage);
+        File.AppendAllText(logFilePath, logMessage + Environment.NewLine);
+    }
+}

+ 2 - 0
Assets/Scripts/Functions/LogSystem.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: b0882e3ae4ff64b0a8906472d57e16d9

+ 1 - 1
Assets/Scripts/GameControllers/GameData.cs

@@ -2,7 +2,6 @@
  */
 
 using System;
-using System.Net.NetworkInformation;
 
 public static class GameData
 {
@@ -12,6 +11,7 @@ public static class GameData
     public static string playedToy = string.Empty;        // 用于暂存游戏中使用的玩具
     public static string bathItemId = string.Empty;        // 用于暂存洗澡场景中使用的道具
     public static bool isVoiceTrainingToday;        // 是否今天已经进行过语音训练
+    // public static bool isFirstInteraction = true;        // 是否第一次互动
     public static DateTime lastFeedbackTime = new DateTime(2000, 1, 1);        // 上次反馈的时间
 
 }

+ 13 - 0
Assets/Scripts/GameControllers/GameTool.cs

@@ -80,4 +80,17 @@ public static class GameTool
         }
         return dogNameAllowed;
     }
+
+    // 恢复游戏时间运行
+    public static void ResumeGameTime()
+    {
+        Time.timeScale = 1;
+        Time.fixedDeltaTime = 0.02f * Time.timeScale;
+    }
+    // 暂停游戏时间运行
+    public static void PauseGameTime()
+    {
+        Time.timeScale = 0;
+        Time.fixedDeltaTime = 0.02f * Time.timeScale;
+    }
 }

+ 41 - 0
Assets/Scripts/Home/DogBarkController.cs

@@ -0,0 +1,41 @@
+using System.Collections;
+using System.Net.NetworkInformation;
+using UnityEngine;
+
+/* Home场景全局控制音效播放
+* 本代码挂在在Home场景的Player上
+ */
+
+public class DogBarkController: MonoBehaviour
+{
+    public static DogBarkController Instance;
+    //音效相关
+    public AudioSource audioSource;
+    public AudioClip[] soundEffect;
+
+    void Awake()
+    {
+        // 单例模式,确保只有一个GlobalSoundManager
+        if (Instance == null)
+        {
+            Instance = this;
+            //DontDestroyOnLoad(gameObject);        // 必须关掉否则会导致原场景destroy不能执行
+        }
+        else
+        {
+            Destroy(gameObject);
+        }
+    }
+
+
+    public void PlayDogBarkWithDelay(int id,  float delay=0.0f)
+    {
+        StartCoroutine(PlayDogBarkCorountine(id, delay));
+    }
+
+    private IEnumerator PlayDogBarkCorountine(int id, float delay=0.0f)
+    {
+        yield return new WaitForSeconds(delay);
+        audioSource.PlayOneShot(soundEffect[id]);
+    }
+}

+ 2 - 0
Assets/Scripts/Home/DogBarkController.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 1138d19d967b04638903c1710eace1db

+ 36 - 15
Assets/Scripts/Home/DogInScene.cs

@@ -44,9 +44,12 @@ public class DogInScene //: ScriptableObject
     #region 通用函数段
 
     // 这个函数主要是为了在狗的属性发生变化时,重新加载狗的属性
-    public void ReloadDogProperty(){
-        foreach (var dog in UserProperty.dogs){
-            if (dog.d_id == dogProperty.d_id){
+    public void ReloadDogProperty()
+    {
+        foreach (var dog in UserProperty.dogs)
+        {
+            if (dog.d_id == dogProperty.d_id)
+            {
                 this.dogProperty = dog;
                 break;
             }
@@ -64,11 +67,12 @@ public class DogInScene //: ScriptableObject
     public DogInScene(DogProperty property)
     {
         this.dogProperty = property;
-        this.activeIndex = (int)Math.Round((property.liveliness + property.intimate) * UnityEngine.Random.Range(0.3f, 0.7f));
+        this.activeIndex = (int)Math.Round((property.liveliness + property.intimate) * UnityEngine.Random.Range(0.01f, 0.5f));
         this.isMoving = false;
     }
 
-    public void RemoveZzzParticle(){
+    public void RemoveZzzParticle()
+    {
         // 关闭狗的睡觉粒子特效
         var zzzParticle = gameObject.transform.Find("zzzParticle").gameObject;
         if (zzzParticle != null)
@@ -78,7 +82,8 @@ public class DogInScene //: ScriptableObject
     }
 
     // 关闭所有animation动画的状态,回到默认的状态
-    public void ResetAnimationStatus(){
+    public void ResetAnimationStatus()
+    {
 
         // 获取所有参数
         AnimatorControllerParameter[] parameters = animator.parameters;
@@ -96,12 +101,27 @@ public class DogInScene //: ScriptableObject
     // 启动交互行为准备过程
     public void SetupInteract()
     {
+        Debug.Log("SetupInteract:" + this.gameObject.name);
+        DogBarkController.Instance.PlayDogBarkWithDelay(3);    // 狗叫相应一下
+        if (dogProperty.voiceCall == 10)
+        {
+            // GameData.isFirstInteraction = false;
+            PlayerPrefs.SetString("isFirstInteraction", "false");
+            PlayerPrefs.Save();
+            GameTool.PauseGameTime();
+            string msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", "first_touch_interactive", EnviromentSetting.languageCode });
+            MessageBoxController.ShowMessage(msg, () => GameTool.ResumeGameTime());
+
+        }
         // 加载Interact animator controller,避免过于复杂的Animator Controller
         Animator animator = gameObject.GetComponent<Animator>();
         RuntimeAnimatorController animatorController = Resources.Load<RuntimeAnimatorController>("Dog/AnimatorController/shibaInu/HomeDogInteractController");
         if (dogProperty.breed == "shibaInu") { animatorController = Resources.Load<RuntimeAnimatorController>("Dog/AnimatorController/shibaInu/HomeDogInteractController"); }
         animator.runtimeAnimatorController = animatorController;
 
+        float randomIndex = UnityEngine.Random.Range(0, 1f);
+        animator.SetFloat("randomIndex", randomIndex);
+
         //this.dogState = "interact";
         this.dogState = DogState.INTERACT;       // 设置狗的状态为交互状态
         this.interactLastUpdate = DateTime.Now;
@@ -110,6 +130,7 @@ public class DogInScene //: ScriptableObject
 
         // 如果狗距离超出一定范围才开始移动
         float distance = Vector3.Distance(gameObject.transform.position, moveToLocation);
+        Debug.Log(this.gameObject.name + "interact move to player distance:" + distance);
         if (distance > 2.5f)
         {
             this.animator.SetTrigger("move");       // 切换为走路动画
@@ -141,7 +162,7 @@ public class DogInScene //: ScriptableObject
         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动画
+            this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, dogProperty.runSpeed * (1 + moveSpeed) * 0.02f * moveSpeedAdj);  // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应RM动画.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, dogProperty.runSpeed * (1 + moveSpeed) * 0.02f * moveSpeedAdj);  // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应RM动画
         }
         else
         {
@@ -168,17 +189,17 @@ public class DogInScene //: ScriptableObject
     }
 
     // 交互动画行为计时器(暂时设定为6秒)
-    // 考虑一下是否需要这个功能,如果不需要就删除
-    public void InteractAnimationTimeout()
+    public IEnumerator InteractAnimationCountDown(float seconds = 6.0f)
     {
 
         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>();
-            animator.SetBool(interactAnimation, false);
+        if (ts.TotalSeconds < 6){
+            yield return new WaitForSeconds(0.25f);
+        }
+        else{
+            Debug.Log("InteractAnimation count down stop:" + this.gameObject.name);
+            this.ResetAnimationStatus();
         }
     }
 
@@ -194,7 +215,7 @@ public class DogInScene //: ScriptableObject
         animator.runtimeAnimatorController = animatorController;
         this.RandomMove();
     }
-    
+
     // 狗播放问号的表情
     public void PlayQuestionMark()
     {

+ 150 - 82
Assets/Scripts/Home/HomeController.cs

@@ -46,6 +46,7 @@ public class HomeController : MonoBehaviour
     private string trainingDogId = "";        // 训练的狗id
     private bool isTrainingMsgShowed_1 = false;        // 第一条是否已经显示训练提示
     private bool isTrainingMsgShowed_2 = false;        // 第二条是否已经显示训练提示
+    private bool isTrainingAnimationPlayed = false;        // 训练动画是否已经播放
 
     private void Awake()
     {
@@ -118,31 +119,21 @@ public class HomeController : MonoBehaviour
             }
 
             // 生成一个数据数用于随机开启动画,如果和狗的randomFactor相同就开启动画
-            int randomCheck = UnityEngine.Random.Range(0, 51);
+            int sceneRandomFactor = UnityEngine.Random.Range(0, 51);
 
             // 检测是否有狗没有通过voiceCall训练,如果有,立刻进入训练模式
             if (sceneMode == SceneMode.NORMAL)        // 这段代码用于在NORMAL场景下检测是否有狗进入训练模式
             {
                 foreach (var dog in dogsInScene)
                 {
+                    if (trainingContent != String.Empty) { break; }        // 如果已经有狗进入训练模式,跳出循环
                     if (!dog.dogProperty.voiceCallEnable)
                     {
-                        //isTrainingMode = true;
-                        sceneMode = SceneMode.TRAINING;
-                        dog.RemoveZzzParticle();
                         trainingContent = "voiceCall";
-                        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;
-                        VoiceButtonOnlySwitch(true);        // 交互模式下关闭其他菜单
                     }
-                    else if (dog.dogProperty.voiceCall > 40 && dog.dogProperty.voiceCallEnable && !GameData.isVoiceTrainingToday)
+                    else if (dog.dogProperty.voiceCall >= 40 && dog.dogProperty.voiceCallEnable && !GameData.isVoiceTrainingToday)
                     {
-                        // 当狗的voiceCall大于40,进入第一阶段指令训练模式
+                        // 当狗的voiceCall大于等于40,进入第一阶段指令训练模式
                         int random = UnityEngine.Random.Range(0, 100);
                         if (random < 25 && !dog.dogProperty.commandSit)
                         {
@@ -160,33 +151,55 @@ public class HomeController : MonoBehaviour
                         {
                             trainingContent = "commandLieDown";
                         }
-                        else
+                        // else
+                        // {
+                        //     trainingContent = String.Empty;
+                        // }
+                    }
+                    else if (dog.dogProperty.voiceCommand >= 40 && dog.dogProperty.voiceCommandEnable && !GameData.isVoiceTrainingToday)
+                    {
+                        // 当狗的voiceCommand大于等于40,进入第二阶段指令训练模式
+                        int random = UnityEngine.Random.Range(0, 100);
+                        if (random < 20 && !dog.dogProperty.commandRotate)
                         {
-                            trainingContent = String.Empty;
-                            GameData.isVoiceTrainingToday = true;
+                            trainingContent = "commandRotate";
                         }
-
-                        if (trainingContent != String.Empty)
+                        else if (random < 40 && !dog.dogProperty.commandHug)
                         {
-                            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;
-                            VoiceButtonOnlySwitch(true);        // 交互模式下关闭其他菜单
-
-                            // 开始训练时让狗播放动画
-                            if (trainingContent != "voiceCall")
-                            {
-                                string command = trainingContent.Substring(7);
-                                dog.animator.SetTrigger(command);
-                                dog.animator.SetBool("is" + command + "ing", true);
-                            }
+                            trainingContent = "commandHug";
                         }
+                        else if (random < 60 && !dog.dogProperty.commandDeath)
+                        {
+                            trainingContent = "commandDeath";
+                        }
+                        else if (random < 80 && !dog.dogProperty.commandTurnL)
+                        {
+                            trainingContent = "commandTurnL";
+                        }
+                        else if (random < 100 && !dog.dogProperty.commandTurnR)
+                        {
+                            trainingContent = "commandTurnR";
+                        }
+                    }
+                    else
+                    {
+                        trainingContent = String.Empty;
+                    }
+
+                    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);        // 交互模式下关闭其他菜单
+
                     }
                 }
             }
@@ -206,10 +219,25 @@ public class HomeController : MonoBehaviour
                         }
                         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)
@@ -221,6 +249,10 @@ public class HomeController : MonoBehaviour
                             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;
                             }
@@ -293,7 +325,7 @@ public class HomeController : MonoBehaviour
                             dog.RandomMove();
                         }
 
-                        else if (randomCheck == dog.randomFactor && !dog.isSleeping)        // 当狗自身的随机数和系统随机数相同时候触发。约100秒触发一次。
+                        else if (sceneRandomFactor == dog.randomFactor && !dog.isSleeping)        // 当狗自身的随机数和系统随机数相同时候触发。约100秒触发一次。
                         {
                             TimeSpan ts = DateTime.Now - dog.animationStartTime;
                             if (ts.Seconds >= 30)        // 如果距离上一个动作超过30秒就可以开始新的动作
@@ -333,8 +365,6 @@ public class HomeController : MonoBehaviour
     //void InitialScene()
     IEnumerator InitialScene()
     {
-        //yield return null;     
-        //yield return null;     
         yield return null;      // 跳过三帧,初始化最多三只狗
         //Debug.Log(isInitialDone);
         foreach (var dog in UserProperty.dogs)
@@ -461,6 +491,11 @@ public class HomeController : MonoBehaviour
     // 计算多只狗的中心位置,用于主摄像机瞄准
     private Vector3 CenterOfDogs()
     {
+        if (dogsInScene.Count == 0)
+        {
+            return Vector3.zero;
+        }
+        
         Vector3 center = Vector3.zero;
         foreach (var dog in dogsInScene)
         {
@@ -480,13 +515,7 @@ public class HomeController : MonoBehaviour
         WWWForm form = new();
         form.AddField("user_id", UserProperty.userId);
 
-        // TODO 待后台开发完成后,开启网络通讯功能,目前暂用临时直接赋值
         StartCoroutine(WebController.PostRequest(url, form, filePath, callback: VoiceCallCallback));
-        sceneMode = SceneMode.INACTIVE;     // 场景进入交互模式
-        //isInteractMode = true;        // 场景进入交互模式
-        dogsInScene[0].SetupInteract();
-        interactDog = dogsInScene[0].gameObject;
-        VoiceButtonOnlySwitch(true);        // 交互模式下关闭其他菜单
     }
 
     // 语音呼唤上传回调函数
@@ -507,39 +536,54 @@ public class HomeController : MonoBehaviour
             var scoresList = JsonConvert.DeserializeObject<Dictionary<string, float>>(scores);
             foreach (var score in scoresList)
             {
-                if (score.Value > highestScore)
+                // 根据狗的数量度修正得分。计算方式为狗的voiceCall属性值/1000
+                int dogIndex = UserProperty.GetDogIndexById(score.Key);
+                if (dogIndex < 0)
                 {
-                    highestScore = score.Value;
+                    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 >= 60)        // 60分以上才可以进入交互模式
+            if (highestScore >= 0.6)        // 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))
+                        // 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)
                         {
-                            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)
                             {
-                                if (otherDog.dogProperty.d_id != highestScoreDogId)
-                                {
-                                    otherDog.gameObject.SetActive(false);
-                                }
+                                otherDog.gameObject.SetActive(false);
                             }
                         }
+                        // }
                     }
                 }
+                HomeSoundEffectController.Instance.PlaySoundEffect(5);
             }
             else
             {
@@ -556,6 +600,7 @@ public class HomeController : MonoBehaviour
     // 用户语音呼唤上传,Voice call指令用于呼唤所有的狗,得分最高的过来进入交互模式
     public void VoiceCommandRequest(string filePath)
     {
+        //Debug.Log("Voice Command Post request");
         if (sceneMode == SceneMode.INACTIVE)
         {
             Debug.Log("Voice Command Post request");
@@ -569,7 +614,15 @@ public class HomeController : MonoBehaviour
         }
         else if (sceneMode == SceneMode.TRAINING)
         {
+            // todo 临时代码查上传数据
             Debug.Log("Voice training Post request");
+            Debug.Log("filepath:" + filePath);
+            Debug.Log("dog_id:" + UserProperty.dogs[GameData.focusDog].d_id);
+            Debug.Log("user_id:" + UserProperty.userId);
+            Debug.Log("trainingContent:" + trainingContent);
+            Debug.Log("current times:" + this.currentTrainingTimes.ToString());
+            Debug.Log("total times:" + totalTrainingTimes.ToString());
+
             //Debug.Log("current times before ++:" + this.currentTrainingTimes.ToString());
             this.currentTrainingTimes++;
             string url = "/api/voice/training/";
@@ -612,24 +665,17 @@ public class HomeController : MonoBehaviour
                         highestScoreCommand = score.Key;
                     }
                 }
-
+                dogsInScene[GameData.focusDog].ResetAnimationStatus();        // 重置狗的动画状态
                 if (highestScore >= 60)
                 {
-
-                    if (GameTool.Random100Check(dogsInScene[GameData.focusDog].dogProperty.voiceCommand))
-                    {
-                        string animationTrigger = highestScoreCommand.Substring(5);
-                        string animationBool = "is" + highestScoreCommand + "ing";
-                        var animator = dogsInScene[GameData.focusDog].gameObject.GetComponent<Animator>();
-                        animator.SetTrigger(animationTrigger);
-                        if (animationBool != "isSiting" || animationBool != "isLieing" || animationBool != "isDieing")
-                        {
-                            animator.SetBool(animationBool, true);
-                            dogsInScene[GameData.focusDog].interactAnimation = animationBool;
-                            dogsInScene[GameData.focusDog].interactAnimationStartTime = DateTime.Now;
-                        }
-                    }
-
+                    string animationTrigger = highestScoreCommand.Substring(7);
+                    string animationBool = highestScoreCommand + "_status";
+                    var animator = dogsInScene[GameData.focusDog].gameObject.GetComponent<Animator>();
+                    animator.SetTrigger(animationTrigger);
+                    animator.SetBool(animationBool, true);
+
+                    // 交互动画执行一段时间后停止
+                    StartCoroutine(dogsInScene[GameData.focusDog].InteractAnimationCountDown());
                 }
                 else
                 {
@@ -666,7 +712,7 @@ public class HomeController : MonoBehaviour
                     }
 
                     string msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", trainingContent + "_10", EnviromentSetting.languageCode });
-                    Time.timeScale = 0f;
+                    GameTool.PauseGameTime();
 
                     MessageBoxController.ShowMessage(msg, ExitTrainingMode);
                     this.sceneMode = SceneMode.NORMAL;
@@ -683,7 +729,7 @@ public class HomeController : MonoBehaviour
                     HomeSoundEffectController.Instance.PlaySoundEffect(4);
 
                     string msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", trainingContent + "_20", EnviromentSetting.languageCode });
-                    Time.timeScale = 0f;
+                    GameTool.PauseGameTime();
                     MessageBoxController.ShowMessage(msg, RestartTraining);
                 }
             }
@@ -714,13 +760,24 @@ public class HomeController : MonoBehaviour
         trainingDogId = "";
         isTrainingMsgShowed_1 = false;
         isTrainingMsgShowed_2 = false;
+        isTrainingAnimationPlayed = false;
+        sceneMode = SceneMode.NORMAL;       // 交互模式
         Debug.Log("Reset Training Mode Parameters");
-        Time.timeScale = 1f;
+        GameTool.ResumeGameTime();
+        GameData.isVoiceTrainingToday = true;        // 训练完成,设置为true
         var BGM = GameObject.Find("BGM");
         if (BGM != null)
         {
             FadeBGM(BGM.GetComponent<AudioSource>(), true);
         }
+        // 恢复因为交互,训练模式隐藏的狗
+        // foreach (var dog in dogsInScene)
+        // {
+        //     if (dog.gameObject.activeSelf == false)
+        //     {
+        //         dog.gameObject.SetActive(true);
+        //     }
+        // }
     }
 
     private void RestartTraining()
@@ -776,7 +833,7 @@ public class HomeController : MonoBehaviour
                     previousPointerPosition = pointerPosition;
                 }
             }
-            if (interactTime > 3)        // 如果交互时间超过1秒,播放心形粒子效果
+            if (interactTime > 2.5)        // 如果交互时间超过1秒,播放心形粒子效果
             {
                 HeartParticlePlay();
                 var animation = interactDog.GetComponent<Animator>();
@@ -822,10 +879,21 @@ public class HomeController : MonoBehaviour
         if (!fadeIn)
         {
             bgmSource.Stop(); // 如果是淡出,停止播放
-        }else{
+        }
+        else
+        {
             bgmSource.Play(); // 如果是淡入,开始播放
         }
     }
+
+    // 刷新dogInScene的狗数据
+    public void RefreshDogInScene()
+    {
+        foreach (var dog in dogsInScene)
+        {
+            dog.ReloadDogProperty();
+        }
+    }
     #endregion
 }
 

+ 2 - 1
Assets/Scripts/Home/HomeSoundEffectController.cs

@@ -1,7 +1,8 @@
-using System.Net.NetworkInformation;
+using System.Collections;
 using UnityEngine;
 
 /* Home场景全局控制音效播放
+* 本代码挂在在Home场景的Player上
  */
 
 public class HomeSoundEffectController: MonoBehaviour

+ 72 - 0
Assets/Scripts/Home/UserFeedbackController.cs

@@ -0,0 +1,72 @@
+using UnityEngine;
+using UnityEngine.UIElements;
+
+/* 用于管理用户反馈界面和提交
+*/
+
+public class UserFeedbackController : MonoBehaviour
+{
+    // Start is called once before the first execution of Update after the MonoBehaviour is created
+    private DropdownField type;
+    private TextField feedback;
+    private Button submit, cancel;
+    private string typeOption0, typeOption1;
+    void Awake()
+    {
+        var root = GetComponent<UIDocument>().rootVisualElement;
+        type = root.Q<DropdownField>("type");
+        feedback = root.Q<TextField>("feedback");
+        submit = root.Q<Button>("submit");
+        cancel = root.Q<Button>("cancel");
+
+        InitSetting();
+
+        cancel.RegisterCallback<ClickEvent>(ev => CancelClick());
+    }
+
+    // Update is called once per frame
+    void Update()
+    {
+        if(feedback.text.Trim() == "")
+        {
+            submit.SetEnabled(false);
+        }
+        else
+        {
+            submit.SetEnabled(true);
+        }
+    }
+
+    void InitSetting(){
+        string textValue = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "FeedbackUI", "button", "submit", EnviromentSetting.languageCode });
+        submit.text = textValue;
+        textValue = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "FeedbackUI", "button", "cancel", EnviromentSetting.languageCode });
+        cancel.text = textValue;
+        textValue = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "FeedbackUI", "label", "type", EnviromentSetting.languageCode });
+        type.label = textValue;
+        textValue = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "FeedbackUI", "label", "feedback", EnviromentSetting.languageCode });
+        feedback.label = textValue;
+
+        string typeOption0 = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "FeedbackUI", "label", "option_0", EnviromentSetting.languageCode });
+        string typeOption1 = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "FeedbackUI", "label", "option_1", EnviromentSetting.languageCode });
+
+        type.choices.Clear();
+        type.choices.Add(typeOption0);
+        type.choices.Add(typeOption1);
+        type.value = typeOption0;
+    }
+
+     void CancelClick()
+    {
+         HomeSoundEffectController.Instance.PlaySoundEffect(2);
+
+        var uiPlaceholder = GameObject.Find("UI Placeholder");
+        if (uiPlaceholder != null)
+        {
+            var FeedbackUI = uiPlaceholder.transform.Find("Feedback").gameObject;
+            var UserInfoUI = uiPlaceholder.transform.Find("User Info").gameObject;
+            FeedbackUI.SetActive(false);
+            UserInfoUI.SetActive(false);
+        }
+    }
+}

+ 2 - 0
Assets/Scripts/Home/UserFeedbackController.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: ac67974180f864edb845fb446a042844