Prechádzať zdrojové kódy

3月30日更

2025/3/30	Userproperty添加根据dog_id和Gamedata.focusdog index互查函数
Home场景为语音接入做好准备,目标狗可以移到镜头前
Kenny Chen 2 mesiacov pred
rodič
commit
bc3ef87d9f

+ 84 - 0
Assets/Resources/Item/Materials/Red.mat

@@ -0,0 +1,84 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+  serializedVersion: 8
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_Name: Red
+  m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
+  m_Parent: {fileID: 0}
+  m_ModifiedSerializedProperties: 0
+  m_ValidKeywords: []
+  m_InvalidKeywords: []
+  m_LightmapFlags: 4
+  m_EnableInstancingVariants: 0
+  m_DoubleSidedGI: 0
+  m_CustomRenderQueue: -1
+  stringTagMap: {}
+  disabledShaderPasses: []
+  m_LockedProperties: 
+  m_SavedProperties:
+    serializedVersion: 3
+    m_TexEnvs:
+    - _BumpMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailAlbedoMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailMask:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailNormalMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _EmissionMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _MainTex:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _MetallicGlossMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _OcclusionMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _ParallaxMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    m_Ints: []
+    m_Floats:
+    - _BumpScale: 1
+    - _Cutoff: 0.5
+    - _DetailNormalMapScale: 1
+    - _DstBlend: 0
+    - _GlossMapScale: 1
+    - _Glossiness: 0
+    - _GlossyReflections: 1
+    - _Metallic: 0
+    - _Mode: 0
+    - _OcclusionStrength: 1
+    - _Parallax: 0.02
+    - _SmoothnessTextureChannel: 0
+    - _SpecularHighlights: 1
+    - _SrcBlend: 1
+    - _UVSec: 0
+    - _ZWrite: 1
+    m_Colors:
+    - _Color: {r: 0.80208915, g: 0.05806145, b: 0.11052732, a: 1}
+    - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
+  m_BuildTextureStacks: []
+  m_AllowLocking: 1

+ 8 - 0
Assets/Resources/Item/Materials/Red.mat.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: e2c6d44f6f4cb49fd9fa8153251f7f3a
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 2100000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

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

@@ -103,15 +103,14 @@ public class VoiceController : MonoBehaviour
     {
         Debug.Log("voice button pointer up.");
         //HomeController.listenBreak = false;
-        StopRecording();
         waveForm.visible = false;
-
         HomeController.listenBreak = false;
         // TODO 以后根据音频识别返回值修改狗的行动
         foreach (var dog in HomeController.dogsInScene)
         {
             dog.animator.SetBool("isListening", false);
         }
+        StopRecording();
     }
 
     #region 录音相关
@@ -121,8 +120,8 @@ public class VoiceController : MonoBehaviour
         if (isRecording) return; // 如果已经在录音,则不再重复开始
 
         // 设置录音文件名和路径
-        filePathWav = Path.Combine(Application.persistentDataPath, "voiceCommand.wav");
-        filePathZip = Path.Combine(Application.persistentDataPath, "voiceCommand.zip");
+        filePathWav = Path.Combine(Application.persistentDataPath, "voice.wav");
+        filePathZip = Path.Combine(Application.persistentDataPath, "voice.zip");
 
         // 检测目录是否存在不存在就创建
         string directoryPath = Path.GetDirectoryName(filePathWav);
@@ -163,7 +162,7 @@ public class VoiceController : MonoBehaviour
 
         if (isCommandMode)
         {
-            // ommand模式,调用Home Controller Command的方法上传音频文件
+            // command模式,调用Home Controller Command的方法上传音频文件
             HomeController.Instance.VoiceCommandRequest(filePathZip);
         }
         else

+ 3 - 3
Assets/Scenes/Home.unity

@@ -338,7 +338,7 @@ PrefabInstance:
       objectReference: {fileID: 0}
     - target: {fileID: 2417705292335416526, guid: 358eaf0dc05de8c4b925b8d7b41c3df9, type: 3}
       propertyPath: m_IsActive
-      value: 1
+      value: 0
       objectReference: {fileID: 0}
     - target: {fileID: 3082356105365184116, guid: 358eaf0dc05de8c4b925b8d7b41c3df9, type: 3}
       propertyPath: m_LocalScale.x
