From a77faec0fa941db1e6e5b91c86633f716cc37ec9 Mon Sep 17 00:00:00 2001 From: ninemine <1371605831@qq.com> Date: Thu, 2 Oct 2025 11:11:42 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=90=91=E5=88=A4=E5=AE=9A=E6=95=88=E6=9E=9C?= =?UTF-8?q?IInteraction=E4=B8=AD=E5=A2=9E=E5=BC=BA,=20=E6=94=AF=E6=8C=81Ho?= =?UTF-8?q?ld=E7=B1=BB=E5=9E=8B=E5=88=A4=E5=AE=9A,=20=E8=BF=99=E5=B0=86?= =?UTF-8?q?=E6=98=AF=E9=99=A4Tap=E4=BB=A5=E5=A4=96=E5=94=AF=E4=BA=8C?= =?UTF-8?q?=E7=9A=84=E5=88=A4=E5=AE=9A=E6=A8=A1=E5=BC=8F\n2.GameController?= =?UTF-8?q?=E7=8E=B0=E5=9C=A8=E8=83=BD=E5=A4=9F=E6=89=93=E5=BC=80=E5=B8=A6?= =?UTF-8?q?=E6=9C=89Helper=E7=9A=84=E9=A1=B9=E7=9B=AE=E6=A0=B9=E7=9B=AE?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EditiorContent/EditorController.cs | 9 +- .../Framework/GameContent/GameController.cs | 112 +++++++++++------- Assets/Scripts/Framework/ScriptableObject.cs | 2 +- Assets/Scripts/Interaction/IInteraction.cs | 11 +- .../Interaction/FullScreenInteraction.cs | 62 ++++++++-- 5 files changed, 138 insertions(+), 58 deletions(-) diff --git a/Assets/Scripts/Framework/EditiorContent/EditorController.cs b/Assets/Scripts/Framework/EditiorContent/EditorController.cs index 3f5374e..217bb88 100644 --- a/Assets/Scripts/Framework/EditiorContent/EditorController.cs +++ b/Assets/Scripts/Framework/EditiorContent/EditorController.cs @@ -302,6 +302,11 @@ namespace Demo.Editor } } + //[Header("PersistentDataPath")] + public string PersistentDataPath => PlatformIndicator.PersistentDataPath; + public string PersistentProjectPath => Path.Combine(PersistentDataPath, "Projects/"); + public string PersistentHelperPath => Path.Combine(PersistentDataPath, "Helper/"); + private void OpenGameScene(string ProjectName, bool IsCreateNewProject) { if (GameContent.instance == null) @@ -309,7 +314,7 @@ namespace Demo.Editor new GameObject("GameContent").AddComponent(); } var content = GameContent.instance; - content.RootSourceDir = Path.Combine(PlatformIndicator.PersistentDataPath, ProjectName) + "/"; + content.RootSourceDir = Path.Combine(PersistentProjectPath, ProjectName) + "/"; content.IsCreateNewProject = IsCreateNewProject; content.ScriptableObjectTypen = GetDefaultScriptableObjectTypen(); content.IsAutoPlay = true; @@ -371,7 +376,7 @@ namespace Demo.Editor private void Start() { // Helper Files - ToolFile helperHeaderDir = new ToolFile(PlatformIndicator.StreamingAssetsPath) | "Helper/"; + ToolFile helperHeaderDir = new ToolFile(PersistentHelperPath); if (helperHeaderDir.Exists() == false) { ProjectCreateHelper.CreateHelperFiles(helperHeaderDir, CurrentProjectDefaultFileStyle); diff --git a/Assets/Scripts/Framework/GameContent/GameController.cs b/Assets/Scripts/Framework/GameContent/GameController.cs index a3a9fdd..19105e5 100644 --- a/Assets/Scripts/Framework/GameContent/GameController.cs +++ b/Assets/Scripts/Framework/GameContent/GameController.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.IO; using Cinemachine; using Convention; -using Convention.WindowsUI.Variant; using Unity.Profiling; using UnityEngine; using UnityEngine.InputSystem; @@ -27,7 +26,17 @@ namespace Demo.Game public Action SetSongCurrentTime { get; private set; } = _ => { }; public bool IsMain { get; set; } = false; public bool IsAutoPlay { get; private set; } = false; - public string ScriptEditor { get; private set; } = "{0}"; + /// + /// 使用形如"E:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\devenv.exe" {0}来打开文件, + /// {0}是必要的, 指代的是将要打开的文件 + /// + public string WhichOpenScript { get; private set; } = "{0}"; + /// + /// 使用形如"E:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\devenv.exe" {0}来打开项目存贮目录, + /// {0}是必要的, 指代的是Helper的父目录, 同时也应该是项目的父目录, 同时配备有全局项目配置, 用于提供注释内容, + /// 值为null时不会在启动时打开 + /// + public string WhichOpenProject { get; private set; } = null; public ProjectDefaultFileStyle CurrentProjectDefaultFileStyle = default; public float SongOffset; @@ -117,55 +126,70 @@ namespace Demo.Game SetupSongDuration = GameContent.instance.SetupSongDuration; SetSongCurrentTime = GameContent.instance.SetSongCurrentTime; SongOffset = GameContent.instance.SongOffset; - } - { - IsHideTrackRender = (bool)MainConfig.FindItem(nameof(IsHideTrackRender), false); - IsAutoPlay = GameContent.instance.IsAutoPlay; - ScriptEditor = (string)MainConfig.FindItem(nameof(ScriptEditor), ScriptEditor); - CurrentProjectDefaultFileStyle = content.CurrentProjectDefaultFileStyle; - } - - yield return null; - - MainConfig.SaveProperties(); - - // Load Root Object - { - while (MainConfig.Contains("root") == false) + // Open Project + WhichOpenProject = (string)MainConfig.FindItem(nameof(WhichOpenProject), WhichOpenProject); + if (string.IsNullOrEmpty(WhichOpenProject) == false) { - string defaultRootPath = "root" + CurrentProjectDefaultFileStyle switch + string path = string.Format($"{WhichOpenProject}", $"\"{Editor.EditorController.instance.PersistentDataPath}\"") ; + try { - ProjectDefaultFileStyle.PY => ".py", - _ => ".h" - }; - if (content.IsCreateNewProject) - { - MainConfig["root"] = defaultRootPath; - if (MainConfig.CreateFile(defaultRootPath)) - { - MainConfig.SaveProperties(); - break; - } + System.Diagnostics.Process.Start(path); + } + catch (Exception ex) + { + Debug.LogError($"Cannt open {path}", this); + Debug.LogException(ex, this); } - Debug.LogError($"{nameof(defaultRootPath)} is cannt create or config's root property is not exist", this); - StartCoroutine(GameExit()); - yield break; } - var rootFileName = (string)MainConfig.FindItem("root"); - var rootObject = new ToolFile(Path.Combine(content.RootSourceDir, rootFileName)); - rootObject.MustExistsPath(); - var rootGameObject = new GameObject(rootObject.GetName(true)).AddComponent(); - rootGameObject.transform.SetParent(transform); - rootGameObject.ScriptName = rootObject.GetName(true); - rootGameObject.audioSystem = MainAudio; - rootGameObject.EnableScript(content.RootSourceDir, rootObject.GetFullPath(), this); - try { - yield return rootGameObject.LoadScript(rootObject.LoadAsText()); + IsHideTrackRender = (bool)MainConfig.FindItem(nameof(IsHideTrackRender), false); + IsAutoPlay = GameContent.instance.IsAutoPlay; + WhichOpenScript = (string)MainConfig.FindItem(nameof(WhichOpenScript), WhichOpenScript); + CurrentProjectDefaultFileStyle = content.CurrentProjectDefaultFileStyle; } - finally + + yield return null; + + MainConfig.SaveProperties(); + + // Load Root Object { - MainObject = rootGameObject; + while (MainConfig.Contains("root") == false) + { + string defaultRootPath = "root" + CurrentProjectDefaultFileStyle switch + { + ProjectDefaultFileStyle.PY => ".py", + _ => ".h" + }; + if (content.IsCreateNewProject) + { + MainConfig["root"] = defaultRootPath; + if (MainConfig.CreateFile(defaultRootPath)) + { + MainConfig.SaveProperties(); + break; + } + } + Debug.LogError($"{nameof(defaultRootPath)} is cannt create or config's root property is not exist", this); + StartCoroutine(GameExit()); + yield break; + } + var rootFileName = (string)MainConfig.FindItem("root"); + var rootObject = new ToolFile(Path.Combine(content.RootSourceDir, rootFileName)); + rootObject.MustExistsPath(); + var rootGameObject = new GameObject(rootObject.GetName(true)).AddComponent(); + rootGameObject.transform.SetParent(transform); + rootGameObject.ScriptName = rootObject.GetName(true); + rootGameObject.audioSystem = MainAudio; + rootGameObject.EnableScript(content.RootSourceDir, rootObject.GetFullPath(), this); + try + { + yield return rootGameObject.LoadScript(rootObject.LoadAsText()); + } + finally + { + MainObject = rootGameObject; + } } } } diff --git a/Assets/Scripts/Framework/ScriptableObject.cs b/Assets/Scripts/Framework/ScriptableObject.cs index e37a3cb..5f768a1 100644 --- a/Assets/Scripts/Framework/ScriptableObject.cs +++ b/Assets/Scripts/Framework/ScriptableObject.cs @@ -133,7 +133,7 @@ namespace Demo public static void OpenScriptFile(ScriptableObject so) { string path = so.ScriptPath; - var ScriptEditor = so.GetRoot().RootGameController.ScriptEditor; + var ScriptEditor = so.GetRoot().RootGameController.WhichOpenScript; try { System.Diagnostics.Process.Start(string.Format($"{ScriptEditor}", $"\"{path}\"")); diff --git a/Assets/Scripts/Interaction/IInteraction.cs b/Assets/Scripts/Interaction/IInteraction.cs index f8eacfd..6cc250b 100644 --- a/Assets/Scripts/Interaction/IInteraction.cs +++ b/Assets/Scripts/Interaction/IInteraction.cs @@ -138,7 +138,16 @@ namespace Demo.Game return DurationStats.After; } - public abstract bool JudgementBehaviour(float timePoint); + public enum JudgementLevel + { + None = -2,//No Judge + Default = -1, + BestLevel = 0,//Level0 + ScoreLevel = 1,//Level1 + Bad = 128, + } + + public abstract JudgementLevel JudgementBehaviour(float timePoint); protected override void UpdateTicks(float currentTime, float deltaTime, TickType tickType) { diff --git a/Assets/Scripts/Interaction/Interaction/FullScreenInteraction.cs b/Assets/Scripts/Interaction/Interaction/FullScreenInteraction.cs index d287181..ca4f928 100644 --- a/Assets/Scripts/Interaction/Interaction/FullScreenInteraction.cs +++ b/Assets/Scripts/Interaction/Interaction/FullScreenInteraction.cs @@ -1,3 +1,4 @@ +using Convention; using UnityEngine; namespace Demo.Game @@ -9,21 +10,62 @@ namespace Demo.Game return new GameObject().AddComponent(); } - public override bool JudgementBehaviour(float timePoint) + [Content] public bool IsNeedTap = true; + [Content, SerializeField] private bool IsJudgement = false; + [Content, SerializeField] private bool IsReleaseJudgementEffect = false; + + /// + /// 设置为Hold模式, 即不需要点按即可判定的模式 + /// + [ScriptableCall(@"设置为Hold模式, 即不需要点按即可判定的模式")] + public void EnableHoldMode() { - if (GetRoot().RootGameController.IsAutoPlay) - return timePoint > GetBestJudgementTimePoint(); - var inputs = GetRoot().InputCatch; - for (int i = 0, e = inputs.Count; i < e; i++) + IsNeedTap = false; + } + + protected override void UpdateTicks(float currentTime, float deltaTime, TickType tickType) + { + base.UpdateTicks(currentTime, deltaTime, tickType); + if (tickType == TickType.Pause || tickType == TickType.Reset) { - var current = inputs[i]; - if (IsInInteractiveDuration(current.TimePoint)) + IsJudgement = false; + IsReleaseJudgementEffect = false; + } + } + + public override JudgementLevel JudgementBehaviour(float timePoint) + { + var stats = timePoint > GetBestJudgementTimePoint(); + if (IsJudgement) + { + if (IsNeedTap) + return JudgementLevel.None; + else if (stats && IsReleaseJudgementEffect == false) { - inputs.RemoveAt(i); - return true; + IsReleaseJudgementEffect = true; + return JudgementLevel.BestLevel; + } + else + return JudgementLevel.None; + } + if (GetRoot().RootGameController.IsAutoPlay) + return stats ? JudgementLevel.BestLevel: JudgementLevel.None; + var inputs = GetRoot().InputCatch; + var index = inputs.FindIndex(x => IsInInteractiveDuration(x.TimePoint)); + if (index != -1) + { + if (IsNeedTap) + { + inputs.RemoveAt(index); + return JudgementLevel.Default; + } + else + { + IsJudgement = true; + return JudgementLevel.None; } } - return false; + return JudgementLevel.None; } } }