Browse Source

5/11更新

完善轨迹功能。
Jees 3 weeks ago
parent
commit
93d0603f13

+ 165 - 3
Assets/Scenes/Test Scene.unity

@@ -130,6 +130,7 @@ GameObject:
   - component: {fileID: 347493358}
   - component: {fileID: 347493357}
   - component: {fileID: 347493356}
+  - component: {fileID: 347493359}
   m_Layer: 0
   m_Name: Main Camera
   m_TagString: MainCamera
@@ -177,7 +178,7 @@ Camera:
     width: 1
     height: 1
   near clip plane: 0.3
-  far clip plane: 1000
+  far clip plane: 100
   field of view: 60
   orthographic: 0
   orthographic size: 5
@@ -211,6 +212,50 @@ Transform:
   m_Children: []
   m_Father: {fileID: 0}
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &347493359
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 347493355}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_RenderShadows: 1
+  m_RequiresDepthTextureOption: 2
+  m_RequiresOpaqueTextureOption: 2
+  m_CameraType: 0
+  m_Cameras: []
+  m_RendererIndex: -1
+  m_VolumeLayerMask:
+    serializedVersion: 2
+    m_Bits: 1
+  m_VolumeTrigger: {fileID: 0}
+  m_VolumeFrameworkUpdateModeOption: 2
+  m_RenderPostProcessing: 0
+  m_Antialiasing: 0
+  m_AntialiasingQuality: 2
+  m_StopNaN: 0
+  m_Dithering: 0
+  m_ClearDepth: 1
+  m_AllowXRRendering: 1
+  m_AllowHDROutput: 1
+  m_UseScreenCoordOverride: 0
+  m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0}
+  m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0}
+  m_RequiresDepthTexture: 0
+  m_RequiresColorTexture: 0
+  m_Version: 2
+  m_TaaSettings:
+    m_Quality: 3
+    m_FrameInfluence: 0.1
+    m_JitterScale: 1
+    m_MipBias: 0
+    m_VarianceClampScale: 0.9
+    m_ContrastAdaptiveSharpening: 0
 --- !u!1 &801546032
 GameObject:
   m_ObjectHideFlags: 0
@@ -222,6 +267,7 @@ GameObject:
   - component: {fileID: 801546033}
   - component: {fileID: 801546034}
   - component: {fileID: 801546035}
+  - component: {fileID: 801546036}
   m_Layer: 0
   m_Name: Player
   m_TagString: Untagged
@@ -238,9 +284,9 @@ Transform:
   m_GameObject: {fileID: 801546032}
   serializedVersion: 2
   m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
-  m_LocalPosition: {x: -4.760311, y: -1.0233593, z: 5.7006884}
+  m_LocalPosition: {x: 0, y: 1, z: 0}
   m_LocalScale: {x: 1, y: 1, z: 1}
-  m_ConstrainProportionsScale: 0
+  m_ConstrainProportionsScale: 1
   m_Children: []
   m_Father: {fileID: 0}
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@@ -302,6 +348,122 @@ MonoBehaviour:
   m_Script: {fileID: 11500000, guid: 47852a50d335dd9499f14d1d61b72f00, type: 3}
   m_Name: 
   m_EditorClassIdentifier: 