@@ -362,7 +362,7 @@ PrefabInstance:
       objectReference: {fileID: 0}
     - target: {fileID: 3082356105365184116, guid: 358eaf0dc05de8c4b925b8d7b41c3df9, type: 3}
       propertyPath: m_LocalPosition.z
-      value: -4.75
+      value: -4
       objectReference: {fileID: 0}
     - target: {fileID: 3082356105365184116, guid: 358eaf0dc05de8c4b925b8d7b41c3df9, type: 3}
       propertyPath: m_LocalRotation.w
@@ -403,7 +403,7 @@ PrefabInstance:
     - target: {fileID: 8946003046713885710, guid: 358eaf0dc05de8c4b925b8d7b41c3df9, type: 3}
       propertyPath: m_Controller
       value: 
-      objectReference: {fileID: 9100000, guid: 51b6d0e7e6188834fa7e294baea2192a, type: 2}
+      objectReference: {fileID: 9100000, guid: 129befd34211a25489f4488cf57c38d5, type: 2}
     m_RemovedComponents: []
     m_RemovedGameObjects: []
     m_AddedGameObjects: []

+ 23 - 0
Assets/Scripts/GameControllers/UserProperty.cs

@@ -85,6 +85,29 @@ public static class UserProperty
         }
     }
 
+    // 用Dog id搜索Gamedata.focusDog的下标
+    public static int GetDogIndex(string dogId)
+    {
+        for (int i = 0; i < UserProperty.dogs.Count; i++)
+        {
+            if (UserProperty.dogs[i].d_id == dogId)
+            {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    // 用Gamedata.focusDog的下标获取Dog id
+    public static string GetDogId(int dogIndex)
+    {
+        if (dogIndex < 0 || dogIndex >= UserProperty.dogs.Count)
+        {
+            return null;
+        }
+        return UserProperty.dogs[dogIndex].d_id;
+    }
+
 }
 
 // 待删除代码,废弃

+ 32 - 19
Assets/Scripts/Home/DogInScene.cs

@@ -9,12 +9,6 @@ using UnityEngine.Rendering.PostProcessing;
 //[CreateAssetMenu(fileName = "DogInScene", menuName = "Scriptable Objects/DogInScene")]
 public class DogInScene : ScriptableObject
 {
-    
-//}
-
-
-//public class DogInScene
-//{
     //通用参数段
     public DogProperty dogProperty;
     public GameObject gameObject { set; get; }
@@ -25,9 +19,9 @@ public class DogInScene : ScriptableObject
 
     // 喝水吃饭参数段
     public DateTime drinkStartTime, eatStartTime;      // 记录吃喝开始时间
-    public bool itemConsumeProgress=false;     // 是否在吃和喝的进程中。如果是的话,跳过常规动画检测
+    public bool itemConsumeProgress = false;     // 是否在吃和喝的进程中。如果是的话,跳过常规动画检测
     public bool isMovingToBowl;
-    
+
 
 
     // 随机动作参数段
@@ -42,7 +36,7 @@ public class DogInScene : ScriptableObject
 
     // interact相关的参数
     public DateTime interactLastUpdate;     // 上次交互指令时间
-    private bool isMovingToPlayer;      // 是否在向玩家移动
+    public bool isMovingToPlayer;      // 是否在向玩家移动
 
 
     #region 通用函数段
@@ -76,10 +70,11 @@ public class DogInScene : ScriptableObject
 
         this.dogState = "interact";
         this.interactLastUpdate = DateTime.Now;
-        this.moveToLocation = new Vector3(0f, 0f, -4.75f);
-
+        this.moveToLocation = new Vector3(0f, 0f, -4f);
         this.isMovingToPlayer = true;
-        MovetoPlayer();
+        this.animator.SetTrigger("move");       // 切换为走路动画
+        this.animator.SetBool("isMoving", true);        // 保持为走路动画
+        this.animator.SetFloat("moveSpeed", 0.5f);
     }
     public void MovetoPlayer()
     {
@@ -87,17 +82,24 @@ public class DogInScene : ScriptableObject
         // 如果距离目标小于0.5米就把速度调整为零
         if (Vector3.Distance(moveToLocation, this.gameObject.transform.position) < 0.5f)
         {
+            Debug.Log(this.gameObject.name + "current move speed:" + moveSpeed);
             this.SetMoveSpeed(0);
+            Debug.Log(this.gameObject.name + "reduce move speed:" + moveSpeed);
         }
 
-        this.gameObject.transform.LookAt(new Vector3(0f, 1f, -8f));
-        this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, dogProperty.runSpeed * (1 + moveSpeed) * 0.02f * moveSpeedAdj);  // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应RM动画
-
         // 如果狗距离到达重点就停止跑步动画
         float distance = Vector3.Distance(gameObject.transform.position, moveToLocation);
-        if (distance < 0.1)
+        Debug.Log(this.gameObject.name + "interact move to player distance:" + distance);
+        if (distance > 2f)      // 距离一米就开始停下来,否则刹不住
+        {
+            this.gameObject.transform.LookAt(moveToLocation);
+            this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, dogProperty.runSpeed * (1 + moveSpeed) * 0.02f * moveSpeedAdj);  // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应RM动画this.gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, moveToLocation, dogProperty.runSpeed * (1 + moveSpeed) * 0.02f * moveSpeedAdj);  // 第一个0.02对应50帧fixupdate画面,后面一个数字对应速度调整,对应RM动画
+        }
+        
+        else
         {
             this.animator.SetBool("isMoving", false);
+            this.gameObject.transform.LookAt(new Vector3(0f, 1f, -8f));
             this.isMovingToPlayer = false;
         }
     }
@@ -105,9 +107,15 @@ public class DogInScene : ScriptableObject
     // 交互行为计时器
     public bool InteractTimeout()
     {
+
         TimeSpan ts = new TimeSpan();
         ts = DateTime.Now - this.interactLastUpdate;
-        if (ts.TotalSeconds > 10) { return true; }
+        if (ts.TotalSeconds > 10)
+        {
+            Debug.Log("InteractTimeout:" + this.gameObject.name);
+            this.dogState= "idle";
+            return true;
+        }
         else { return false; }
     }
 
@@ -116,7 +124,12 @@ public class DogInScene : ScriptableObject
 
         // 结束交互行为,恢复原有的菜单
         this.dogState = "idle";
-    } 
+        // 恢复场景idle对应的Animator Controller
+        Animator animator = gameObject.GetComponent<Animator>();
+        RuntimeAnimatorController animatorController = Resources.Load<RuntimeAnimatorController>("Dog/AnimatorController/shibaInu/HomeDogAnimatorController");
+        if (dogProperty.breed == "shibaInu") { animatorController = Resources.Load<RuntimeAnimatorController>("Dog/AnimatorController/shibaInu/HomeDogAnimatorController"); }
+        animator.runtimeAnimatorController = animatorController;
+    }
     #endregion
 
     #region 随机动作控制函数
@@ -240,7 +253,7 @@ public class DogInScene : ScriptableObject
         {
             bowl = GameObject.Find("Bowl_food");        // 开启整个吃食物的进程
         }
-        
+
         this.moveToLocation = bowl.transform.position;
         this.isMovingToBowl = true;
         this.animator.SetTrigger("move");       // 切换为走路动画

+ 90 - 52
Assets/Scripts/Home/HomeController.cs

@@ -30,7 +30,7 @@ public class HomeController : MonoBehaviour
     private bool isSleepChecked = false;        // 用于检测第一次睡眠检测是否执行完成
     // Start is called once before the first execution of Update after the MonoBehaviour is created
     private GameObject centerOfDogs;