+--- !u!96 &801546036
+TrailRenderer:
+  serializedVersion: 3
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 801546032}
+  m_Enabled: 1
+  m_CastShadows: 0
+  m_ReceiveShadows: 1
+  m_DynamicOccludee: 1
+  m_StaticShadowCaster: 0
+  m_MotionVectors: 0
+  m_LightProbeUsage: 0
+  m_ReflectionProbeUsage: 0
+  m_RayTracingMode: 0
+  m_RayTraceProcedural: 0
+  m_RayTracingAccelStructBuildFlagsOverride: 0
+  m_RayTracingAccelStructBuildFlags: 1
+  m_SmallMeshCulling: 1
+  m_RenderingLayerMask: 1
+  m_RendererPriority: 0
+  m_Materials:
+  - {fileID: 10306, guid: 0000000000000000f000000000000000, type: 0}
+  m_StaticBatchInfo:
+    firstSubMesh: 0
+    subMeshCount: 0
+  m_StaticBatchRoot: {fileID: 0}
+  m_ProbeAnchor: {fileID: 0}
+  m_LightProbeVolumeOverride: {fileID: 0}
+  m_ScaleInLightmap: 1
+  m_ReceiveGI: 1
+  m_PreserveUVs: 0
+  m_IgnoreNormalsForChartDetection: 0
+  m_ImportantGI: 0
+  m_StitchLightmapSeams: 1
+  m_SelectedEditorRenderState: 3
+  m_MinimumChartSize: 4
+  m_AutoUVMaxDistance: 0.5
+  m_AutoUVMaxAngle: 89
+  m_LightmapParameters: {fileID: 0}
+  m_SortingLayerID: 0
+  m_SortingLayer: 0
+  m_SortingOrder: 0
+  m_Time: 1
+  m_PreviewTimeScale: 1
+  m_Parameters:
+    serializedVersion: 3
+    widthMultiplier: 0.2
+    widthCurve:
+      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.09375
+        inSlope: 0
+        outSlope: 0
+        tangentMode: 0
+        weightedMode: 0
+        inWeight: 0
+        outWeight: 0
+      m_PreInfinity: 2
+      m_PostInfinity: 2
+      m_RotationOrder: 4
+    colorGradient:
+      serializedVersion: 2
+      key0: {r: 0.2901961, g: 0.972549, b: 0.41807657, a: 0.78431374}
+      key1: {r: 1, g: 0, b: 0.7185302, a: 0.78431374}
+      key2: {r: 0, g: 0, b: 0, a: 1}
+      key3: {r: 0, g: 0, b: 0, a: 0}
+      key4: {r: 0, g: 0, b: 0, a: 0}
+      key5: {r: 0, g: 0, b: 0, a: 0}
+      key6: {r: 0, g: 0, b: 0, a: 0}
+      key7: {r: 0, g: 0, b: 0, a: 0}
+      ctime0: 0
+      ctime1: 65535
+      ctime2: 0
+      ctime3: 0
+      ctime4: 0
+      ctime5: 0
+      ctime6: 0
+      ctime7: 0
+      atime0: 0
+      atime1: 65535
+      atime2: 65535
+      atime3: 0
+      atime4: 0
+      atime5: 0
+      atime6: 0
+      atime7: 0
+      m_Mode: 0
+      m_ColorSpace: 0
+      m_NumColorKeys: 2
+      m_NumAlphaKeys: 2
+    numCornerVertices: 0
+    numCapVertices: 0
+    alignment: 1
+    textureMode: 1
+    textureScale: {x: 1, y: 1}
+    shadowBias: 0.5
+    generateLightingData: 1
+  m_MinVertexDistance: 0.1
+  m_MaskInteraction: 0
+  m_Autodestruct: 0
+  m_Emitting: 1
+  m_ApplyActiveColorSpace: 1
 --- !u!1 &1772971345
 GameObject:
   m_ObjectHideFlags: 0

+ 102 - 23
Assets/Scripts/Functions/Gesture/GestureManager.cs

@@ -1,8 +1,6 @@
 using Newtonsoft.Json;
-using NUnit.Framework;
 using System;
 using System.Collections.Generic;
-using System.Net.Sockets;
 using UnityEngine;
 using UnityEngine.InputSystem;
 