-    //private bool isInteract = false;        // 是否在交互状态
+    private bool isInteractMode = false;        // 是否在交互状态
 
     private void Awake()
     {
@@ -51,7 +51,7 @@ public class HomeController : MonoBehaviour
         lastCameraChange = DateTime.Now;
         playerCam = GameObject.Find("VCam Player").GetComponent<CinemachineVirtualCamera>();
         dogCam = GameObject.Find("VCam Dog").GetComponent<CinemachineVirtualCamera>();
-        centerOfDogs= GameObject.Find("CenterOfDogs");
+        centerOfDogs = GameObject.Find("CenterOfDogs");
 
         //InitialScene();
         StartCoroutine(InitialScene());
@@ -64,7 +64,7 @@ public class HomeController : MonoBehaviour
         {
             // 计算多只狗的中心位置,用于主摄像机瞄准
             centerOfDogs.transform.position = CenterOfDogs();
-            
+
             if (!isSleepChecked)        // 每次启动检测只进行一次是否进入睡眠
             {
                 // 判断是否在睡觉时间
@@ -104,58 +104,70 @@ public class HomeController : MonoBehaviour
             // 生成一个数据数用于随机开启动画,如果和狗的randomFactor相同就开启动画
             int randomCheck = UnityEngine.Random.Range(0, 51);
 
-            foreach (var dog in dogsInScene)
+            if (isInteractMode)
             {
-                // 如果在eat drink进程结束前不执行随机场景代码
-                //if (dog.itemConsumeProgress)        // TODO 以后用DogInScene.dogState来判断
-                if (dog.dogState == "itemConsume")
+                foreach (var dog in dogsInScene)
                 {
-                    if (dog.isMovingToBowl)
+                    if (dog.dogState == "interact")
                     {
-                        dog.MovetoBowl();
+                        dogCam.m_LookAt = dog.gameObject.transform;
+                        dogCam.Priority = 10;
+                        // 单只狗在交互的状态控制代码
+                        if (dog.isMovingToPlayer)
+                        {
+                            dog.MovetoPlayer();
+                        }
+                        if (dog.InteractTimeout())        // 如果交互时间结束,结束交互状态
+                        {
+                            dog.ExitInteract();
+                            isInteractMode = false;        // 交互结束,退出交互状态
+                        }
                     }
                 }
-                else if (dog.dogState == "interact")
+            }
+            else
+            {
+                foreach (var dog in dogsInScene)
                 {
-                    // 单只狗在交互的状态控制代码
-                    if (dog.isMovingToBowl)
+                    // 如果在eat drink进程结束前不执行随机场景代码
+                    //if (dog.itemConsumeProgress)        // TODO 以后用DogInScene.dogState来判断
+                    if (dog.dogState == "itemConsume")
                     {
-                        dog.MovetoBowl();
+                        if (dog.isMovingToBowl)
+                        {
+                            dog.MovetoBowl();
+                        }
                     }
-                    if (dog.InteractTimeout())        // 如果交互时间结束,结束交互状态
+                    else
                     {
-                        dog.ExitInteract();
-                    }
-                }
-                else
-                {
-                    // 随机动作控制控制   
-                    RandomCameraChange();
+                        // 随机动作控制控制   
+                        RandomCameraChange();
 
-                    if (listenBreak)        // 如果用户按下说话按键,立刻切换到监听状态
-                    {
-                        dog.Listen();
-                    }
-                    else if (dog.isMoving)
-                    {
-                        dog.RandomMove();
-                    }
+                        if (listenBreak)        // 如果用户按下说话按键,立刻切换到监听状态
+                        {
+                            dog.Listen();
+                        }
+                        else if (dog.isMoving)
+                        {
+                            dog.RandomMove();
+                        }
 
-                    else if (randomCheck == dog.randomFactor && !dog.isSleeping)        // 当狗自身的随机数和系统随机数相同时候触发。约100秒触发一次。
-                    {
-                        TimeSpan ts = DateTime.Now - dog.animationStartTime;
-                        if (ts.Seconds >= 30)        // 如果距离上一个动作超过30秒就可以开始新的动作
+                        else if (randomCheck == dog.randomFactor && !dog.isSleeping)        // 当狗自身的随机数和系统随机数相同时候触发。约100秒触发一次。
                         {
-                            float r = UnityEngine.Random.Range(0, 1f);
-                            if (r > 0.6)       // 随机选择开始动画,或者移动
-                            {
-                                dog.IdleAnimation();
-                            }
-                            else        // 狗狗开始步行移动
+                            TimeSpan ts = DateTime.Now - dog.animationStartTime;
+                            if (ts.Seconds >= 30)        // 如果距离上一个动作超过30秒就可以开始新的动作
                             {
-                                dog.SetMoveSpeed(0);
-                                dog.moveSpeed = 0;
-                                dog.RandomMove();
+                                float r = UnityEngine.Random.Range(0, 1f);
+                                if (r > 0.6)       // 随机选择开始动画,或者移动
+                                {
+                                    dog.IdleAnimation();
+                                }
+                                else        // 狗狗开始步行移动
+                                {
+                                    dog.SetMoveSpeed(0);
+                                    dog.moveSpeed = 0;
+                                    dog.RandomMove();
+                                }
                             }
                         }
                     }
@@ -246,9 +258,9 @@ public class HomeController : MonoBehaviour
     {
         int delay = 10;     // 延迟10秒执行一次
         TimeSpan ts = DateTime.Now - lastCameraChange;
-        if (ts.TotalSeconds < delay) {return;}
+        if (ts.TotalSeconds < delay) { return; }
         int dogCount = dogsInScene.Count;
-        int r = UnityEngine.Random.Range(0, dogCount+1);
+        int r = UnityEngine.Random.Range(0, dogCount + 1);
         if (r < dogCount)
         {
             dogCam.m_LookAt = dogsInScene[r].gameObject.transform;
@@ -271,7 +283,7 @@ public class HomeController : MonoBehaviour
         {
             foreach (var dog in dogsInScene)
             {
-                if(dog.gameObject.GetComponent<Animator>().runtimeAnimatorController == null)
+                if (dog.gameObject.GetComponent<Animator>().runtimeAnimatorController == null)
                 {
                     initDone = false;
                 }
@@ -279,7 +291,7 @@ public class HomeController : MonoBehaviour
         }
         else
         {
-            initDone=false;
+            initDone = false;
         }
         //Debug.Log("Home scene initial status:"+initDone);
         return initDone;
@@ -307,7 +319,11 @@ public class HomeController : MonoBehaviour
         WWWForm form = new();
         form.AddField("user_id", UserProperty.userId);
 
-        StartCoroutine(WebController.PostRequest(url, form, filePath, callback: VoiceCallCallback));
+        // TODO 待后台开发完成后,开启网络通讯功能,目前暂用临时直接赋值
+        // StartCoroutine(WebController.PostRequest(url, form, filePath, callback: VoiceCallCallback));
+        isInteractMode = true;        // 进入交互模式
+        dogsInScene[0].SetupInteract();
+        VoiceButtonOnlySwitch(true);        // 交互模式下关闭其他菜单
     }
 
     // 语音呼唤上传回调函数
@@ -317,12 +333,37 @@ public class HomeController : MonoBehaviour
         var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
         if (data != null && data["status"].ToString() == "success")
         {
-       
             // 刷新狗的数据
             string dogJson = data["dogs"].ToString();
             UserProperty.FreshDogInfo(dogJson);
 
             // TODO 根据返回结果设定focusdog
+            float highestScore = 0;
+            string highestScoreDogId = "";
+            var scores = data["scores"].ToString();
+            var scoresList = JsonConvert.DeserializeObject<Dictionary<string, float>>(scores);
+            foreach (var score in scoresList)
+            {
+                if (score.Value > highestScore)
+                {
+                    highestScore = score.Value;
+                    highestScoreDogId = score.Key;
+                }
+            }
+
+            if (highestScore > 60)        // 60分以上才可以进入交互模式
+            {
+                GameData.focusDog = UserProperty.GetDogIndex(highestScoreDogId);
+                VoiceButtonOnlySwitch(true);        // 交互模式下关闭其他菜单
+                foreach (var dog in dogsInScene)
+                {
+                    if (dog.dogProperty.d_id == highestScoreDogId)
+                    {
+                        dog.SetupInteract();
+                    }
+                }
+            }
+
             // focusdog 开启互动模式
             HomeController.dogsInScene[GameData.focusDog].dogState = "interact";
             HomeController.dogsInScene[GameData.focusDog].SetupInteract();
@@ -367,7 +408,7 @@ public class HomeController : MonoBehaviour
     }
 
     // 改变Voice And Menu 菜单形态
-    public void VoiceButtonSwitch(bool state)
+    public void VoiceButtonOnlySwitch(bool state)
     {
         // 交互时候关闭其他菜单
         var vamUI = GameObject.Find("VoiceAndMenu");
@@ -381,9 +422,6 @@ public class HomeController : MonoBehaviour
     #endregion
 }
 
-
-
-// 
 public enum ItemGroup
 {
     food,