@@ -13,32 +11,38 @@ public class GestureManager
 {
     // Start is called once before the first execution of Update after the MonoBehaviour is created
     public List<GesturePointOffset> gesturePointOffsetList { set; get; } = new List<GesturePointOffset>();
-    public int sampleRate { set; get; } = 10;        // 采样率
+    public int sampleRate { set; get; } = 20;        // 采样率
     private Vector2 prePointLoc = new Vector2(0, 0); // 第一个点
     private Vector2 curPointLoc = new Vector2(0, 0); // 第二个点
-    private float timer = 0f;
+    private float timer = 0f;       // 配合interval使用
     public bool isRecording;
-    private float interval;
+    private float interval;     // 采样间隔,使用采样率计算
     private float lengthTorrence = 0.25f; // 允许的长度误差
+    private DateTime startTime;
+    private DateTime endTime;
+    private float duration;
+    private int screenWidth;
+    private int screenHeight;
 
     public GestureManager()
     {
-        interval = (float)1 / sampleRate;
+        interval = 1f / sampleRate;
+        screenWidth = Screen.width;
+        screenHeight = Screen.height;
     }
 
     public string ExportToJson()
     {
         string json = string.Empty;
-        if (gesturePointOffsetList.Count / 2 <= sampleRate) { return json; }
         json = JsonConvert.SerializeObject(this);
         return json;
     }
 
     public void ImportFromJson(string json)
     {
-        this.isRecording = false;
+        isRecording = false;
         var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
-        this.sampleRate = int.Parse(data["sampleRate"].ToString());
+        sampleRate = int.Parse(data["sampleRate"].ToString());
         gesturePointOffsetList.Clear();
         GesturePointOffset[] pointOffsets = JsonConvert.DeserializeObject<GesturePointOffset[]>(data["gesturePointOffsetList"].ToString());
         foreach (var point in pointOffsets)
@@ -53,6 +57,13 @@ public class GestureManager
         Vector2 pointLoc = Pointer.current.position.ReadValue();
         if (isRecording)
         {
+            // if (!IsMouseOnScreen())
+            // {
+            //     StopRecording();
+            //     Debug.Log("Mouse not on screen");
+            //     return;
+            // }
+
             if (gesturePointOffsetList.Count == 0)
             {
                 prePointLoc = pointLoc;
@@ -68,16 +79,20 @@ public class GestureManager
                 if (timer >= interval)
                 {
                     timer = 0f;
-
                     curPointLoc = pointLoc;
-                    float distance = Vector2.Distance(prePointLoc, curPointLoc);
-                    float angle = Vector2.Angle(prePointLoc, curPointLoc);
+
+                    Vector2 normalizedCurPoint = NormalizePoint(curPointLoc);
+                    Vector2 normalizedPrePoint = NormalizePoint(prePointLoc);
+                    float distance = Vector2.Distance(normalizedCurPoint, normalizedPrePoint);
+
+                    Vector2 direction = curPointLoc - prePointLoc;
+                    float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
+                    // float angle = Vector2.Angle(prePointLoc, curPointLoc);
                     GesturePointOffset gesturePointMovement = new GesturePointOffset(distance, angle);
 
                     if (distance * angle != 0)
                     {
                         gesturePointOffsetList.Add(gesturePointMovement);
-                        Debug.Log("log time:" + DateTime.Now.ToString());
                     }
                     prePointLoc = curPointLoc;
                 }
@@ -88,21 +103,27 @@ public class GestureManager
     public float CompareGesture(GestureManager anotherGesture)
     {
         float score = 0f;
-        if (this.sampleRate != anotherGesture.sampleRate)
+        if (sampleRate != anotherGesture.sampleRate)
         {
             Debug.Log("Sample rate not match");
             return -1f;
         }
 
-        int maxGesturePoints = Mathf.Max(this.gesturePointOffsetList.Count, anotherGesture.gesturePointOffsetList.Count);
-        int minGesturePoints = Mathf.Min(this.gesturePointOffsetList.Count, anotherGesture.gesturePointOffsetList.Count);
+        if (gesturePointOffsetList.Count == 0 || anotherGesture.gesturePointOffsetList.Count == 0)
+        {
+            Debug.Log("Gesture point count is 0");
+            return -1f;
+        }
+
+        int maxGesturePoints = Mathf.Max(gesturePointOffsetList.Count, anotherGesture.gesturePointOffsetList.Count);
+        int minGesturePoints = Mathf.Min(gesturePointOffsetList.Count, anotherGesture.gesturePointOffsetList.Count);
         for (int i = 0; i < minGesturePoints; i++)
         {
 
-            float distanceMin = Mathf.Min(this.gesturePointOffsetList[i].distance - anotherGesture.gesturePointOffsetList[i].distance);
-            float distanceMax = Mathf.Max(this.gesturePointOffsetList[i].distance - anotherGesture.gesturePointOffsetList[i].distance);
-            float angleMin = Mathf.Min(this.gesturePointOffsetList[i].angle - anotherGesture.gesturePointOffsetList[i].angle);
-            float angleMax = Mathf.Max(this.gesturePointOffsetList[i].angle - anotherGesture.gesturePointOffsetList[i].angle);
+            float distanceMin = Mathf.Min(gesturePointOffsetList[i].distance, anotherGesture.gesturePointOffsetList[i].distance);
+            float distanceMax = Mathf.Max(gesturePointOffsetList[i].distance, anotherGesture.gesturePointOffsetList[i].distance);
+            float angleMin = Mathf.Min(gesturePointOffsetList[i].angle, anotherGesture.gesturePointOffsetList[i].angle);
+            float angleMax = Mathf.Max(gesturePointOffsetList[i].angle, anotherGesture.gesturePointOffsetList[i].angle);
 
             float distanceScore = 0f;
             if (distanceMin == 0)
@@ -122,10 +143,10 @@ public class GestureManager
         }
 
         // 如果长度超过公差范围,就要考虑调整score
-        if ((maxGesturePoints / minGesturePoints) > (1f+ lengthTorrence))
+        if ((maxGesturePoints / minGesturePoints) > (1f + lengthTorrence))
         {
             int deltaGesturePoints = Mathf.RoundToInt(maxGesturePoints - minGesturePoints * (1f + lengthTorrence));
-            score = score * (minGesturePoints / (minGesturePoints + deltaGesturePoints));
+            score = score * ((float)minGesturePoints / (minGesturePoints + deltaGesturePoints));
         }
 
         return score;
@@ -133,6 +154,64 @@ public class GestureManager
 
     public void ResetGesture()
     {
-        this.gesturePointOffsetList.Clear();
+        gesturePointOffsetList.Clear();
+    }
+
+    public void StartRecording()
+    {
+        isRecording = true;
+        gesturePointOffsetList.Clear();
+        timer = 0f;
+        prePointLoc = Vector2.zero;
+        curPointLoc = Vector2.zero;
+        startTime = DateTime.Now;
+    }
+    public bool StopRecording()
+    {
+        isRecording = false;
+        endTime = DateTime.Now;
+        duration = (float)(endTime - startTime).TotalSeconds;
+        Debug.Log("gesture duration:" + duration.ToString());
+        Debug.Log("gesture point count:" + gesturePointOffsetList.Count.ToString());
+        // 如果采样过少,就不记录这个手势
+        if (gesturePointOffsetList.Count <= sampleRate/2)
+        {
+            Debug.Log("gesture duration too short");
+            gesturePointOffsetList.Clear();
+        }
+        if (gesturePointOffsetList.Count > 0)
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    private bool IsMouseOnScreen()
+    {
+        Vector2 mousePos = Pointer.current.position.ReadValue();
+        return mousePos.x >= 0 && mousePos.x < Screen.width &&
+               mousePos.y >= 0 && mousePos.y < Screen.height;
+    }
+
+    private Vector2 NormalizePoint(Vector2 point)
+    {
+        float x = point.x / screenWidth;
+        float y = point.y / screenHeight;
+        return new Vector2(x, y);
+    }
+    private Vector2 DenormalizePoint(Vector2 point)
+    {
+        float x = point.x * screenWidth;
+        float y = point.y * screenHeight;
+        return new Vector2(x, y);
+    }
+
+    public void SetSampleRate(int rate)
+    {
+        sampleRate = rate;
+        interval = 1f / sampleRate;
     }
 }

+ 2 - 1
Assets/Scripts/Functions/LogSystem.cs

@@ -26,7 +26,8 @@ public class LogSystem : MonoBehaviour
         }
 
         // 设置日志文件路径
-        logFilePath = Application.persistentDataPath + "/logs/" + UserProperty.userId + ".log";
+        DateTime now = DateTime.Now;
+        logFilePath = Application.persistentDataPath + "/logs/" + now.ToString("yyyy-MM-dd") + UserProperty.userId + ".log";
         Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
     }
 

File diff suppressed because it is too large
+ 1 - 2
Assets/Scripts/Test Scene/PlayerGestureController.cs


Some files were not shown because too many files changed in this diff