diff --git a/Assets/Editor/DeveloperMode/TestSaveSystemTests.cs b/Assets/Editor/DeveloperMode/TestSaveSystemTests.cs index d1ef08196..dc1206359 100644 --- a/Assets/Editor/DeveloperMode/TestSaveSystemTests.cs +++ b/Assets/Editor/DeveloperMode/TestSaveSystemTests.cs @@ -1,12 +1,15 @@ #if UNITY_EDITOR using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using AibisDream.Framework; using AibisDream.SaveSystem; using Newtonsoft.Json; using NUnit.Framework; +using UnityEngine; namespace AibisDream.DeveloperMode.Editor.Tests { @@ -178,6 +181,134 @@ namespace AibisDream.DeveloperMode.Editor.Tests Assert.That(actual, Is.EqualTo(expected)); } + [TestCase(new[] { "content" }, NodeSaveTiming.NodeEnter, SaveResumeMode.RestartNode)] + [TestCase(new[] { "interaction" }, NodeSaveTiming.DialogueExit, SaveResumeMode.StateOnly)] + [TestCase(new[] { "content", "save_on_exit" }, NodeSaveTiming.DialogueExit, SaveResumeMode.StateOnly)] + [TestCase(new[] { "event", "save_on_exit" }, NodeSaveTiming.DialogueExit, SaveResumeMode.StateOnly)] + [TestCase(new[] { "interaction", "save_on_exit" }, NodeSaveTiming.DialogueExit, SaveResumeMode.StateOnly)] + [TestCase(new[] { "interaction", "no_save" }, NodeSaveTiming.None, SaveResumeMode.RestartNode)] + [TestCase(new[] { "content", "event" }, NodeSaveTiming.None, SaveResumeMode.RestartNode)] + public void ResolveNodePolicy_MapsNodeTypeAndModifiers( + string[] tags, + NodeSaveTiming expectedTiming, + SaveResumeMode expectedResumeMode) + { + var policy = SavePointEvaluator.ResolveNodePolicy( + "Node", + tags, + out _, + logWarnings: false); + + Assert.That(policy.Timing, Is.EqualTo(expectedTiming)); + Assert.That(policy.ResumeMode, Is.EqualTo(expectedResumeMode)); + } + + [Test] + public void Repository_StateOnlySnapshot_PreservesAnchorNode() + { + var request = CreateRequest("ChapterA", "ProjectA", "InteractionNode", "SceneA"); + request.Snapshot.anchor.startDialogueOnRestore = false; + request.SaveTrigger = "DialogueExit"; + request.ResumeMode = nameof(SaveResumeMode.StateOnly); + request.StartDialogueOnRestore = false; + request.DedupeKey = TestSaveRecorder.BuildDedupeKey( + request.SceneSoName, + request.YarnProjectId, + request.NodeName, + request.ResumeMode); + request.EntryId = TestSaveRepository.StableHash(request.DedupeKey); + + var entry = _repository.Record(request); + var loaded = _repository.TryLoad(entry, out var snapshot, out var error); + + Assert.That(loaded, Is.True, error); + Assert.That(entry.NodeName, Is.EqualTo("InteractionNode")); + Assert.That(entry.ResumeMode, Is.EqualTo(nameof(SaveResumeMode.StateOnly))); + Assert.That(snapshot.anchor.nodeName, Is.EqualTo("InteractionNode")); + Assert.That(snapshot.anchor.startDialogueOnRestore, Is.False); + } + + [Test] + public void SnapshotPersistence_MissingRestoreFlag_IsRejected() + { + const string json = + "{\"schemaVersion\":2,\"anchor\":{\"sceneSoName\":\"ChapterA\"," + + "\"yarnProjectId\":\"ProjectA\",\"nodeName\":\"NodeA\"}}"; + + Assert.Throws( + () => SnapshotPersistence.Deserialize(json)); + } + + [Test] + public void SerialTaskQueue_DoesNotDropOrReorderRequests() + { + var queue = new SerialTaskQueue(); + var releaseFirst = new TaskCompletionSource(); + var firstStarted = new TaskCompletionSource(); + var order = new List(); + + var first = queue.Enqueue(async () => + { + order.Add(1); + firstStarted.SetResult(true); + await releaseFirst.Task; + order.Add(2); + }); + var second = queue.Enqueue(() => + { + order.Add(3); + return Task.CompletedTask; + }); + + Assert.That(firstStarted.Task.Wait(TimeSpan.FromSeconds(2)), Is.True); + Assert.That(order, Is.EqualTo(new[] { 1 })); + Assert.That(queue.PendingCount, Is.EqualTo(2)); + + releaseFirst.SetResult(true); + Assert.That( + Task.WaitAll( + new[] { first.Completion, second.Completion }, + TimeSpan.FromSeconds(2)), + Is.True); + + Assert.That(first.Sequence, Is.LessThan(second.Sequence)); + Assert.That(order, Is.EqualTo(new[] { 1, 2, 3 })); + } + + [Test] + public void SaveRequest_MapsResumeModeToExplicitAnchorFlag() + { + var enter = SaveRequest.NodeEnter("NodeA", "ProjectA", "ChapterA", 3, 7); + var exit = SaveRequest.DialogueExit("NodeB", "ProjectA", "ChapterA", 3, 9); + + Assert.That(enter.AnchorSpec.NodeName, Is.EqualTo("NodeA")); + Assert.That(enter.AnchorSpec.StartDialogueOnRestore, Is.True); + Assert.That(exit.AnchorSpec.NodeName, Is.EqualTo("NodeB")); + Assert.That(exit.AnchorSpec.StartDialogueOnRestore, Is.False); + } + + [Test] + public void InteractionLock_ComposesWithDialogueLock() + { + var gameObject = new GameObject("EventSystemEx-Test"); + try + { + var eventSystem = gameObject.AddComponent(); + EnumEventSystem.Global.Send(InteractionEventEnum.DialogStart); + var checkpointLock = eventSystem.AcquireInteractionLock("test"); + + EnumEventSystem.Global.Send(InteractionEventEnum.DialogEnd); + Assert.That(eventSystem.isLocked, Is.True); + + checkpointLock.Dispose(); + Assert.That(eventSystem.isLocked, Is.False); + } + finally + { + UnityEngine.Object.DestroyImmediate(gameObject); + } + } + private static TestSaveRecordRequest CreateRequest( string sceneSoName, string yarnProject, @@ -196,7 +327,8 @@ namespace AibisDream.DeveloperMode.Editor.Tests { sceneSoName = sceneSoName, yarnProjectId = yarnProject, - nodeName = nodeName + nodeName = nodeName, + startDialogueOnRestore = true } }, DedupeKey = key, @@ -206,6 +338,9 @@ namespace AibisDream.DeveloperMode.Editor.Tests SceneSoName = sceneSoName, YarnProjectId = yarnProject, NodeName = nodeName, + SaveTrigger = "NodeEnter", + ResumeMode = nameof(SaveResumeMode.RestartNode), + StartDialogueOnRestore = true, SceneName = sceneName, GameVersion = "1.0" }; @@ -222,6 +357,9 @@ namespace AibisDream.DeveloperMode.Editor.Tests sceneSoName = request.SceneSoName, yarnProjectId = request.YarnProjectId, nodeName = request.NodeName, + saveTrigger = request.SaveTrigger, + resumeMode = request.ResumeMode, + startDialogueOnRestore = request.StartDialogueOnRestore, sceneName = request.SceneName, firstSeenOrder = order, firstRecordedAt = "2026-01-01 00:00:00", diff --git a/Assets/Editor/FrameAnimationActorIntegrationTests.cs b/Assets/Editor/FrameAnimationActorIntegrationTests.cs index ffb77ad4d..aa7384bfc 100644 --- a/Assets/Editor/FrameAnimationActorIntegrationTests.cs +++ b/Assets/Editor/FrameAnimationActorIntegrationTests.cs @@ -44,7 +44,7 @@ namespace AibisDream.SystemEditor.Tests } [Test] - public void CaptureEntry_ReusesActorSnapshotFieldsWithoutSchemaChange() + public void CaptureEntry_ReusesActorSnapshotFields() { var prefab = AssetDatabase.LoadAssetAtPath(PrefabPath); var actorObject = Object.Instantiate(prefab); @@ -66,7 +66,6 @@ namespace AibisDream.SystemEditor.Tests Assert.That(entry.actorType, Is.EqualTo(nameof(ActorType.FrameAnimation))); Assert.That(entry.alpha, Is.EqualTo(1f)); Assert.That(entry.stateName, Is.Empty); - Assert.That(SaveSnapshotSchema.CurrentVersion, Is.EqualTo(1)); } finally { diff --git a/Assets/Editor/PresentationSnapshotContractTests.cs b/Assets/Editor/PresentationSnapshotContractTests.cs index 3f5bbfedd..74f8ac368 100644 --- a/Assets/Editor/PresentationSnapshotContractTests.cs +++ b/Assets/Editor/PresentationSnapshotContractTests.cs @@ -44,7 +44,7 @@ namespace AibisDream.SystemEditor.Tests Assert.That(playTool.objPicName, Is.EqualTo("证物")); Assert.That(playTool.isFullScreenVisible, Is.True); Assert.That(playTool.fullScreenPicName, Is.EqualTo("教室")); - Assert.That(restored.schemaVersion, Is.EqualTo(1)); + Assert.That(restored.schemaVersion, Is.EqualTo(SaveSnapshotSchema.CurrentVersion)); } [Test] @@ -84,12 +84,12 @@ namespace AibisDream.SystemEditor.Tests } [Test] - public void OldSnapshotWithoutPresentationSections_RemainsCompatible() + public void OldSnapshotWithoutPresentationSections_DeserializesWithoutSynthesizingSections() { var restored = JsonConvert.DeserializeObject( "{\"schemaVersion\":1,\"sections\":{}}"); - Assert.That(restored.schemaVersion, Is.EqualTo(SaveSnapshotSchema.CurrentVersion)); + Assert.That(restored.schemaVersion, Is.EqualTo(1)); Assert.That(restored.sections.ContainsKey(SnapshotProviderIds.Showcase), Is.False); Assert.That(restored.sections.ContainsKey(SnapshotProviderIds.Day2SleepPresentation), Is.False); Assert.That(restored.sections.ContainsKey(SnapshotProviderIds.PlayTool), Is.False); diff --git a/Assets/GameContent/Huoshan/Actor/火山Graph.asset b/Assets/GameContent/Huoshan/Actor/火山Graph.asset index 4fe1f9592..2b484d69a 100644 --- a/Assets/GameContent/Huoshan/Actor/火山Graph.asset +++ b/Assets/GameContent/Huoshan/Actor/火山Graph.asset @@ -15,10 +15,10 @@ MonoBehaviour: id: "\u6263\u5934\u706F\u6CE1" displayName: "\u6263\u5934\u706F\u6CE1" frames: - - sprite: {fileID: 6147323577121316844, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + - sprite: {fileID: -1597267871085758117, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} durationMs: 300 - frameName: "\u706B\u5C71\u50CF\u7D20\u7248 23.aseprite" - sourceIndex: 23 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 22.aseprite" + sourceIndex: 22 speed: 1 defaultEndBehavior: 1 hasImportInfo: 1 @@ -49,6 +49,10 @@ MonoBehaviour: id: "\u4F38\u624B\u8868\u60C5idle" displayName: "\u4F38\u624B\u8868\u60C5idle" frames: + - sprite: {fileID: -4164942248284793206, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 0.aseprite" + sourceIndex: 0 - sprite: {fileID: -1677818779029218552, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} durationMs: 300 frameName: "\u706B\u5C71\u50CF\u7D20\u7248 1.aseprite" @@ -73,10 +77,6 @@ MonoBehaviour: durationMs: 300 frameName: "\u706B\u5C71\u50CF\u7D20\u7248 6.aseprite" sourceIndex: 6 - - sprite: {fileID: 7141184682861996702, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} - durationMs: 300 - frameName: "\u706B\u5C71\u50CF\u7D20\u7248 7.aseprite" - sourceIndex: 7 speed: 1 defaultEndBehavior: 1 hasImportInfo: 1 @@ -92,6 +92,44 @@ MonoBehaviour: manageSpriteSlicing: 0 lastSourceHash: lastImportedTagName: +--- !u!114 &-8037865275180630762 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 408fe45af4d321848a6c97f0356e8e5c, type: 3} + m_Name: "\u706B\u5C71\u7ACB\u7231\u5FC3" + m_EditorClassIdentifier: + id: "\u706B\u5C71\u7ACB\u7231\u5FC3" + displayName: "\u706B\u5C71\u7ACB\u7231\u5FC3" + frames: + - sprite: {fileID: 1165957775, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 58.aseprite" + sourceIndex: 58 + - sprite: {fileID: 724704929, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 59.aseprite" + sourceIndex: 59 + speed: 1 + defaultEndBehavior: 1 + hasImportInfo: 1 + importInfo: + importSourceId: d329feaf92a945f885e419c05824cd56 + sourceTagName: "\u706B\u5C71\u7ACB\u7231\u5FC3" + isMissingFromSource: 0 + hasStandaloneImportSource: 0 + standaloneImportSource: + texture: {fileID: 0} + asepriteJson: {fileID: 0} + pivot: {x: 0.5, y: 0.5} + manageSpriteSlicing: 0 + lastSourceHash: + lastImportedTagName: --- !u!114 &-5742946164860628285 MonoBehaviour: m_ObjectHideFlags: 0 @@ -107,6 +145,10 @@ MonoBehaviour: id: "\u6342\u5934\u8868\u60C5idle" displayName: "\u6342\u5934\u8868\u60C5idle" frames: + - sprite: {fileID: 7853721251838497650, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 42.aseprite" + sourceIndex: 42 - sprite: {fileID: 1773845448817315849, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} durationMs: 300 frameName: "\u706B\u5C71\u50CF\u7D20\u7248 43.aseprite" @@ -131,10 +173,6 @@ MonoBehaviour: durationMs: 300 frameName: "\u706B\u5C71\u50CF\u7D20\u7248 48.aseprite" sourceIndex: 48 - - sprite: {fileID: 711362045575723135, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} - durationMs: 300 - frameName: "\u706B\u5C71\u50CF\u7D20\u7248 49.aseprite" - sourceIndex: 49 speed: 1 defaultEndBehavior: 1 hasImportInfo: 1 @@ -165,10 +203,10 @@ MonoBehaviour: id: "\u6263\u5934 \uFF1F" displayName: "\u6263\u5934 \uFF1F" frames: - - sprite: {fileID: -1597267871085758117, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + - sprite: {fileID: -3742796876328757744, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} durationMs: 300 - frameName: "\u706B\u5C71\u50CF\u7D20\u7248 22.aseprite" - sourceIndex: 22 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 21.aseprite" + sourceIndex: 21 speed: 1 defaultEndBehavior: 0 hasImportInfo: 1 @@ -184,40 +222,6 @@ MonoBehaviour: manageSpriteSlicing: 0 lastSourceHash: lastImportedTagName: ---- !u!114 &-1981100710209546618 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 408fe45af4d321848a6c97f0356e8e5c, type: 3} - m_Name: "\u4F38\u624B \u77F3\u5316\u8868\u60C5" - m_EditorClassIdentifier: - id: "\u4F38\u624B \u77F3\u5316\u8868\u60C5" - displayName: "\u4F38\u624B \u77F3\u5316\u8868\u60C5" - frames: - - sprite: {fileID: 3023878692377788431, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} - durationMs: 300 - frameName: "\u706B\u5C71\u50CF\u7D20\u7248 8.aseprite" - sourceIndex: 8 - speed: 1 - defaultEndBehavior: 0 - hasImportInfo: 1 - importInfo: - importSourceId: d329feaf92a945f885e419c05824cd56 - sourceTagName: "\u4F38\u624B \u77F3\u5316\u8868\u60C5" - isMissingFromSource: 0 - hasStandaloneImportSource: 0 - standaloneImportSource: - texture: {fileID: 0} - asepriteJson: {fileID: 0} - pivot: {x: 0.5, y: 0.5} - manageSpriteSlicing: 0 - lastSourceHash: - lastImportedTagName: --- !u!114 &-1158850888323987525 MonoBehaviour: m_ObjectHideFlags: 0 @@ -233,10 +237,10 @@ MonoBehaviour: id: "\u62FF\u4F4F\u5E3D\u5B50" displayName: "\u62FF\u4F4F\u5E3D\u5B50" frames: - - sprite: {fileID: -7408847304050000695, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + - sprite: {fileID: 711362045575723135, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} durationMs: 300 - frameName: "\u706B\u5C71\u50CF\u7D20\u7248 50.aseprite" - sourceIndex: 50 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 49.aseprite" + sourceIndex: 49 speed: 1 defaultEndBehavior: 1 hasImportInfo: 1 @@ -267,6 +271,10 @@ MonoBehaviour: id: "\u6263\u5934\u5207\u5C4F\u7279\u6548" displayName: "\u6263\u5934\u5207\u5C4F\u7279\u6548" frames: + - sprite: {fileID: 6147323577121316844, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 100 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 23.aseprite" + sourceIndex: 23 - sprite: {fileID: 8112637510959776406, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} durationMs: 100 frameName: "\u706B\u5C71\u50CF\u7D20\u7248 24.aseprite" @@ -287,10 +295,6 @@ MonoBehaviour: durationMs: 100 frameName: "\u706B\u5C71\u50CF\u7D20\u7248 28.aseprite" sourceIndex: 28 - - sprite: {fileID: -7420326846939562944, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} - durationMs: 100 - frameName: "\u706B\u5C71\u50CF\u7D20\u7248 29.aseprite" - sourceIndex: 29 speed: 1 defaultEndBehavior: 0 hasImportInfo: 1 @@ -322,7 +326,6 @@ MonoBehaviour: displayName: "\u706B\u5C71Graph" clips: - {fileID: -8307372092058666549} - - {fileID: -1981100710209546618} - {fileID: 7171718461941095968} - {fileID: -2521262061966760486} - {fileID: -9029408385253611036} @@ -333,6 +336,12 @@ MonoBehaviour: - {fileID: -1158850888323987525} - {fileID: 8692045413535011072} - {fileID: 9210071199681937383} + - {fileID: 7179291567807344696} + - {fileID: 5571957112070260853} + - {fileID: -8037865275180630762} + - {fileID: 2123298223373503916} + - {fileID: 2435584756273942976} + - {fileID: 3900209379325061236} nodes: [] edges: [] flows: [] @@ -345,13 +354,205 @@ MonoBehaviour: pivot: {x: 0.5, y: 0} manageSpriteSlicing: 1 defaultNewClipEndBehavior: 1 - lastSourceHash: 03aa43972baa03853708e40fc6c9033f6a3d5aeaa4e52a1d9c3e7f909921509a + lastSourceHash: 3bde2d51887d87b2797e63607cbd0476580a7f32625ba86bce368431ae2a3750 settings: defaultPlayableId: "\u4F38\u624B\u8868\u60C5idle" newManualClipDefaultEndBehavior: 0 editorData: nodeEditorData: [] flowEditorData: [] +--- !u!114 &2123298223373503916 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 408fe45af4d321848a6c97f0356e8e5c, type: 3} + m_Name: "\u706B\u5C71\u7ACB\u5E3D\u5B50" + m_EditorClassIdentifier: + id: "\u706B\u5C71\u7ACB\u5E3D\u5B50" + displayName: "\u706B\u5C71\u7ACB\u5E3D\u5B50" + frames: + - sprite: {fileID: 1934625881, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 60.aseprite" + sourceIndex: 60 + speed: 1 + defaultEndBehavior: 1 + hasImportInfo: 1 + importInfo: + importSourceId: d329feaf92a945f885e419c05824cd56 + sourceTagName: "\u706B\u5C71\u7ACB\u5E3D\u5B50" + isMissingFromSource: 0 + hasStandaloneImportSource: 0 + standaloneImportSource: + texture: {fileID: 0} + asepriteJson: {fileID: 0} + pivot: {x: 0.5, y: 0.5} + manageSpriteSlicing: 0 + lastSourceHash: + lastImportedTagName: +--- !u!114 &2435584756273942976 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 408fe45af4d321848a6c97f0356e8e5c, type: 3} + m_Name: "\u706B\u5C71\u7ACB\u5207\u5C4F\u7279\u6548" + m_EditorClassIdentifier: + id: "\u706B\u5C71\u7ACB\u5207\u5C4F\u7279\u6548" + displayName: "\u706B\u5C71\u7ACB\u5207\u5C4F\u7279\u6548" + frames: + - sprite: {fileID: -797704885, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 100 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 61.aseprite" + sourceIndex: 61 + - sprite: {fileID: -1458435954, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 100 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 62.aseprite" + sourceIndex: 62 + - sprite: {fileID: -333109225, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 100 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 63.aseprite" + sourceIndex: 63 + - sprite: {fileID: -1362429362, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 100 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 64.aseprite" + sourceIndex: 64 + - sprite: {fileID: -679944024, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 100 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 65.aseprite" + sourceIndex: 65 + - sprite: {fileID: -1037734280, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 100 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 66.aseprite" + sourceIndex: 66 + speed: 1 + defaultEndBehavior: 1 + hasImportInfo: 1 + importInfo: + importSourceId: d329feaf92a945f885e419c05824cd56 + sourceTagName: "\u706B\u5C71\u7ACB\u5207\u5C4F\u7279\u6548" + isMissingFromSource: 0 + hasStandaloneImportSource: 0 + standaloneImportSource: + texture: {fileID: 0} + asepriteJson: {fileID: 0} + pivot: {x: 0.5, y: 0.5} + manageSpriteSlicing: 0 + lastSourceHash: + lastImportedTagName: +--- !u!114 &3900209379325061236 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 408fe45af4d321848a6c97f0356e8e5c, type: 3} + m_Name: "\u6307\u533B\u751Fidle" + m_EditorClassIdentifier: + id: "\u6307\u533B\u751Fidle" + displayName: "\u6307\u533B\u751Fidle" + frames: + - sprite: {fileID: 1184580192, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 200 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 67.aseprite" + sourceIndex: 67 + - sprite: {fileID: 1227746343, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 68.aseprite" + sourceIndex: 68 + - sprite: {fileID: -1235719373, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 69.aseprite" + sourceIndex: 69 + - sprite: {fileID: 480632, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 200 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 70.aseprite" + sourceIndex: 70 + speed: 1 + defaultEndBehavior: 1 + hasImportInfo: 1 + importInfo: + importSourceId: d329feaf92a945f885e419c05824cd56 + sourceTagName: "\u6307\u533B\u751Fidle" + isMissingFromSource: 0 + hasStandaloneImportSource: 0 + standaloneImportSource: + texture: {fileID: 0} + asepriteJson: {fileID: 0} + pivot: {x: 0.5, y: 0.5} + manageSpriteSlicing: 0 + lastSourceHash: + lastImportedTagName: +--- !u!114 &5571957112070260853 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 408fe45af4d321848a6c97f0356e8e5c, type: 3} + m_Name: "\u706B\u5C71\u7ACB\u8868\u60C5idle" + m_EditorClassIdentifier: + id: "\u706B\u5C71\u7ACB\u8868\u60C5idle" + displayName: "\u706B\u5C71\u7ACB\u8868\u60C5idle" + frames: + - sprite: {fileID: -9064000754950765326, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 51.aseprite" + sourceIndex: 51 + - sprite: {fileID: 476753166, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 52.aseprite" + sourceIndex: 52 + - sprite: {fileID: -290437651, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 53.aseprite" + sourceIndex: 53 + - sprite: {fileID: 1161122348, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 54.aseprite" + sourceIndex: 54 + - sprite: {fileID: -1682718823, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 55.aseprite" + sourceIndex: 55 + - sprite: {fileID: 2006670954, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 56.aseprite" + sourceIndex: 56 + - sprite: {fileID: -1240037077, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 57.aseprite" + sourceIndex: 57 + speed: 1 + defaultEndBehavior: 1 + hasImportInfo: 1 + importInfo: + importSourceId: d329feaf92a945f885e419c05824cd56 + sourceTagName: "\u706B\u5C71\u7ACB\u8868\u60C5idle" + isMissingFromSource: 0 + hasStandaloneImportSource: 0 + standaloneImportSource: + texture: {fileID: 0} + asepriteJson: {fileID: 0} + pivot: {x: 0.5, y: 0.5} + manageSpriteSlicing: 0 + lastSourceHash: + lastImportedTagName: --- !u!114 &6833375499271667009 MonoBehaviour: m_ObjectHideFlags: 0 @@ -367,6 +568,10 @@ MonoBehaviour: id: "\u5BF9\u624B\u6307\u5207\u5C4F\u7279\u6548" displayName: "\u5BF9\u624B\u6307\u5207\u5C4F\u7279\u6548" frames: + - sprite: {fileID: 8063529297442791384, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 100 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 36.aseprite" + sourceIndex: 36 - sprite: {fileID: 5032543470190648888, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} durationMs: 100 frameName: "\u706B\u5C71\u50CF\u7D20\u7248 37.aseprite" @@ -387,10 +592,6 @@ MonoBehaviour: durationMs: 100 frameName: "\u706B\u5C71\u50CF\u7D20\u7248 41.aseprite" sourceIndex: 41 - - sprite: {fileID: 7853721251838497650, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} - durationMs: 100 - frameName: "\u706B\u5C71\u50CF\u7D20\u7248 42.aseprite" - sourceIndex: 42 speed: 1 defaultEndBehavior: 1 hasImportInfo: 1 @@ -421,6 +622,10 @@ MonoBehaviour: id: "\u6263\u5934\u8868\u60C5idle" displayName: "\u6263\u5934\u8868\u60C5idle" frames: + - sprite: {fileID: -280250252267852960, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 14.aseprite" + sourceIndex: 14 - sprite: {fileID: 4436847421114479055, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} durationMs: 300 frameName: "\u706B\u5C71\u50CF\u7D20\u7248 15.aseprite" @@ -445,10 +650,6 @@ MonoBehaviour: durationMs: 300 frameName: "\u706B\u5C71\u50CF\u7D20\u7248 20.aseprite" sourceIndex: 20 - - sprite: {fileID: -3742796876328757744, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} - durationMs: 300 - frameName: "\u706B\u5C71\u50CF\u7D20\u7248 21.aseprite" - sourceIndex: 21 speed: 1 defaultEndBehavior: 1 hasImportInfo: 1 @@ -464,6 +665,40 @@ MonoBehaviour: manageSpriteSlicing: 0 lastSourceHash: lastImportedTagName: +--- !u!114 &7179291567807344696 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 408fe45af4d321848a6c97f0356e8e5c, type: 3} + m_Name: "\u4F38\u624B\u77F3\u5316\u8868\u60C5" + m_EditorClassIdentifier: + id: "\u4F38\u624B\u77F3\u5316\u8868\u60C5" + displayName: "\u4F38\u624B\u77F3\u5316\u8868\u60C5" + frames: + - sprite: {fileID: 7141184682861996702, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 7.aseprite" + sourceIndex: 7 + speed: 1 + defaultEndBehavior: 1 + hasImportInfo: 1 + importInfo: + importSourceId: d329feaf92a945f885e419c05824cd56 + sourceTagName: "\u4F38\u624B\u77F3\u5316\u8868\u60C5" + isMissingFromSource: 0 + hasStandaloneImportSource: 0 + standaloneImportSource: + texture: {fileID: 0} + asepriteJson: {fileID: 0} + pivot: {x: 0.5, y: 0.5} + manageSpriteSlicing: 0 + lastSourceHash: + lastImportedTagName: --- !u!114 &8692045413535011072 MonoBehaviour: m_ObjectHideFlags: 0 @@ -479,10 +714,10 @@ MonoBehaviour: id: "\u6458\u5E3D" displayName: "\u6458\u5E3D" frames: - - sprite: {fileID: -9064000754950765326, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + - sprite: {fileID: -7408847304050000695, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} durationMs: 300 - frameName: "\u706B\u5C71\u50CF\u7D20\u7248 51.aseprite" - sourceIndex: 51 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 50.aseprite" + sourceIndex: 50 speed: 1 defaultEndBehavior: 1 hasImportInfo: 1 @@ -513,6 +748,10 @@ MonoBehaviour: id: "\u5BF9\u624B\u6307\u8868\u60C5idle" displayName: "\u5BF9\u624B\u6307\u8868\u60C5idle" frames: + - sprite: {fileID: -7420326846939562944, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 300 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 29.aseprite" + sourceIndex: 29 - sprite: {fileID: 6693685528016350094, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} durationMs: 300 frameName: "\u706B\u5C71\u50CF\u7D20\u7248 30.aseprite" @@ -537,10 +776,6 @@ MonoBehaviour: durationMs: 300 frameName: "\u706B\u5C71\u50CF\u7D20\u7248 35.aseprite" sourceIndex: 35 - - sprite: {fileID: 8063529297442791384, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} - durationMs: 300 - frameName: "\u706B\u5C71\u50CF\u7D20\u7248 36.aseprite" - sourceIndex: 36 speed: 1 defaultEndBehavior: 1 hasImportInfo: 1 @@ -571,6 +806,10 @@ MonoBehaviour: id: "\u4F38\u624B\u5207\u5C4F\u7279\u6548" displayName: "\u4F38\u624B\u5207\u5C4F\u7279\u6548" frames: + - sprite: {fileID: 3023878692377788431, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} + durationMs: 100 + frameName: "\u706B\u5C71\u50CF\u7D20\u7248 8.aseprite" + sourceIndex: 8 - sprite: {fileID: 328454971127517396, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} durationMs: 100 frameName: "\u706B\u5C71\u50CF\u7D20\u7248 9.aseprite" @@ -591,10 +830,6 @@ MonoBehaviour: durationMs: 100 frameName: "\u706B\u5C71\u50CF\u7D20\u7248 13.aseprite" sourceIndex: 13 - - sprite: {fileID: -280250252267852960, guid: 88f27e53d9104824ca9d666f01dd908a, type: 3} - durationMs: 100 - frameName: "\u706B\u5C71\u50CF\u7D20\u7248 14.aseprite" - sourceIndex: 14 speed: 1 defaultEndBehavior: 1 hasImportInfo: 1 diff --git a/Assets/GameContent/Huoshan/Actor/火山像素版.aseprite b/Assets/GameContent/Huoshan/Actor/火山像素版.aseprite new file mode 100644 index 000000000..5db60083b Binary files /dev/null and b/Assets/GameContent/Huoshan/Actor/火山像素版.aseprite differ diff --git a/Assets/GameContent/Huoshan/Actor/火山像素版.aseprite.meta b/Assets/GameContent/Huoshan/Actor/火山像素版.aseprite.meta new file mode 100644 index 000000000..b0676ea3e --- /dev/null +++ b/Assets/GameContent/Huoshan/Actor/火山像素版.aseprite.meta @@ -0,0 +1,2124 @@ +fileFormatVersion: 2 +guid: 3d49bb35a83135d489e61d8144661285 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 62a9f0aa5b59740cfbadc7e5f9823bb0, type: 3} + textureImporterSettings: + alphaSource: 1 + mipMapMode: 0 + enableMipMap: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + convertToNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + swizzle: 50462976 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + nPOTScale: 1 + sRGBTexture: 1 + spriteMode: 2 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 0 + flipbookColumns: 0 + ignorePngGamma: 0 + cookieMode: 0 + filterMode: 0 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + normalMap: 0 + textureFormat: 0 + maxTextureSize: 0 + lightmap: 0 + compressionQuality: 0 + linearTexture: 0 + grayScaleToAlpha: 0 + rGBM: 0 + cubemapConvolutionSteps: 0 + cubemapConvolutionExponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + previousAsepriteImporterSettings: + fileImportMode: 1 + importHiddenLayers: 0 + layerImportMode: 1 + defaultPivotSpace: 0 + defaultPivotAlignment: 7 + customPivotPosition: {x: 0.5, y: 0.5} + spritePadding: 0 + generateModelPrefab: 1 + generateAnimationClips: 1 + addSortingGroup: 1 + addShadowCasters: 0 + asepriteImporterSettings: + fileImportMode: 1 + importHiddenLayers: 0 + layerImportMode: 1 + defaultPivotSpace: 0 + defaultPivotAlignment: 7 + customPivotPosition: {x: 0.5, y: 0.5} + spritePadding: 0 + generateModelPrefab: 1 + generateAnimationClips: 1 + addSortingGroup: 1 + addShadowCasters: 0 + importFileNodeState: 1 + platformSettingsDirtyTick: 0 + textureAssetName: + singleSpriteImportData: + - name: + originalName: + pivot: {x: 0, y: 0} + alignment: 0 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + spriteID: + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 0, y: 0} + animatedSpriteImportData: + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_67" + originalName: + pivot: {x: 0.5484848, y: -0.1800643} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1439 + y: 323 + width: 330 + height: 311 + spriteID: 7536c5b1b809cad4f9e5aa3d566597f5 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1439, y: 323} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_68" + originalName: + pivot: {x: 0.5484848, y: -0.1800643} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1439 + y: 642 + width: 330 + height: 311 + spriteID: 47b1759d7ea6eb947bb9ce9dc38a804d + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1439, y: 642} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_69" + originalName: + pivot: {x: 0.5484848, y: -0.1800643} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1439 + y: 961 + width: 330 + height: 311 + spriteID: d0376665c95c96545889bbe8df952f2e + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1439, y: 961} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_70" + originalName: + pivot: {x: 0.52463764, y: -0.1800643} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1439 + y: 4 + width: 345 + height: 311 + spriteID: e3888afd58a5afb4b9362b5b53106719 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1439, y: 4} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_51" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1439 + y: 1280 + width: 288 + height: 335 + spriteID: d81eaa44ccf4baa46bbc40a77f8480fe + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1439, y: 1280} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_52" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1439 + y: 1623 + width: 288 + height: 335 + spriteID: f7ec8c4d1fd2c3840a3ff989b104da0a + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1439, y: 1623} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_53" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1439 + y: 1966 + width: 288 + height: 335 + spriteID: 618fe28453fb5c94e9b19eb11666cdb2 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1439, y: 1966} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_54" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1439 + y: 2309 + width: 288 + height: 335 + spriteID: 3188e167cf7cec74999bd0c126164cd7 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1439, y: 2309} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_55" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1439 + y: 2652 + width: 288 + height: 335 + spriteID: 1446bf8961aa72248b9da0cbd94d9b5c + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1439, y: 2652} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_56" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1439 + y: 2995 + width: 288 + height: 335 + spriteID: e924edd09ae1f284e8a51f0bd5b04875 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1439, y: 2995} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_57" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1439 + y: 3338 + width: 288 + height: 335 + spriteID: 63f2becfd2b465440bd27e9eb0d33831 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1439, y: 3338} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_58" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1439 + y: 3681 + width: 288 + height: 335 + spriteID: 1300c6f786c97df4fb9f8bdf8989a36e + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1439, y: 3681} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_59" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1111 + y: 408 + width: 288 + height: 335 + spriteID: 0556f30333c1c814fb119b2c1351ee44 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1111, y: 408} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_60" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1111 + y: 751 + width: 288 + height: 335 + spriteID: 8bc490f1fec39ff4f8593bdb617800f3 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1111, y: 751} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_61" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1111 + y: 1094 + width: 288 + height: 335 + spriteID: 764298aa89898a343a70d827c28102c7 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1111, y: 1094} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_62" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1111 + y: 1437 + width: 288 + height: 335 + spriteID: 22b3f2719f3d20b4fa78cb2e638dba0f + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1111, y: 1437} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_63" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1111 + y: 1780 + width: 288 + height: 335 + spriteID: bb28fa02905b02f448bed70b57da1ab3 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1111, y: 1780} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_64" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1111 + y: 2123 + width: 288 + height: 335 + spriteID: b90b610e9c5dbd34f842a42cde9fadfb + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1111, y: 2123} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_65" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1111 + y: 2466 + width: 288 + height: 335 + spriteID: 09302375ab6aeb94c9beb53c4214236c + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1111, y: 2466} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_66" + originalName: + pivot: {x: 0.6458333, y: -0.2358209} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1111 + y: 2809 + width: 288 + height: 335 + spriteID: cf92eff2415ed1a4b8e188053cd96069 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1111, y: 2809} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_50" + originalName: + pivot: {x: 0.71428573, y: 0} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 718 + y: 4 + width: 385 + height: 346 + spriteID: 88d6461142abfff4584f9b60ab87a5fb + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 718, y: 4} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_49" + originalName: + pivot: {x: 0.415625, y: -0.012626261} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1111 + y: 4 + width: 320 + height: 396 + spriteID: cfdbab315da25044b9742fc3d50d792a + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1111, y: 4} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_42" + originalName: + pivot: {x: 0.6367188, y: -0.013550135} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 2306 + y: 4 + width: 256 + height: 369 + spriteID: 64c87b6e2e978c240b1e6077080cadee + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 2306, y: 4} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_43" + originalName: + pivot: {x: 0.6367188, y: -0.013550135} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 2306 + y: 381 + width: 256 + height: 369 + spriteID: 44272823f5f89ba47b3cbcbe86fee589 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 2306, y: 381} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_44" + originalName: + pivot: {x: 0.6367188, y: -0.013550135} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 2306 + y: 758 + width: 256 + height: 369 + spriteID: acc9f163373ee464296b8a4075245647 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 2306, y: 758} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_45" + originalName: + pivot: {x: 0.6367188, y: -0.013550135} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 2306 + y: 1135 + width: 256 + height: 369 + spriteID: a5e1b982954398340826dba27a6c67f0 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 2306, y: 1135} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_46" + originalName: + pivot: {x: 0.6367188, y: -0.013550135} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 2306 + y: 1512 + width: 256 + height: 369 + spriteID: 4e2125bc1198d5243b637e36f0459e80 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 2306, y: 1512} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_47" + originalName: + pivot: {x: 0.6367188, y: -0.013550135} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 2306 + y: 1889 + width: 256 + height: 369 + spriteID: a5174888dac8e904b9d1cc0d5fac6e5c + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 2306, y: 1889} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_48" + originalName: + pivot: {x: 0.6367188, y: -0.013550135} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 2306 + y: 2266 + width: 256 + height: 369 + spriteID: ff1958764913c2c438bdc22704549fb9 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 2306, y: 2266} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_29" + originalName: + pivot: {x: 0.48995984, y: -0.055263158} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1111 + y: 3152 + width: 249 + height: 380 + spriteID: ad79d8b0423a07345919a274dda86bc0 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1111, y: 3152} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_30" + originalName: + pivot: {x: 0.48995984, y: -0.055263158} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1111 + y: 3540 + width: 249 + height: 380 + spriteID: cb2787dab12d6df45aaa67666b9f7f8e + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1111, y: 3540} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_31" + originalName: + pivot: {x: 0.48995984, y: -0.055263158} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1792 + y: 4 + width: 249 + height: 380 + spriteID: dac6245cb7d086c448d6b15353acaf6b + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1792, y: 4} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_32" + originalName: + pivot: {x: 0.48995984, y: -0.055263158} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1792 + y: 392 + width: 249 + height: 380 + spriteID: 8a4fe7906953f134bbfad3a62e5d4773 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1792, y: 392} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_33" + originalName: + pivot: {x: 0.48995984, y: -0.055263158} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1792 + y: 780 + width: 249 + height: 380 + spriteID: 7ed9305a08d17c147aea41e3612edb5a + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1792, y: 780} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_34" + originalName: + pivot: {x: 0.48995984, y: -0.055263158} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1792 + y: 1168 + width: 249 + height: 380 + spriteID: 5a866e8375a08924892ea56975e7d56a + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1792, y: 1168} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_35" + originalName: + pivot: {x: 0.48995984, y: -0.055263158} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1792 + y: 1556 + width: 249 + height: 380 + spriteID: 1faed0c69c06f8649a777bac8c2a3cf1 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1792, y: 1556} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_36" + originalName: + pivot: {x: 0.48995984, y: -0.055263158} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1792 + y: 1944 + width: 249 + height: 380 + spriteID: b1e2cff8623f7ed49810799116453d7c + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1792, y: 1944} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_37" + originalName: + pivot: {x: 0.48995984, y: -0.055263158} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1792 + y: 2332 + width: 249 + height: 380 + spriteID: 030a7eb6734306e4ba0658672bca9318 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1792, y: 2332} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_38" + originalName: + pivot: {x: 0.48995984, y: -0.055263158} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1792 + y: 2720 + width: 249 + height: 380 + spriteID: 688e9317700552340b3f04dc8b10b4fd + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1792, y: 2720} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_39" + originalName: + pivot: {x: 0.48995984, y: -0.055263158} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1792 + y: 3108 + width: 249 + height: 380 + spriteID: e87b6d2cd38156040b83548e2eeb1663 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1792, y: 3108} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_40" + originalName: + pivot: {x: 0.48995984, y: -0.055263158} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 1792 + y: 3496 + width: 249 + height: 380 + spriteID: 779addf31e6856345b43fc6441cae776 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 1792, y: 3496} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_41" + originalName: + pivot: {x: 0.48995984, y: -0.055263158} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 2049 + y: 4 + width: 249 + height: 380 + spriteID: 55ac07d4e5cf05b4ea5c140282dbe7ac + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 2049, y: 4} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_14" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 4 + y: 4 + width: 349 + height: 395 + spriteID: 5e6a57edaf7baa9428ace4a8ee532815 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 4, y: 4} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_15" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 4 + y: 407 + width: 349 + height: 395 + spriteID: 6524ae96fef3e1d47a0eea07efe19477 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 4, y: 407} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_16" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 4 + y: 810 + width: 349 + height: 395 + spriteID: dc575b5810bf6a548935db6a03a5bae4 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 4, y: 810} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_17" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 4 + y: 1213 + width: 349 + height: 395 + spriteID: 1f7d9ea0b73e45045bc0107bdf384b60 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 4, y: 1213} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_18" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 4 + y: 1616 + width: 349 + height: 395 + spriteID: 1fcbf9cdaf062744ab6aee5579c768ba + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 4, y: 1616} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_19" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 4 + y: 2019 + width: 349 + height: 395 + spriteID: 93a1c538a250a754db9b321ddfa76845 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 4, y: 2019} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_20" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 4 + y: 2422 + width: 349 + height: 395 + spriteID: 6ab616e0f681c8b4d861d2efdcfc309a + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 4, y: 2422} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_21" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 4 + y: 2825 + width: 349 + height: 395 + spriteID: d73c5f7258e3f194a8a435a23918b66f + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 4, y: 2825} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_22" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 4 + y: 3228 + width: 349 + height: 395 + spriteID: 19f1861086a28da4daad6f2d31047e67 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 4, y: 3228} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_23" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 4 + y: 3631 + width: 349 + height: 395 + spriteID: 8386ab5d6bcfd0d4fb800139040528eb + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 4, y: 3631} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_24" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 361 + y: 4 + width: 349 + height: 395 + spriteID: 1efc224fb630c10468ef313b5b244d43 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 361, y: 4} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_25" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 361 + y: 407 + width: 349 + height: 395 + spriteID: f5dff738dc5bee1499ffc750aa2f1fc1 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 361, y: 407} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_26" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 361 + y: 810 + width: 349 + height: 395 + spriteID: 728a95f18375a644b8d962349c615f93 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 361, y: 810} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_27" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 361 + y: 1213 + width: 349 + height: 395 + spriteID: f0586b008f19e4c4e9d2a05da3d17912 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 361, y: 1213} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_28" + originalName: + pivot: {x: 0.46704873, y: -0.012658228} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 361 + y: 1616 + width: 349 + height: 395 + spriteID: 20d2e715c2b3da14ba3ee33d6ce88ca6 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 361, y: 1616} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_0" + originalName: + pivot: {x: 0.70481926, y: -0.024999999} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 361 + y: 2019 + width: 332 + height: 400 + spriteID: 4336edabc8ce0104cae15c6488309d5b + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 361, y: 2019} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_1" + originalName: + pivot: {x: 0.70481926, y: -0.024999999} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 361 + y: 2427 + width: 332 + height: 400 + spriteID: ebec265cef6079e44bf523ef46bff018 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 361, y: 2427} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_2" + originalName: + pivot: {x: 0.70481926, y: -0.024999999} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 361 + y: 2835 + width: 332 + height: 400 + spriteID: 4477cbbf04800e84d9b33e2434f5e7bb + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 361, y: 2835} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_3" + originalName: + pivot: {x: 0.70481926, y: -0.024999999} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 361 + y: 3243 + width: 332 + height: 400 + spriteID: d430a60149bc61042b80295338fef774 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 361, y: 3243} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_4" + originalName: + pivot: {x: 0.70481926, y: -0.024999999} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 361 + y: 3651 + width: 332 + height: 400 + spriteID: 2e18530d133c52f44b953cb7fdfc1802 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 361, y: 3651} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_5" + originalName: + pivot: {x: 0.70481926, y: -0.024999999} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 718 + y: 358 + width: 332 + height: 400 + spriteID: 1042ce1c023fd5d4eb6b1d09933aad46 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 718, y: 358} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_6" + originalName: + pivot: {x: 0.70481926, y: -0.024999999} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 718 + y: 766 + width: 332 + height: 400 + spriteID: 35b6c17ff36947549b8e1c3dada8562e + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 718, y: 766} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_7" + originalName: + pivot: {x: 0.70481926, y: -0.024999999} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 718 + y: 1174 + width: 332 + height: 400 + spriteID: ecc2cbad9a035cb44b4e319c2497b595 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 718, y: 1174} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_8" + originalName: + pivot: {x: 0.70481926, y: -0.024999999} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 718 + y: 1582 + width: 332 + height: 400 + spriteID: 428ecf4448f63cb4dafce5263caa3b99 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 718, y: 1582} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_9" + originalName: + pivot: {x: 0.70481926, y: -0.024999999} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 718 + y: 1990 + width: 332 + height: 400 + spriteID: c3524d26d54029440ba6266db9a7e469 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 718, y: 1990} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_10" + originalName: + pivot: {x: 0.70481926, y: -0.024999999} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 718 + y: 2398 + width: 332 + height: 400 + spriteID: a41b32f5fc658aa4aa549b02862afe19 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 718, y: 2398} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_11" + originalName: + pivot: {x: 0.70481926, y: -0.024999999} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 718 + y: 2806 + width: 332 + height: 400 + spriteID: 3519a0a01dceee049b2dfe58fd7f2a37 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 718, y: 2806} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_12" + originalName: + pivot: {x: 0.70481926, y: -0.024999999} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 718 + y: 3214 + width: 332 + height: 400 + spriteID: d70e7312d0ba0a54c91d1a8351053510 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 718, y: 3214} + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_13" + originalName: + pivot: {x: 0.70481926, y: -0.024999999} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 718 + y: 3622 + width: 332 + height: 400 + spriteID: 673d2d5d6ec3283458e7f419797803eb + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 718, y: 3622} + spriteSheetImportData: [] + asepriteLayers: + - layerIndex: 0 + guid: -2100781431 + name: "\u706B\u5C71\u50CF\u7D20\u7248" + layerFlags: 0 + layerType: 0 + blendMode: 0 + cells: + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_67" + frameIndex: 67 + cellRect: + x: 94 + y: 56 + width: 330 + height: 311 + spriteId: 7536c5b1b809cad4f9e5aa3d566597f5 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_68" + frameIndex: 68 + cellRect: + x: 94 + y: 56 + width: 330 + height: 311 + spriteId: 47b1759d7ea6eb947bb9ce9dc38a804d + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_69" + frameIndex: 69 + cellRect: + x: 94 + y: 56 + width: 330 + height: 311 + spriteId: d0376665c95c96545889bbe8df952f2e + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_70" + frameIndex: 70 + cellRect: + x: 94 + y: 56 + width: 345 + height: 311 + spriteId: e3888afd58a5afb4b9362b5b53106719 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_51" + frameIndex: 51 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: d81eaa44ccf4baa46bbc40a77f8480fe + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_52" + frameIndex: 52 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: f7ec8c4d1fd2c3840a3ff989b104da0a + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_53" + frameIndex: 53 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: 618fe28453fb5c94e9b19eb11666cdb2 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_54" + frameIndex: 54 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: 3188e167cf7cec74999bd0c126164cd7 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_55" + frameIndex: 55 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: 1446bf8961aa72248b9da0cbd94d9b5c + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_56" + frameIndex: 56 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: e924edd09ae1f284e8a51f0bd5b04875 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_57" + frameIndex: 57 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: 63f2becfd2b465440bd27e9eb0d33831 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_58" + frameIndex: 58 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: 1300c6f786c97df4fb9f8bdf8989a36e + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_59" + frameIndex: 59 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: 0556f30333c1c814fb119b2c1351ee44 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_60" + frameIndex: 60 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: 8bc490f1fec39ff4f8593bdb617800f3 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_61" + frameIndex: 61 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: 764298aa89898a343a70d827c28102c7 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_62" + frameIndex: 62 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: 22b3f2719f3d20b4fa78cb2e638dba0f + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_63" + frameIndex: 63 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: bb28fa02905b02f448bed70b57da1ab3 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_64" + frameIndex: 64 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: b90b610e9c5dbd34f842a42cde9fadfb + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_65" + frameIndex: 65 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: 09302375ab6aeb94c9beb53c4214236c + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_66" + frameIndex: 66 + cellRect: + x: 89 + y: 79 + width: 288 + height: 335 + spriteId: cf92eff2415ed1a4b8e188053cd96069 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_50" + frameIndex: 50 + cellRect: + x: 0 + y: 0 + width: 385 + height: 346 + spriteId: 88d6461142abfff4584f9b60ab87a5fb + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_49" + frameIndex: 49 + cellRect: + x: 142 + y: 5 + width: 320 + height: 396 + spriteId: cfdbab315da25044b9742fc3d50d792a + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_42" + frameIndex: 42 + cellRect: + x: 112 + y: 5 + width: 256 + height: 369 + spriteId: 64c87b6e2e978c240b1e6077080cadee + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_43" + frameIndex: 43 + cellRect: + x: 112 + y: 5 + width: 256 + height: 369 + spriteId: 44272823f5f89ba47b3cbcbe86fee589 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_44" + frameIndex: 44 + cellRect: + x: 112 + y: 5 + width: 256 + height: 369 + spriteId: acc9f163373ee464296b8a4075245647 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_45" + frameIndex: 45 + cellRect: + x: 112 + y: 5 + width: 256 + height: 369 + spriteId: a5e1b982954398340826dba27a6c67f0 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_46" + frameIndex: 46 + cellRect: + x: 112 + y: 5 + width: 256 + height: 369 + spriteId: 4e2125bc1198d5243b637e36f0459e80 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_47" + frameIndex: 47 + cellRect: + x: 112 + y: 5 + width: 256 + height: 369 + spriteId: a5174888dac8e904b9d1cc0d5fac6e5c + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_48" + frameIndex: 48 + cellRect: + x: 112 + y: 5 + width: 256 + height: 369 + spriteId: ff1958764913c2c438bdc22704549fb9 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_29" + frameIndex: 29 + cellRect: + x: 153 + y: 21 + width: 249 + height: 380 + spriteId: ad79d8b0423a07345919a274dda86bc0 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_30" + frameIndex: 30 + cellRect: + x: 153 + y: 21 + width: 249 + height: 380 + spriteId: cb2787dab12d6df45aaa67666b9f7f8e + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_31" + frameIndex: 31 + cellRect: + x: 153 + y: 21 + width: 249 + height: 380 + spriteId: dac6245cb7d086c448d6b15353acaf6b + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_32" + frameIndex: 32 + cellRect: + x: 153 + y: 21 + width: 249 + height: 380 + spriteId: 8a4fe7906953f134bbfad3a62e5d4773 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_33" + frameIndex: 33 + cellRect: + x: 153 + y: 21 + width: 249 + height: 380 + spriteId: 7ed9305a08d17c147aea41e3612edb5a + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_34" + frameIndex: 34 + cellRect: + x: 153 + y: 21 + width: 249 + height: 380 + spriteId: 5a866e8375a08924892ea56975e7d56a + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_35" + frameIndex: 35 + cellRect: + x: 153 + y: 21 + width: 249 + height: 380 + spriteId: 1faed0c69c06f8649a777bac8c2a3cf1 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_36" + frameIndex: 36 + cellRect: + x: 153 + y: 21 + width: 249 + height: 380 + spriteId: b1e2cff8623f7ed49810799116453d7c + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_37" + frameIndex: 37 + cellRect: + x: 153 + y: 21 + width: 249 + height: 380 + spriteId: 030a7eb6734306e4ba0658672bca9318 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_38" + frameIndex: 38 + cellRect: + x: 153 + y: 21 + width: 249 + height: 380 + spriteId: 688e9317700552340b3f04dc8b10b4fd + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_39" + frameIndex: 39 + cellRect: + x: 153 + y: 21 + width: 249 + height: 380 + spriteId: e87b6d2cd38156040b83548e2eeb1663 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_40" + frameIndex: 40 + cellRect: + x: 153 + y: 21 + width: 249 + height: 380 + spriteId: 779addf31e6856345b43fc6441cae776 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_41" + frameIndex: 41 + cellRect: + x: 153 + y: 21 + width: 249 + height: 380 + spriteId: 55ac07d4e5cf05b4ea5c140282dbe7ac + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_14" + frameIndex: 14 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: 5e6a57edaf7baa9428ace4a8ee532815 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_15" + frameIndex: 15 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: 6524ae96fef3e1d47a0eea07efe19477 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_16" + frameIndex: 16 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: dc575b5810bf6a548935db6a03a5bae4 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_17" + frameIndex: 17 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: 1f7d9ea0b73e45045bc0107bdf384b60 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_18" + frameIndex: 18 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: 1fcbf9cdaf062744ab6aee5579c768ba + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_19" + frameIndex: 19 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: 93a1c538a250a754db9b321ddfa76845 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_20" + frameIndex: 20 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: 6ab616e0f681c8b4d861d2efdcfc309a + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_21" + frameIndex: 21 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: d73c5f7258e3f194a8a435a23918b66f + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_22" + frameIndex: 22 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: 19f1861086a28da4daad6f2d31047e67 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_23" + frameIndex: 23 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: 8386ab5d6bcfd0d4fb800139040528eb + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_24" + frameIndex: 24 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: 1efc224fb630c10468ef313b5b244d43 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_25" + frameIndex: 25 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: f5dff738dc5bee1499ffc750aa2f1fc1 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_26" + frameIndex: 26 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: 728a95f18375a644b8d962349c615f93 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_27" + frameIndex: 27 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: f0586b008f19e4c4e9d2a05da3d17912 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_28" + frameIndex: 28 + cellRect: + x: 112 + y: 5 + width: 349 + height: 395 + spriteId: 20d2e715c2b3da14ba3ee33d6ce88ca6 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_0" + frameIndex: 0 + cellRect: + x: 41 + y: 10 + width: 332 + height: 400 + spriteId: 4336edabc8ce0104cae15c6488309d5b + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_1" + frameIndex: 1 + cellRect: + x: 41 + y: 10 + width: 332 + height: 400 + spriteId: ebec265cef6079e44bf523ef46bff018 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_2" + frameIndex: 2 + cellRect: + x: 41 + y: 10 + width: 332 + height: 400 + spriteId: 4477cbbf04800e84d9b33e2434f5e7bb + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_3" + frameIndex: 3 + cellRect: + x: 41 + y: 10 + width: 332 + height: 400 + spriteId: d430a60149bc61042b80295338fef774 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_4" + frameIndex: 4 + cellRect: + x: 41 + y: 10 + width: 332 + height: 400 + spriteId: 2e18530d133c52f44b953cb7fdfc1802 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_5" + frameIndex: 5 + cellRect: + x: 41 + y: 10 + width: 332 + height: 400 + spriteId: 1042ce1c023fd5d4eb6b1d09933aad46 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_6" + frameIndex: 6 + cellRect: + x: 41 + y: 10 + width: 332 + height: 400 + spriteId: 35b6c17ff36947549b8e1c3dada8562e + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_7" + frameIndex: 7 + cellRect: + x: 41 + y: 10 + width: 332 + height: 400 + spriteId: ecc2cbad9a035cb44b4e319c2497b595 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_8" + frameIndex: 8 + cellRect: + x: 41 + y: 10 + width: 332 + height: 400 + spriteId: 428ecf4448f63cb4dafce5263caa3b99 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_9" + frameIndex: 9 + cellRect: + x: 41 + y: 10 + width: 332 + height: 400 + spriteId: c3524d26d54029440ba6266db9a7e469 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_10" + frameIndex: 10 + cellRect: + x: 41 + y: 10 + width: 332 + height: 400 + spriteId: a41b32f5fc658aa4aa549b02862afe19 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_11" + frameIndex: 11 + cellRect: + x: 41 + y: 10 + width: 332 + height: 400 + spriteId: 3519a0a01dceee049b2dfe58fd7f2a37 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_12" + frameIndex: 12 + cellRect: + x: 41 + y: 10 + width: 332 + height: 400 + spriteId: d70e7312d0ba0a54c91d1a8351053510 + - name: "\u706B\u5C71\u50CF\u7D20\u7248_Frame_13" + frameIndex: 13 + cellRect: + x: 41 + y: 10 + width: 332 + height: 400 + spriteId: 673d2d5d6ec3283458e7f419797803eb + linkedCells: [] + parentIndex: -1 + platformSettings: [] + secondarySpriteTextures: [] + spritePackingTag: + canvasSize: {x: 550, y: 414} diff --git a/Assets/GameContent/Huoshan/Actor/火山像素版.json b/Assets/GameContent/Huoshan/Actor/火山像素版.json index 2175119b2..106a251e1 100644 --- a/Assets/GameContent/Huoshan/Actor/火山像素版.json +++ b/Assets/GameContent/Huoshan/Actor/火山像素版.json @@ -1,419 +1,571 @@ { "frames": { "火山像素版 0.aseprite": { - "frame": { "x": 0, "y": 0, "w": 462, "h": 410 }, + "frame": { "x": 0, "y": 0, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, - "duration": 100 + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 }, "火山像素版 1.aseprite": { - "frame": { "x": 462, "y": 0, "w": 462, "h": 410 }, + "frame": { "x": 550, "y": 0, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 2.aseprite": { - "frame": { "x": 924, "y": 0, "w": 462, "h": 410 }, + "frame": { "x": 1100, "y": 0, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 3.aseprite": { - "frame": { "x": 1386, "y": 0, "w": 462, "h": 410 }, + "frame": { "x": 1650, "y": 0, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 4.aseprite": { - "frame": { "x": 1848, "y": 0, "w": 462, "h": 410 }, + "frame": { "x": 2200, "y": 0, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 5.aseprite": { - "frame": { "x": 2310, "y": 0, "w": 462, "h": 410 }, + "frame": { "x": 2750, "y": 0, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 6.aseprite": { - "frame": { "x": 2772, "y": 0, "w": 462, "h": 410 }, + "frame": { "x": 3300, "y": 0, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 7.aseprite": { - "frame": { "x": 3234, "y": 0, "w": 462, "h": 410 }, + "frame": { "x": 3850, "y": 0, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 8.aseprite": { - "frame": { "x": 0, "y": 410, "w": 462, "h": 410 }, + "frame": { "x": 4400, "y": 0, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, - "duration": 300 + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 100 }, "火山像素版 9.aseprite": { - "frame": { "x": 462, "y": 410, "w": 462, "h": 410 }, + "frame": { "x": 4950, "y": 0, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 10.aseprite": { - "frame": { "x": 924, "y": 410, "w": 462, "h": 410 }, + "frame": { "x": 5500, "y": 0, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 11.aseprite": { - "frame": { "x": 1386, "y": 410, "w": 462, "h": 410 }, + "frame": { "x": 6050, "y": 0, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 12.aseprite": { - "frame": { "x": 1848, "y": 410, "w": 462, "h": 410 }, + "frame": { "x": 6600, "y": 0, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 13.aseprite": { - "frame": { "x": 2310, "y": 410, "w": 462, "h": 410 }, + "frame": { "x": 7150, "y": 0, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 14.aseprite": { - "frame": { "x": 2772, "y": 410, "w": 462, "h": 410 }, + "frame": { "x": 0, "y": 414, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, - "duration": 100 + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 }, "火山像素版 15.aseprite": { - "frame": { "x": 3234, "y": 410, "w": 462, "h": 410 }, + "frame": { "x": 550, "y": 414, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 16.aseprite": { - "frame": { "x": 0, "y": 820, "w": 462, "h": 410 }, + "frame": { "x": 1100, "y": 414, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 17.aseprite": { - "frame": { "x": 462, "y": 820, "w": 462, "h": 410 }, + "frame": { "x": 1650, "y": 414, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 18.aseprite": { - "frame": { "x": 924, "y": 820, "w": 462, "h": 410 }, + "frame": { "x": 2200, "y": 414, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 19.aseprite": { - "frame": { "x": 1386, "y": 820, "w": 462, "h": 410 }, + "frame": { "x": 2750, "y": 414, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 20.aseprite": { - "frame": { "x": 1848, "y": 820, "w": 462, "h": 410 }, + "frame": { "x": 3300, "y": 414, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 21.aseprite": { - "frame": { "x": 2310, "y": 820, "w": 462, "h": 410 }, + "frame": { "x": 3850, "y": 414, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 22.aseprite": { - "frame": { "x": 2772, "y": 820, "w": 462, "h": 410 }, + "frame": { "x": 4400, "y": 414, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 23.aseprite": { - "frame": { "x": 3234, "y": 820, "w": 462, "h": 410 }, + "frame": { "x": 4950, "y": 414, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, - "duration": 300 + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 100 }, "火山像素版 24.aseprite": { - "frame": { "x": 0, "y": 1230, "w": 462, "h": 410 }, + "frame": { "x": 5500, "y": 414, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 25.aseprite": { - "frame": { "x": 462, "y": 1230, "w": 462, "h": 410 }, + "frame": { "x": 6050, "y": 414, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 26.aseprite": { - "frame": { "x": 924, "y": 1230, "w": 462, "h": 410 }, + "frame": { "x": 6600, "y": 414, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 27.aseprite": { - "frame": { "x": 1386, "y": 1230, "w": 462, "h": 410 }, + "frame": { "x": 7150, "y": 414, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 28.aseprite": { - "frame": { "x": 1848, "y": 1230, "w": 462, "h": 410 }, + "frame": { "x": 0, "y": 828, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 29.aseprite": { - "frame": { "x": 2310, "y": 1230, "w": 462, "h": 410 }, + "frame": { "x": 550, "y": 828, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, - "duration": 100 + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 }, "火山像素版 30.aseprite": { - "frame": { "x": 2772, "y": 1230, "w": 462, "h": 410 }, + "frame": { "x": 1100, "y": 828, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 31.aseprite": { - "frame": { "x": 3234, "y": 1230, "w": 462, "h": 410 }, + "frame": { "x": 1650, "y": 828, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 32.aseprite": { - "frame": { "x": 0, "y": 1640, "w": 462, "h": 410 }, + "frame": { "x": 2200, "y": 828, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 33.aseprite": { - "frame": { "x": 462, "y": 1640, "w": 462, "h": 410 }, + "frame": { "x": 2750, "y": 828, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 34.aseprite": { - "frame": { "x": 924, "y": 1640, "w": 462, "h": 410 }, + "frame": { "x": 3300, "y": 828, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 35.aseprite": { - "frame": { "x": 1386, "y": 1640, "w": 462, "h": 410 }, + "frame": { "x": 3850, "y": 828, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 36.aseprite": { - "frame": { "x": 1848, "y": 1640, "w": 462, "h": 410 }, + "frame": { "x": 4400, "y": 828, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, - "duration": 300 + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 100 }, "火山像素版 37.aseprite": { - "frame": { "x": 2310, "y": 1640, "w": 462, "h": 410 }, + "frame": { "x": 4950, "y": 828, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 38.aseprite": { - "frame": { "x": 2772, "y": 1640, "w": 462, "h": 410 }, + "frame": { "x": 5500, "y": 828, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 39.aseprite": { - "frame": { "x": 3234, "y": 1640, "w": 462, "h": 410 }, + "frame": { "x": 6050, "y": 828, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 40.aseprite": { - "frame": { "x": 0, "y": 2050, "w": 462, "h": 410 }, + "frame": { "x": 6600, "y": 828, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 41.aseprite": { - "frame": { "x": 462, "y": 2050, "w": 462, "h": 410 }, + "frame": { "x": 7150, "y": 828, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 100 }, "火山像素版 42.aseprite": { - "frame": { "x": 924, "y": 2050, "w": 462, "h": 410 }, + "frame": { "x": 0, "y": 1242, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, - "duration": 100 + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 }, "火山像素版 43.aseprite": { - "frame": { "x": 1386, "y": 2050, "w": 462, "h": 410 }, + "frame": { "x": 550, "y": 1242, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 44.aseprite": { - "frame": { "x": 1848, "y": 2050, "w": 462, "h": 410 }, + "frame": { "x": 1100, "y": 1242, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 45.aseprite": { - "frame": { "x": 2310, "y": 2050, "w": 462, "h": 410 }, + "frame": { "x": 1650, "y": 1242, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 46.aseprite": { - "frame": { "x": 2772, "y": 2050, "w": 462, "h": 410 }, + "frame": { "x": 2200, "y": 1242, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 47.aseprite": { - "frame": { "x": 3234, "y": 2050, "w": 462, "h": 410 }, + "frame": { "x": 2750, "y": 1242, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 48.aseprite": { - "frame": { "x": 0, "y": 2460, "w": 462, "h": 410 }, + "frame": { "x": 3300, "y": 1242, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 49.aseprite": { - "frame": { "x": 462, "y": 2460, "w": 462, "h": 410 }, + "frame": { "x": 3850, "y": 1242, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 50.aseprite": { - "frame": { "x": 924, "y": 2460, "w": 462, "h": 410 }, + "frame": { "x": 4400, "y": 1242, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 }, "火山像素版 51.aseprite": { - "frame": { "x": 1386, "y": 2460, "w": 462, "h": 410 }, + "frame": { "x": 4950, "y": 1242, "w": 550, "h": 414 }, "rotated": false, "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 462, "h": 410 }, - "sourceSize": { "w": 462, "h": 410 }, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, "duration": 300 + }, + "火山像素版 52.aseprite": { + "frame": { "x": 5500, "y": 1242, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 + }, + "火山像素版 53.aseprite": { + "frame": { "x": 6050, "y": 1242, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 + }, + "火山像素版 54.aseprite": { + "frame": { "x": 6600, "y": 1242, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 + }, + "火山像素版 55.aseprite": { + "frame": { "x": 7150, "y": 1242, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 + }, + "火山像素版 56.aseprite": { + "frame": { "x": 0, "y": 1656, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 + }, + "火山像素版 57.aseprite": { + "frame": { "x": 550, "y": 1656, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 + }, + "火山像素版 58.aseprite": { + "frame": { "x": 1100, "y": 1656, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 + }, + "火山像素版 59.aseprite": { + "frame": { "x": 1650, "y": 1656, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 + }, + "火山像素版 60.aseprite": { + "frame": { "x": 2200, "y": 1656, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 + }, + "火山像素版 61.aseprite": { + "frame": { "x": 2750, "y": 1656, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 100 + }, + "火山像素版 62.aseprite": { + "frame": { "x": 3300, "y": 1656, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 100 + }, + "火山像素版 63.aseprite": { + "frame": { "x": 3850, "y": 1656, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 100 + }, + "火山像素版 64.aseprite": { + "frame": { "x": 4400, "y": 1656, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 100 + }, + "火山像素版 65.aseprite": { + "frame": { "x": 4950, "y": 1656, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 100 + }, + "火山像素版 66.aseprite": { + "frame": { "x": 5500, "y": 1656, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 100 + }, + "火山像素版 67.aseprite": { + "frame": { "x": 6050, "y": 1656, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 200 + }, + "火山像素版 68.aseprite": { + "frame": { "x": 6600, "y": 1656, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 + }, + "火山像素版 69.aseprite": { + "frame": { "x": 7150, "y": 1656, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 300 + }, + "火山像素版 70.aseprite": { + "frame": { "x": 0, "y": 2070, "w": 550, "h": 414 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 550, "h": 414 }, + "sourceSize": { "w": 550, "h": 414 }, + "duration": 200 } }, "meta": { @@ -421,24 +573,31 @@ "version": "1.3.17.2-x64", "image": "火山像素版.png", "format": "RGBA8888", - "size": { "w": 4096, "h": 2870 }, + "size": { "w": 8192, "h": 2484 }, "scale": "1", "frameTags": [ - { "name": "伸手表情idle", "from": 1, "to": 7, "direction": "forward", "color": "#000000ff" }, - { "name": "伸手 石化表情", "from": 8, "to": 8, "direction": "forward", "color": "#000000ff" }, - { "name": "伸手切屏特效 ", "from": 9, "to": 14, "direction": "forward", "color": "#000000ff" }, - { "name": "扣头表情idle", "from": 15, "to": 21, "direction": "forward", "color": "#000000ff" }, - { "name": "扣头 ?", "from": 22, "to": 22, "direction": "forward", "color": "#000000ff" }, - { "name": "扣头灯泡", "from": 23, "to": 23, "direction": "forward", "color": "#000000ff" }, - { "name": "扣头切屏特效", "from": 24, "to": 29, "direction": "forward", "color": "#000000ff" }, - { "name": "对手指表情idle", "from": 30, "to": 36, "direction": "forward", "color": "#000000ff" }, - { "name": "对手指切屏特效", "from": 37, "to": 42, "direction": "forward", "color": "#000000ff" }, - { "name": "捂头表情idle", "from": 43, "to": 49, "direction": "forward", "color": "#000000ff" }, - { "name": "拿住帽子", "from": 50, "to": 50, "direction": "forward", "color": "#000000ff" }, - { "name": "摘帽", "from": 51, "to": 51, "direction": "forward", "color": "#000000ff" } + { "name": "伸手表情idle", "from": 0, "to": 6, "direction": "forward", "color": "#000000ff" }, + { "name": "伸手石化表情", "from": 7, "to": 7, "direction": "forward", "color": "#000000ff" }, + { "name": "伸手切屏特效 ", "from": 8, "to": 13, "direction": "forward", "color": "#000000ff" }, + { "name": "扣头表情idle", "from": 14, "to": 20, "direction": "forward", "color": "#000000ff" }, + { "name": "扣头 ?", "from": 21, "to": 21, "direction": "forward", "color": "#000000ff" }, + { "name": "扣头灯泡", "from": 22, "to": 22, "direction": "forward", "color": "#000000ff" }, + { "name": "扣头切屏特效", "from": 23, "to": 28, "direction": "forward", "color": "#000000ff" }, + { "name": "对手指表情idle", "from": 29, "to": 35, "direction": "forward", "color": "#000000ff" }, + { "name": "对手指切屏特效", "from": 36, "to": 41, "direction": "forward", "color": "#000000ff" }, + { "name": "捂头表情idle", "from": 42, "to": 48, "direction": "forward", "color": "#000000ff" }, + { "name": "拿住帽子", "from": 49, "to": 49, "direction": "forward", "color": "#000000ff" }, + { "name": "摘帽", "from": 50, "to": 50, "direction": "forward", "color": "#000000ff" }, + { "name": "火山立表情idle", "from": 51, "to": 57, "direction": "forward", "color": "#000000ff" }, + { "name": "火山立爱心", "from": 58, "to": 59, "direction": "forward", "color": "#000000ff" }, + { "name": "火山立帽子", "from": 60, "to": 60, "direction": "forward", "color": "#000000ff" }, + { "name": "火山立切屏特效 ", "from": 61, "to": 66, "direction": "forward", "color": "#000000ff" }, + { "name": "指医生idle", "from": 67, "to": 70, "direction": "forward", "color": "#000000ff" } ], "layers": [ { "name": "火山动作" }, + { "name": "指医生", "group": "火山动作", "opacity": 255, "blendMode": "normal" }, + { "name": "火山立", "group": "火山动作", "opacity": 255, "blendMode": "normal" }, { "name": "动作 摘帽2", "group": "火山动作", "opacity": 255, "blendMode": "normal" }, { "name": "动作 摘帽1", "group": "火山动作", "opacity": 255, "blendMode": "normal" }, { "name": "动作 捂头", "group": "火山动作", "opacity": 255, "blendMode": "normal", "color": "#a5a5a7ff" }, @@ -446,6 +605,8 @@ { "name": "动作 扣头", "group": "火山动作", "opacity": 255, "blendMode": "normal", "color": "#6acd5bff" }, { "name": "动作 伸手", "group": "火山动作", "opacity": 255, "blendMode": "normal", "color": "#fe5b59ff" }, { "name": "火山表情" }, + { "name": "表情 指医生", "group": "火山表情" }, + { "name": "星星特效", "group": "表情 指医生", "opacity": 255, "blendMode": "normal" }, { "name": "表情 捂头", "group": "火山表情", "color": "#a5a5a7ff" }, { "name": "idle", "group": "表情 捂头", "opacity": 255, "blendMode": "normal", "color": "#a5a5a7ff" }, { "name": "表情 对手指", "group": "火山表情", "color": "#57b9f2ff" }, @@ -456,10 +617,13 @@ { "name": "?", "group": "表情 扣头+摘帽1", "opacity": 255, "blendMode": "normal", "color": "#6acd5bff" }, { "name": "idle", "group": "表情 扣头+摘帽1", "opacity": 255, "blendMode": "normal", "color": "#6acd5bff" }, { "name": "切屏特效 扣头", "group": "表情 扣头+摘帽1", "opacity": 255, "blendMode": "normal", "color": "#6acd5bff" }, - { "name": "表情 伸手", "group": "火山表情", "color": "#fe5b59ff" }, - { "name": "切屏特效 伸手", "group": "表情 伸手", "opacity": 255, "blendMode": "normal", "color": "#fe5b59ff" }, - { "name": "表:石化", "group": "表情 伸手", "opacity": 255, "blendMode": "normal", "color": "#fe5b59ff" }, - { "name": "idle", "group": "表情 伸手", "opacity": 255, "blendMode": "normal", "color": "#fe5b59ff" } + { "name": "表情 伸手 火山立", "group": "火山表情", "color": "#fe5b59ff" }, + { "name": "帽子", "group": "表情 伸手 火山立", "opacity": 255, "blendMode": "normal", "color": "#fe5b59ff" }, + { "name": "爱心", "group": "表情 伸手 火山立", "opacity": 255, "blendMode": "normal", "color": "#fe5b59ff" }, + { "name": "切屏特效 伸手", "group": "表情 伸手 火山立", "opacity": 255, "blendMode": "normal", "color": "#fe5b59ff" }, + { "name": "表:石化", "group": "表情 伸手 火山立", "opacity": 255, "blendMode": "normal", "color": "#fe5b59ff" }, + { "name": "idle", "group": "表情 伸手 火山立", "opacity": 255, "blendMode": "normal", "color": "#fe5b59ff" }, + { "name": "火山脸部遮罩" } ], "slices": [ ] diff --git a/Assets/GameContent/Huoshan/Actor/火山像素版.png b/Assets/GameContent/Huoshan/Actor/火山像素版.png index fbc1186f2..33bbe9c01 100644 --- a/Assets/GameContent/Huoshan/Actor/火山像素版.png +++ b/Assets/GameContent/Huoshan/Actor/火山像素版.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e03056998aa107f25e571e3018d7a0e9bea2b3abcc49b882051f723232fc0741 -size 437469 +oid sha256:893f3d9e7725d9f112cfe3613ba963151df65f98f575bc4b857f9d1cf47b0d72 +size 548465 diff --git a/Assets/GameContent/Huoshan/Actor/火山像素版.png.meta b/Assets/GameContent/Huoshan/Actor/火山像素版.png.meta index a467f8835..3600078fa 100644 --- a/Assets/GameContent/Huoshan/Actor/火山像素版.png.meta +++ b/Assets/GameContent/Huoshan/Actor/火山像素版.png.meta @@ -69,7 +69,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 4096 + maxTextureSize: 8192 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 0 @@ -153,9 +153,9 @@ TextureImporter: rect: serializedVersion: 2 x: 0 - y: 2460 - width: 462 - height: 410 + y: 2070 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -163,7 +163,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 55aa504de6ba24d4687cb4dfb3561096 + spriteID: b78f485f08311f54a8a70ea6c41ebb77 internalID: -4164942248284793206 vertices: [] indices: @@ -173,10 +173,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 1.aseprite" rect: serializedVersion: 2 - x: 462 - y: 2460 - width: 462 - height: 410 + x: 550 + y: 2070 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -184,7 +184,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: bc27d9e4aea8417499229b050519aca5 + spriteID: 819eaf73ee9b0974d8671d3fc72ed8e9 internalID: -1677818779029218552 vertices: [] indices: @@ -194,10 +194,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 2.aseprite" rect: serializedVersion: 2 - x: 924 - y: 2460 - width: 462 - height: 410 + x: 1100 + y: 2070 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -205,7 +205,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: ae21a0d6db92ddf4e9d50471dcefc816 + spriteID: 25b232d692e8c0b4c92ba778ca57b582 internalID: 2228560797916198417 vertices: [] indices: @@ -215,10 +215,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 3.aseprite" rect: serializedVersion: 2 - x: 1386 - y: 2460 - width: 462 - height: 410 + x: 1650 + y: 2070 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -226,7 +226,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 61a5f438605e9774eb53aa1bf06172ff + spriteID: 58b926da67e8b0340ab725fea1ecffd0 internalID: 3692674704072360000 vertices: [] indices: @@ -236,10 +236,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 4.aseprite" rect: serializedVersion: 2 - x: 1848 - y: 2460 - width: 462 - height: 410 + x: 2200 + y: 2070 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -247,7 +247,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 087ab56318016694086e4f790b465fa7 + spriteID: c57a491c0965ca94796bdd2b1db420c5 internalID: 1322747803227566868 vertices: [] indices: @@ -257,10 +257,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 5.aseprite" rect: serializedVersion: 2 - x: 2310 - y: 2460 - width: 462 - height: 410 + x: 2750 + y: 2070 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -268,7 +268,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 803c9bb015884f04c8569c0a30c4e50f + spriteID: 8e6891fac4ce6ef47ad30f0ae27fcae2 internalID: 6544607226600977317 vertices: [] indices: @@ -278,10 +278,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 6.aseprite" rect: serializedVersion: 2 - x: 2772 - y: 2460 - width: 462 - height: 410 + x: 3300 + y: 2070 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -289,7 +289,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 5267c5a809b0ba6469fb7352127a7f4e + spriteID: b0b35500102b4d1439e87bd6dfb58700 internalID: -2184225217804312755 vertices: [] indices: @@ -299,10 +299,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 7.aseprite" rect: serializedVersion: 2 - x: 3234 - y: 2460 - width: 462 - height: 410 + x: 3850 + y: 2070 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -310,7 +310,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 7c167e6f2bdc8254db796a95b72e9ad5 + spriteID: 385c597af9eeda64caeb998b5973f0a4 internalID: 7141184682861996702 vertices: [] indices: @@ -320,10 +320,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 8.aseprite" rect: serializedVersion: 2 - x: 0 - y: 2050 - width: 462 - height: 410 + x: 4400 + y: 2070 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -331,7 +331,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 7c3993da032b7db4aa50f4c1771396e6 + spriteID: c838dd95390eaa34fbe5e7c6c9040d30 internalID: 3023878692377788431 vertices: [] indices: @@ -341,10 +341,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 9.aseprite" rect: serializedVersion: 2 - x: 462 - y: 2050 - width: 462 - height: 410 + x: 4950 + y: 2070 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -352,7 +352,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 9f39c9202efb47946bd3ec2bfa839ed3 + spriteID: 0397489d4824e0348ab2f77a9ab96f3e internalID: 328454971127517396 vertices: [] indices: @@ -362,10 +362,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 10.aseprite" rect: serializedVersion: 2 - x: 924 - y: 2050 - width: 462 - height: 410 + x: 5500 + y: 2070 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -373,7 +373,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 96ed5527a50dca64cb316198a26e9ad9 + spriteID: 2855e8f9e727c9e4bbce53452fd1c5c7 internalID: -5721950062080919410 vertices: [] indices: @@ -383,10 +383,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 11.aseprite" rect: serializedVersion: 2 - x: 1386 - y: 2050 - width: 462 - height: 410 + x: 6050 + y: 2070 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -394,7 +394,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 6b0c0640c9d2736449d62f6903145fba + spriteID: 055f83ba892432848a80363920b126a9 internalID: -1975533900375426686 vertices: [] indices: @@ -404,10 +404,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 12.aseprite" rect: serializedVersion: 2 - x: 1848 - y: 2050 - width: 462 - height: 410 + x: 6600 + y: 2070 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -415,7 +415,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 44bbb875a1bcc744c88d350e497effc5 + spriteID: 8e78eeebaa4fb1146b0dc7738937bf8b internalID: -6980694543551506686 vertices: [] indices: @@ -425,10 +425,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 13.aseprite" rect: serializedVersion: 2 - x: 2310 - y: 2050 - width: 462 - height: 410 + x: 7150 + y: 2070 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -436,7 +436,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: b732f22282bf9a24189c0cd8345d66f6 + spriteID: bc85a40ced45f6142b040dca945ad16d internalID: -9065355728817191262 vertices: [] indices: @@ -446,10 +446,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 14.aseprite" rect: serializedVersion: 2 - x: 2772 - y: 2050 - width: 462 - height: 410 + x: 0 + y: 1656 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -457,7 +457,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: bb1cb65e484c05c4a93e9a98f2af61e1 + spriteID: 0ec9edbcf0e70514b840dd6783d6b4b5 internalID: -280250252267852960 vertices: [] indices: @@ -467,10 +467,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 15.aseprite" rect: serializedVersion: 2 - x: 3234 - y: 2050 - width: 462 - height: 410 + x: 550 + y: 1656 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -478,7 +478,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: ee1540dab0343b242bfdeb47c3c0718b + spriteID: cdc1aec090a4855478a6a9ae572128e0 internalID: 4436847421114479055 vertices: [] indices: @@ -488,10 +488,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 16.aseprite" rect: serializedVersion: 2 - x: 0 - y: 1640 - width: 462 - height: 410 + x: 1100 + y: 1656 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -499,7 +499,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: e280dea97184e0f41ba19a4dc06c19de + spriteID: eea668e7f51070b4888267dd3c7e85d4 internalID: 5667594085435701249 vertices: [] indices: @@ -509,10 +509,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 17.aseprite" rect: serializedVersion: 2 - x: 462 - y: 1640 - width: 462 - height: 410 + x: 1650 + y: 1656 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -520,7 +520,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 43e0f688d623b7a42bbc5063a1645662 + spriteID: e4edc30ad8636fd49aeb9d2fa7effe81 internalID: -5721902929574716727 vertices: [] indices: @@ -530,10 +530,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 18.aseprite" rect: serializedVersion: 2 - x: 924 - y: 1640 - width: 462 - height: 410 + x: 2200 + y: 1656 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -541,7 +541,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 0f99fdf1ff1dbfc42a165b9fa9c36dac + spriteID: 2d275780ef058ac44a11213a43948186 internalID: 5343867589828250029 vertices: [] indices: @@ -551,10 +551,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 19.aseprite" rect: serializedVersion: 2 - x: 1386 - y: 1640 - width: 462 - height: 410 + x: 2750 + y: 1656 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -562,7 +562,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: ae2f1e20e47ad874da12a24970d2098f + spriteID: a5494cb5a80a8424382c5f7101f8d3ba internalID: -5771093403194421087 vertices: [] indices: @@ -572,10 +572,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 20.aseprite" rect: serializedVersion: 2 - x: 1848 - y: 1640 - width: 462 - height: 410 + x: 3300 + y: 1656 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -583,7 +583,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 2b2aa885cae66d747a634c5b7a48f57b + spriteID: e074c3602a930ca4eaf305ff6aeb3cc8 internalID: -7267050587848991437 vertices: [] indices: @@ -593,10 +593,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 21.aseprite" rect: serializedVersion: 2 - x: 2310 - y: 1640 - width: 462 - height: 410 + x: 3850 + y: 1656 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -604,7 +604,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: bf1ce4ff021c85248a35d8c5d7727838 + spriteID: 217a4ffdc80bea64997e07749a87ccb4 internalID: -3742796876328757744 vertices: [] indices: @@ -614,10 +614,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 22.aseprite" rect: serializedVersion: 2 - x: 2772 - y: 1640 - width: 462 - height: 410 + x: 4400 + y: 1656 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -625,7 +625,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 11b08e0de0a44ed469565de1c37bdb10 + spriteID: 464d5cf776f52cf41a449c52831b603f internalID: -1597267871085758117 vertices: [] indices: @@ -635,10 +635,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 23.aseprite" rect: serializedVersion: 2 - x: 3234 - y: 1640 - width: 462 - height: 410 + x: 4950 + y: 1656 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -646,7 +646,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: aa25dbea34248454d8f5f0b7c1f5ecc9 + spriteID: 54b5bb49e7b4edf47b1ea6b1fcd9a087 internalID: 6147323577121316844 vertices: [] indices: @@ -656,10 +656,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 24.aseprite" rect: serializedVersion: 2 - x: 0 - y: 1230 - width: 462 - height: 410 + x: 5500 + y: 1656 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -667,7 +667,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 1fc17f818a1edcb4ba8f41c16c367e16 + spriteID: c6f1790330608bb4db6fc41f08424c3d internalID: 8112637510959776406 vertices: [] indices: @@ -677,10 +677,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 25.aseprite" rect: serializedVersion: 2 - x: 462 - y: 1230 - width: 462 - height: 410 + x: 6050 + y: 1656 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -688,7 +688,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 3912f4a3c9614be48a4c3564c1e0e68b + spriteID: 532df8e0e2fb1eb4dbf00747d646f5d6 internalID: 1161578261099833026 vertices: [] indices: @@ -698,10 +698,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 26.aseprite" rect: serializedVersion: 2 - x: 924 - y: 1230 - width: 462 - height: 410 + x: 6600 + y: 1656 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -709,7 +709,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 3de32357234f45740b71bc197c05a1c7 + spriteID: 87788b4edef696644b6aa67e3fb06e05 internalID: 2815972358767843364 vertices: [] indices: @@ -719,10 +719,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 27.aseprite" rect: serializedVersion: 2 - x: 1386 - y: 1230 - width: 462 - height: 410 + x: 7150 + y: 1656 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -730,7 +730,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: e6f6343132da8c4439c3051a4c9ea7a7 + spriteID: 25b37d2e2283b0e478dd5ea566952484 internalID: 349013521611419999 vertices: [] indices: @@ -740,10 +740,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 28.aseprite" rect: serializedVersion: 2 - x: 1848 - y: 1230 - width: 462 - height: 410 + x: 0 + y: 1242 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -751,7 +751,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 5efd0d5f9c54fa149bdf83167349136d + spriteID: d1d62ce972b65df4791369507596a8e6 internalID: -4726918733811212227 vertices: [] indices: @@ -761,10 +761,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 29.aseprite" rect: serializedVersion: 2 - x: 2310 - y: 1230 - width: 462 - height: 410 + x: 550 + y: 1242 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -772,7 +772,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 0baa1b36e6284b240bb34392532d363f + spriteID: ccba80cece9de234dbf06ddf279deb99 internalID: -7420326846939562944 vertices: [] indices: @@ -782,10 +782,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 30.aseprite" rect: serializedVersion: 2 - x: 2772 - y: 1230 - width: 462 - height: 410 + x: 1100 + y: 1242 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -793,7 +793,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 062d013ba79ec1c41b8501c5af12ae4c + spriteID: 67e071b66dc92394e85c8efc48066bfb internalID: 6693685528016350094 vertices: [] indices: @@ -803,10 +803,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 31.aseprite" rect: serializedVersion: 2 - x: 3234 - y: 1230 - width: 462 - height: 410 + x: 1650 + y: 1242 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -814,7 +814,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 21ff93299c31c344a88aa28f958bb2e2 + spriteID: a35b0a6e637110f44a2e4aab133be718 internalID: -6212073585795218389 vertices: [] indices: @@ -824,10 +824,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 32.aseprite" rect: serializedVersion: 2 - x: 0 - y: 820 - width: 462 - height: 410 + x: 2200 + y: 1242 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -835,7 +835,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 1b41b8f2ab547e544929d908ab5ba7e1 + spriteID: 23a68b4ba4bf8e84380a644016f388a8 internalID: -5617383836367654468 vertices: [] indices: @@ -845,10 +845,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 33.aseprite" rect: serializedVersion: 2 - x: 462 - y: 820 - width: 462 - height: 410 + x: 2750 + y: 1242 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -856,7 +856,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: e0df3a67bb64e3946ac3d43feea3f966 + spriteID: 759d793abc34d984ea7276e2c167b25f internalID: -6186328820189021415 vertices: [] indices: @@ -866,10 +866,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 34.aseprite" rect: serializedVersion: 2 - x: 924 - y: 820 - width: 462 - height: 410 + x: 3300 + y: 1242 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -877,7 +877,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: c5e6553c8fe53814ba9ad9a3ae396f03 + spriteID: 00b5b6e970458e245aa55d16d7e3395c internalID: -2427306421867198794 vertices: [] indices: @@ -887,10 +887,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 35.aseprite" rect: serializedVersion: 2 - x: 1386 - y: 820 - width: 462 - height: 410 + x: 3850 + y: 1242 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -898,7 +898,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 1c08195c5de57f04092918fdd2cd1a7f + spriteID: 7da0b67adaedb9b41a33fdc52e565b1c internalID: -763069158220295323 vertices: [] indices: @@ -908,10 +908,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 36.aseprite" rect: serializedVersion: 2 - x: 1848 - y: 820 - width: 462 - height: 410 + x: 4400 + y: 1242 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -919,7 +919,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 73ead5843d5ce764c8c997c98aa600cb + spriteID: a51d0f712bf35c548b2838d0df227638 internalID: 8063529297442791384 vertices: [] indices: @@ -929,10 +929,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 37.aseprite" rect: serializedVersion: 2 - x: 2310 - y: 820 - width: 462 - height: 410 + x: 4950 + y: 1242 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -940,7 +940,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: c04aab86194c79f47b182eab261f84de + spriteID: 2d412ab83a0c8aa49beebbc300c196d4 internalID: 5032543470190648888 vertices: [] indices: @@ -950,10 +950,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 38.aseprite" rect: serializedVersion: 2 - x: 2772 - y: 820 - width: 462 - height: 410 + x: 5500 + y: 1242 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -961,7 +961,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 3f692eb907aeafe42bb4bc8b9cdf77f4 + spriteID: 268ccac8177eb5e43a81909f8c249e17 internalID: -8891496989772103086 vertices: [] indices: @@ -971,10 +971,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 39.aseprite" rect: serializedVersion: 2 - x: 3234 - y: 820 - width: 462 - height: 410 + x: 6050 + y: 1242 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -982,7 +982,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 00ab76679a40008459d9a485b0a2d5dc + spriteID: 57cc36234e8526840b32013ea5e73cda internalID: 8008349618346729921 vertices: [] indices: @@ -992,10 +992,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 40.aseprite" rect: serializedVersion: 2 - x: 0 - y: 410 - width: 462 - height: 410 + x: 6600 + y: 1242 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -1003,7 +1003,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: bc7f678e08d07e54fa7ce14d1d253897 + spriteID: e92fc7800857f964a949269ba06e0310 internalID: 957245915571844022 vertices: [] indices: @@ -1013,10 +1013,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 41.aseprite" rect: serializedVersion: 2 - x: 462 - y: 410 - width: 462 - height: 410 + x: 7150 + y: 1242 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -1024,7 +1024,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 0afa517486ebf9b42b7bff0092e422fe + spriteID: 8d63a712cff15df4a910e7b3428dba44 internalID: -9126885696863182548 vertices: [] indices: @@ -1034,10 +1034,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 42.aseprite" rect: serializedVersion: 2 - x: 924 - y: 410 - width: 462 - height: 410 + x: 0 + y: 828 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -1045,7 +1045,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 85c179edd72eac94e9c7e104da4bb412 + spriteID: f1e1ac4353184794b9b6c243c537d73d internalID: 7853721251838497650 vertices: [] indices: @@ -1055,10 +1055,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 43.aseprite" rect: serializedVersion: 2 - x: 1386 - y: 410 - width: 462 - height: 410 + x: 550 + y: 828 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -1066,7 +1066,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: cf960de6fb5fac3439f3301dc33b307a + spriteID: b59bdefe8e7afa44e980a213483d4033 internalID: 1773845448817315849 vertices: [] indices: @@ -1076,10 +1076,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 44.aseprite" rect: serializedVersion: 2 - x: 1848 - y: 410 - width: 462 - height: 410 + x: 1100 + y: 828 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -1087,7 +1087,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 7896d821d27afe0409787bf9db81471f + spriteID: 7c42313f36c24904d85b42d954bb93d9 internalID: -3195166301208396845 vertices: [] indices: @@ -1097,10 +1097,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 45.aseprite" rect: serializedVersion: 2 - x: 2310 - y: 410 - width: 462 - height: 410 + x: 1650 + y: 828 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -1108,7 +1108,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 5cff77dcac556d94bb50137523a7ed55 + spriteID: 171f8add19cecac499fb83854547b92d internalID: 1368360222237187272 vertices: [] indices: @@ -1118,10 +1118,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 46.aseprite" rect: serializedVersion: 2 - x: 2772 - y: 410 - width: 462 - height: 410 + x: 2200 + y: 828 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -1129,7 +1129,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 925441a57e68c2848a488469a6e3dc1c + spriteID: 7df87900bf8ddae4799822943317bf27 internalID: 7865228568559759454 vertices: [] indices: @@ -1139,10 +1139,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 47.aseprite" rect: serializedVersion: 2 - x: 3234 - y: 410 - width: 462 - height: 410 + x: 2750 + y: 828 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -1150,7 +1150,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 551ab2215fdeb694086d214f4bcfcceb + spriteID: 298630e4c874b4349b6ad2a174ebb255 internalID: 2981399914509237564 vertices: [] indices: @@ -1160,10 +1160,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 48.aseprite" rect: serializedVersion: 2 - x: 0 - y: 0 - width: 462 - height: 410 + x: 3300 + y: 828 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -1171,7 +1171,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: d20c1eb035bc98949ad41a1400cd6f22 + spriteID: 1920145954da1d34d950dd3d380fc775 internalID: 7551530765008677039 vertices: [] indices: @@ -1181,10 +1181,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 49.aseprite" rect: serializedVersion: 2 - x: 462 - y: 0 - width: 462 - height: 410 + x: 3850 + y: 828 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -1192,7 +1192,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 9bf7aa978b27b954195c07a9faf9c129 + spriteID: 206ccea91d2672c4d869aa41fe6f1ab1 internalID: 711362045575723135 vertices: [] indices: @@ -1202,10 +1202,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 50.aseprite" rect: serializedVersion: 2 - x: 924 - y: 0 - width: 462 - height: 410 + x: 4400 + y: 828 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -1213,7 +1213,7 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 33080934adfd1d841b1396dbb8772cf6 + spriteID: cb80e49662d872849a63b9e48427c77a internalID: -7408847304050000695 vertices: [] indices: @@ -1223,10 +1223,10 @@ TextureImporter: name: "\u706B\u5C71\u50CF\u7D20\u7248 51.aseprite" rect: serializedVersion: 2 - x: 1386 - y: 0 - width: 462 - height: 410 + x: 4950 + y: 828 + width: 550 + height: 414 alignment: 9 pivot: {x: 0.5, y: 0} border: {x: 0, y: 0, z: 0, w: 0} @@ -1234,12 +1234,411 @@ TextureImporter: physicsShape: [] tessellationDetail: 0 bones: [] - spriteID: 1c33d3cf750be804f918e0a6b58179a4 + spriteID: 54f2759ec691290449d76d675058262b internalID: -9064000754950765326 vertices: [] indices: edges: [] weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 52.aseprite" + rect: + serializedVersion: 2 + x: 5500 + y: 828 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 7384a3243cb733840a8ed4496aab153f + internalID: 476753166 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 53.aseprite" + rect: + serializedVersion: 2 + x: 6050 + y: 828 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: b05b54de3e97e8546b888709f23409a4 + internalID: -290437651 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 54.aseprite" + rect: + serializedVersion: 2 + x: 6600 + y: 828 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: ce4272c25ed7b3342af2919979ac7a90 + internalID: 1161122348 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 55.aseprite" + rect: + serializedVersion: 2 + x: 7150 + y: 828 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 19c7769161cea994f938dd7798e9ecd7 + internalID: -1682718823 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 56.aseprite" + rect: + serializedVersion: 2 + x: 0 + y: 414 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 6c476510c78995d4f81ed5c0b6b80adc + internalID: 2006670954 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 57.aseprite" + rect: + serializedVersion: 2 + x: 550 + y: 414 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 5832296af2f80be45b430f81c675deeb + internalID: -1240037077 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 58.aseprite" + rect: + serializedVersion: 2 + x: 1100 + y: 414 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 99873bc954204b94fb19d900cb0fba59 + internalID: 1165957775 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 59.aseprite" + rect: + serializedVersion: 2 + x: 1650 + y: 414 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: d29db1152f214df40829c3662d6c40b5 + internalID: 724704929 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 60.aseprite" + rect: + serializedVersion: 2 + x: 2200 + y: 414 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: e852794912722ba40af0775d65f4105b + internalID: 1934625881 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 61.aseprite" + rect: + serializedVersion: 2 + x: 2750 + y: 414 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: ed727e7375c0bba48bdef6a6a6e97139 + internalID: -797704885 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 62.aseprite" + rect: + serializedVersion: 2 + x: 3300 + y: 414 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 16bd7a0e30ee2234d9dcb6fc18dc89f9 + internalID: -1458435954 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 63.aseprite" + rect: + serializedVersion: 2 + x: 3850 + y: 414 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: e23be537bc6e4c44e82a120cc1c76d5b + internalID: -333109225 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 64.aseprite" + rect: + serializedVersion: 2 + x: 4400 + y: 414 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 517635315d046d440887a508a209ef7d + internalID: -1362429362 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 65.aseprite" + rect: + serializedVersion: 2 + x: 4950 + y: 414 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 9c8e5bc1a0c32ad43b00292882962130 + internalID: -679944024 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 66.aseprite" + rect: + serializedVersion: 2 + x: 5500 + y: 414 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 3123636df6fc1ae4a91c42c6249d3eab + internalID: -1037734280 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 67.aseprite" + rect: + serializedVersion: 2 + x: 6050 + y: 414 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 5cbccd8f2878fcc4d9c4f0e42929f13c + internalID: 1184580192 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 68.aseprite" + rect: + serializedVersion: 2 + x: 6600 + y: 414 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 47f8601f5ea9f6b449c369f12ef98294 + internalID: 1227746343 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 69.aseprite" + rect: + serializedVersion: 2 + x: 7150 + y: 414 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: e6370cc03b1ac5c4a8f953c9c51121b6 + internalID: -1235719373 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: "\u706B\u5C71\u50CF\u7D20\u7248 70.aseprite" + rect: + serializedVersion: 2 + x: 0 + y: 0 + width: 550 + height: 414 + alignment: 9 + pivot: {x: 0.5, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 26991c6e671616d458066a0bd320a545 + internalID: 480632 + vertices: [] + indices: + edges: [] + weights: [] outline: [] physicsShape: [] bones: [] diff --git a/Assets/GameContent/Scene_Bridge/Actor.meta b/Assets/GameContent/Scene_Bridge/Actor.meta new file mode 100644 index 000000000..e4763ae8a --- /dev/null +++ b/Assets/GameContent/Scene_Bridge/Actor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d96cfe3953ea060409ec8abf7fdf19b6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameContent/Scene_Bridge/Actor/天桥佩佩.meta b/Assets/GameContent/Scene_Bridge/Actor/天桥佩佩.meta new file mode 100644 index 000000000..e590f23ee --- /dev/null +++ b/Assets/GameContent/Scene_Bridge/Actor/天桥佩佩.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ab69953023519fe4cadc49087ab6941a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameContent/Scene_Bridge/Actor/天桥佩佩/天桥上夕阳佩佩动作.aseprite b/Assets/GameContent/Scene_Bridge/Actor/天桥佩佩/天桥上夕阳佩佩动作.aseprite new file mode 100644 index 000000000..5dcec4d5e Binary files /dev/null and b/Assets/GameContent/Scene_Bridge/Actor/天桥佩佩/天桥上夕阳佩佩动作.aseprite differ diff --git a/Assets/GameContent/Scene_Bridge/Actor/天桥佩佩/天桥上夕阳佩佩动作.aseprite.meta b/Assets/GameContent/Scene_Bridge/Actor/天桥佩佩/天桥上夕阳佩佩动作.aseprite.meta new file mode 100644 index 000000000..446cabefb --- /dev/null +++ b/Assets/GameContent/Scene_Bridge/Actor/天桥佩佩/天桥上夕阳佩佩动作.aseprite.meta @@ -0,0 +1,388 @@ +fileFormatVersion: 2 +guid: 43a56670a48b67c4d8d68e6667fc1533 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 62a9f0aa5b59740cfbadc7e5f9823bb0, type: 3} + textureImporterSettings: + alphaSource: 1 + mipMapMode: 0 + enableMipMap: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + convertToNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + swizzle: 50462976 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + nPOTScale: 1 + sRGBTexture: 1 + spriteMode: 2 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 0 + flipbookColumns: 0 + ignorePngGamma: 0 + cookieMode: 0 + filterMode: 0 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + normalMap: 0 + textureFormat: 0 + maxTextureSize: 0 + lightmap: 0 + compressionQuality: 0 + linearTexture: 0 + grayScaleToAlpha: 0 + rGBM: 0 + cubemapConvolutionSteps: 0 + cubemapConvolutionExponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + previousAsepriteImporterSettings: + fileImportMode: 1 + importHiddenLayers: 0 + layerImportMode: 1 + defaultPivotSpace: 0 + defaultPivotAlignment: 7 + customPivotPosition: {x: 0.5, y: 0.5} + spritePadding: 0 + generateModelPrefab: 1 + generateAnimationClips: 1 + addSortingGroup: 1 + addShadowCasters: 0 + asepriteImporterSettings: + fileImportMode: 1 + importHiddenLayers: 0 + layerImportMode: 1 + defaultPivotSpace: 0 + defaultPivotAlignment: 7 + customPivotPosition: {x: 0.5, y: 0.5} + spritePadding: 0 + generateModelPrefab: 1 + generateAnimationClips: 1 + addSortingGroup: 1 + addShadowCasters: 0 + importFileNodeState: 1 + platformSettingsDirtyTick: 0 + textureAssetName: + singleSpriteImportData: + - name: + originalName: + pivot: {x: 0, y: 0} + alignment: 0 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + spriteID: + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 0, y: 0} + animatedSpriteImportData: + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_0" + originalName: + pivot: {x: 0.5, y: 0} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 4 + y: 4 + width: 76 + height: 111 + spriteID: 476c98f569b965643b8b865c30901818 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 4, y: 4} + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_1" + originalName: + pivot: {x: 0.5, y: 0} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 4 + y: 123 + width: 76 + height: 111 + spriteID: e28da4ad8f4052b48a8ecfa7897a9359 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 4, y: 123} + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_2" + originalName: + pivot: {x: 0.5, y: 0} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 4 + y: 242 + width: 76 + height: 111 + spriteID: 9e459384b3e42974a9e8daa0f8b84e56 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 4, y: 242} + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_4" + originalName: + pivot: {x: 0.5, y: 0} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 4 + y: 361 + width: 76 + height: 111 + spriteID: 31732d0f0c19e0a4ebb63e572f1a97cc + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 4, y: 361} + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_5" + originalName: + pivot: {x: 0.5, y: 0} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 88 + y: 4 + width: 76 + height: 111 + spriteID: 2020fa9e53ae4674a81aace06ba0f979 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 88, y: 4} + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_6" + originalName: + pivot: {x: 0.5, y: 0} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 88 + y: 123 + width: 76 + height: 111 + spriteID: 63509fe351d559d4686e6826cabbc9e2 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 88, y: 123} + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_7" + originalName: + pivot: {x: 0.5, y: 0} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 88 + y: 242 + width: 76 + height: 111 + spriteID: 558aaef6196259a46a037e9f230b22c4 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 88, y: 242} + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_3" + originalName: + pivot: {x: 0.5, y: 0} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 88 + y: 361 + width: 76 + height: 111 + spriteID: ab2848adeccd5d34bab6d520639c4435 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 88, y: 361} + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_8" + originalName: + pivot: {x: 0.5, y: 0} + alignment: 9 + border: {x: 0, y: 0, z: 0, w: 0} + rect: + serializedVersion: 2 + x: 172 + y: 4 + width: 76 + height: 111 + spriteID: e20ccd843be9e7640aee88d5ee02fa30 + spriteBone: [] + spriteOutline: [] + vertices: [] + spritePhysicsOutline: [] + indices: + edges: [] + tessellationDetail: 0 + uvTransform: {x: 172, y: 4} + spriteSheetImportData: [] + asepriteLayers: + - layerIndex: 0 + guid: 244500564 + name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C" + layerFlags: 0 + layerType: 0 + blendMode: 0 + cells: + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_0" + frameIndex: 0 + cellRect: + x: 0 + y: 0 + width: 76 + height: 111 + spriteId: 476c98f569b965643b8b865c30901818 + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_1" + frameIndex: 1 + cellRect: + x: 0 + y: 0 + width: 76 + height: 111 + spriteId: e28da4ad8f4052b48a8ecfa7897a9359 + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_2" + frameIndex: 2 + cellRect: + x: 0 + y: 0 + width: 76 + height: 111 + spriteId: 9e459384b3e42974a9e8daa0f8b84e56 + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_4" + frameIndex: 4 + cellRect: + x: 0 + y: 0 + width: 76 + height: 111 + spriteId: 31732d0f0c19e0a4ebb63e572f1a97cc + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_5" + frameIndex: 5 + cellRect: + x: 0 + y: 0 + width: 76 + height: 111 + spriteId: 2020fa9e53ae4674a81aace06ba0f979 + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_6" + frameIndex: 6 + cellRect: + x: 0 + y: 0 + width: 76 + height: 111 + spriteId: 63509fe351d559d4686e6826cabbc9e2 + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_7" + frameIndex: 7 + cellRect: + x: 0 + y: 0 + width: 76 + height: 111 + spriteId: 558aaef6196259a46a037e9f230b22c4 + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_3" + frameIndex: 3 + cellRect: + x: 0 + y: 0 + width: 76 + height: 111 + spriteId: ab2848adeccd5d34bab6d520639c4435 + - name: "\u5929\u6865\u4E0A\u5915\u9633\u4F69\u4F69\u52A8\u4F5C_Frame_8" + frameIndex: 8 + cellRect: + x: 0 + y: 0 + width: 76 + height: 111 + spriteId: e20ccd843be9e7640aee88d5ee02fa30 + linkedCells: [] + parentIndex: -1 + platformSettings: [] + secondarySpriteTextures: [] + spritePackingTag: + canvasSize: {x: 76, y: 111} diff --git a/Assets/Scripts/Dialog System/DialogController.cs b/Assets/Scripts/Dialog System/DialogController.cs index 71ce27eb0..7ecd13907 100644 --- a/Assets/Scripts/Dialog System/DialogController.cs +++ b/Assets/Scripts/Dialog System/DialogController.cs @@ -22,6 +22,13 @@ namespace AibisDream private string _currentNodeName; private string[] _currentNodeTags; + private PendingExitCheckpoint _pendingExitCheckpoint; + private long _dialogueFlowVersion; + private long _dialogueRunId; + private IDisposable _exitHandoffLock; + + internal long DialogueFlowVersion => _dialogueFlowVersion; + internal long DialogueRunId => _dialogueRunId; private void Start() { @@ -31,18 +38,9 @@ namespace AibisDream _dialogueRunner.onNodeStart ??= new UnityEventString(); _dialogueRunner.onNodeComplete ??= new UnityEventString(); - _dialogueRunner.onDialogueStart.AddListener(() => - { - DialogueActivityChanged?.Invoke(true); - EnumEventSystem.Global.Send(InteractionEventEnum.DialogStart); - }); + _dialogueRunner.onDialogueStart.AddListener(OnDialogueStart); - _dialogueRunner.onDialogueComplete.AddListener(() => - { - DialogueActivityChanged?.Invoke(false); - EnumEventSystem.Global.Send(InteractionEventEnum.DialogEnd); - ClearCurrentNodeContext(); - }); + _dialogueRunner.onDialogueComplete.AddListener(OnDialogueComplete); _dialogueRunner.onNodeStart.AddListener(OnNodeStart); _dialogueRunner.onNodeComplete.AddListener(OnNodeComplete); @@ -61,6 +59,8 @@ namespace AibisDream private void OnDisable() { + CancelPendingExitCheckpoint("DialogController disabled", logIfPending: false); + SingleCastEventSystem.Global.Unregister(DialogEventEnum.StartNode); EnumEventSystem.Global.UnRegister(GameLifecycleEvent.SessionStarted, ResetAdvanceMode); @@ -92,6 +92,7 @@ namespace AibisDream /// Yarn组 public void StartDialog(YarnProject yarnProject) { + CancelPendingExitCheckpoint("StartDialog 切换 YarnProject"); PrepareYarnProjectForDialog(yarnProject); _dialogueRunner.SetProject(yarnProject); _ = _dialogueRunner.StartDialogue("Start"); @@ -104,6 +105,8 @@ namespace AibisDream public IEnumerator StopDialogRoutine() { + CancelPendingExitCheckpoint("StopDialogRoutine", logIfPending: false); + if (_dialogueRunner != null && _dialogueRunner.IsDialogueRunning) { yield return _dialogueRunner.Stop(); @@ -122,6 +125,7 @@ namespace AibisDream public void LoadDialog(YarnProject yarnProject) { + CancelPendingExitCheckpoint("LoadDialog 切换 YarnProject"); PrepareYarnProjectForDialog(yarnProject); _dialogueRunner.SetProject(yarnProject); } @@ -189,9 +193,14 @@ namespace AibisDream private void OnNodeStart(string nodeName) { + _dialogueFlowVersion++; + CancelPendingExitCheckpoint( + $"节点 {nodeName} 已开始,说明之前的退出保存路径继续运行 Yarn", + incrementFlowVersion: false); UpdateCurrentNodeContext(nodeName); var projectId = _dialogueRunner?.YarnProject?.name; + var talkSceneId = GetCurrentTalkSceneId(); var tags = _currentNodeTags ?? Array.Empty(); if (SaveRestoreOrchestrator.IsRestoring) @@ -200,7 +209,12 @@ namespace AibisDream return; } - if (!SavePointEvaluator.OnNodeStartForAutoSave(projectId, nodeName, tags, out var reason)) + if (!SavePointEvaluator.OnNodeStartForSavePolicy( + projectId, + nodeName, + tags, + out var policy, + out var reason)) { if (reason == SavePointRejectReason.DetourResume) { @@ -210,15 +224,122 @@ namespace AibisDream return; } - StartCoroutine(SaveRestoreOrchestrator.AutoSaveRoutine(nodeName)); + if (policy.Timing == NodeSaveTiming.DialogueExit) + { + _pendingExitCheckpoint = new PendingExitCheckpoint + { + ProjectId = projectId, + TalkSceneId = talkSceneId, + NodeName = nodeName, + FlowVersion = _dialogueFlowVersion, + DialogueRunId = _dialogueRunId + }; + return; + } + + if (policy.Timing == NodeSaveTiming.NodeEnter) + { + StartCoroutine(SaveRestoreOrchestrator.AutoSaveRoutine( + nodeName, + projectId, + talkSceneId, + _dialogueRunId, + _dialogueFlowVersion)); + } } private void OnNodeComplete(string nodeName) { SavePointEvaluator.OnNodeComplete(_dialogueRunner?.YarnProject?.name, nodeName); + + if (_pendingExitCheckpoint != null + && string.Equals(_pendingExitCheckpoint.NodeName, nodeName, StringComparison.Ordinal) + && string.Equals( + _pendingExitCheckpoint.ProjectId, + _dialogueRunner?.YarnProject?.name, + StringComparison.Ordinal) + && _pendingExitCheckpoint.DialogueRunId == _dialogueRunId) + { + _pendingExitCheckpoint.IsNodeComplete = true; + } + ClearCurrentNodeContext(); } + private void OnDialogueComplete() + { + var checkpoint = _pendingExitCheckpoint; + _pendingExitCheckpoint = null; + if (checkpoint?.IsNodeComplete == true) + { + _exitHandoffLock = EventSystemEx.Instance?.AcquireInteractionLock( + $"exit checkpoint:{checkpoint.NodeName}"); + } + + DialogueActivityChanged?.Invoke(false); + EnumEventSystem.Global.Send(InteractionEventEnum.DialogEnd); + ClearCurrentNodeContext(); + + if (checkpoint?.IsNodeComplete != true) + { + return; + } + + StartCoroutine(SaveDialogueExitCheckpointRoutine(checkpoint)); + } + + private void OnDialogueStart() + { + _dialogueRunId++; + _dialogueFlowVersion++; + DialogueActivityChanged?.Invoke(true); + EnumEventSystem.Global.Send(InteractionEventEnum.DialogStart); + } + + private IEnumerator SaveDialogueExitCheckpointRoutine(PendingExitCheckpoint checkpoint) + { + try + { + yield return SaveRestoreOrchestrator.DialogueExitSaveRoutine( + checkpoint.NodeName, + checkpoint.ProjectId, + checkpoint.TalkSceneId, + checkpoint.DialogueRunId, + checkpoint.FlowVersion); + } + finally + { + ReleaseExitHandoffLock(); + } + } + + private void CancelPendingExitCheckpoint( + string reason, + bool logIfPending = true, + bool incrementFlowVersion = true) + { + if (incrementFlowVersion) + { + _dialogueFlowVersion++; + } + + ReleaseExitHandoffLock(); + + if (_pendingExitCheckpoint == null) + { + return; + } + + if (logIfPending) + { + Debug.LogWarning( + $"[DialogController] 取消 interaction/save_on_exit 退出存档: " + + $"node={_pendingExitCheckpoint.NodeName}, reason={reason}"); + } + + _pendingExitCheckpoint = null; + } + private void UpdateCurrentNodeContext(string nodeName) { if (_dialogueRunner == null || _dialogueRunner.Dialogue == null) @@ -241,6 +362,29 @@ namespace AibisDream _currentNodeTags = null; } + private void ReleaseExitHandoffLock() + { + _exitHandoffLock?.Dispose(); + _exitHandoffLock = null; + } + + private static string GetCurrentTalkSceneId() + { + return GameManager.Instance != null + ? GameManager.Session.CurrentTalkScene?.name + : null; + } + + private sealed class PendingExitCheckpoint + { + public string ProjectId; + public string TalkSceneId; + public string NodeName; + public long FlowVersion; + public long DialogueRunId; + public bool IsNodeComplete; + } + #region 推进方式修改 public BindProperty advanceMode = new(new AdvanceMode()); diff --git a/Assets/Scripts/Dialog System/OptionView.cs b/Assets/Scripts/Dialog System/OptionView.cs index 7d7d2a8a6..080b07b86 100644 --- a/Assets/Scripts/Dialog System/OptionView.cs +++ b/Assets/Scripts/Dialog System/OptionView.cs @@ -59,11 +59,6 @@ namespace AibisDream return YarnTask.CompletedTask; } - public override void OnNodeExit(string nodeName) - { - ClearPendingOptionPrompt(); - } - public void LoadBubbles(BubbleSlotGroupData data) { defaultViewType = data.dialogViewType; diff --git a/Assets/Scripts/Framework/EventSystemKit/EventSystemEx.cs b/Assets/Scripts/Framework/EventSystemKit/EventSystemEx.cs index 20a34b25d..0b321a4e4 100644 --- a/Assets/Scripts/Framework/EventSystemKit/EventSystemEx.cs +++ b/Assets/Scripts/Framework/EventSystemKit/EventSystemEx.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System; using AibisDream.Kit; using UnityEngine; @@ -9,6 +10,8 @@ namespace AibisDream.Framework #region 状态 public bool isLocked; + private bool _dialogueLocked; + private int _scopedLockDepth; #endregion @@ -106,12 +109,38 @@ namespace AibisDream.Framework private void HandleDialogueComplete() { - isLocked = false; + _dialogueLocked = false; + RefreshLockState(); } private void HandleDialogueStart() { - isLocked = true; + _dialogueLocked = true; + RefreshLockState(); + } + + public IDisposable AcquireInteractionLock(string reason) + { + _scopedLockDepth++; + RefreshLockState(); + Debug.Log( + $"[EventSystemEx] Acquire interaction lock: {reason ?? "(unspecified)"}, " + + $"depth={_scopedLockDepth}"); + return new InteractionLockScope(this, reason); + } + + private void ReleaseInteractionLock(string reason) + { + _scopedLockDepth = Math.Max(0, _scopedLockDepth - 1); + RefreshLockState(); + Debug.Log( + $"[EventSystemEx] Release interaction lock: {reason ?? "(unspecified)"}, " + + $"depth={_scopedLockDepth}"); + } + + private void RefreshLockState() + { + isLocked = _dialogueLocked || _scopedLockDepth > 0; } #region 单例必须的代码 @@ -121,6 +150,9 @@ namespace AibisDream.Framework pointerOverObjList = new List(); draggingObjList = new List(); holdingObjList = new List(); + _dialogueLocked = false; + _scopedLockDepth = 0; + RefreshLockState(); EnumEventSystem.Global.Register(GameLifecycleEvent.SessionStarted, ClearAll); EnumEventSystem.Global.Register(GameLifecycleEvent.SessionEnded, ClearAll); @@ -143,6 +175,33 @@ namespace AibisDream.Framework EnumEventSystem.Global.UnRegister(InteractionEventEnum.DialogEnd, HandleDialogueComplete); EnumEventSystem.Global.UnRegister(InteractionEventEnum.DialogStart, HandleDialogueStart); + + _dialogueLocked = false; + _scopedLockDepth = 0; + RefreshLockState(); + } + + private sealed class InteractionLockScope : IDisposable + { + private EventSystemEx _owner; + private readonly string _reason; + + public InteractionLockScope(EventSystemEx owner, string reason) + { + _owner = owner; + _reason = reason; + } + + public void Dispose() + { + if (_owner == null) + { + return; + } + + _owner.ReleaseInteractionLock(_reason); + _owner = null; + } } #endregion diff --git a/Assets/Scripts/SaveSystem/Development/TestSaveCoverage.cs b/Assets/Scripts/SaveSystem/Development/TestSaveCoverage.cs index d795ae4ec..dce66a7a5 100644 --- a/Assets/Scripts/SaveSystem/Development/TestSaveCoverage.cs +++ b/Assets/Scripts/SaveSystem/Development/TestSaveCoverage.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using UnityEngine; namespace AibisDream.SaveSystem { @@ -16,6 +17,7 @@ namespace AibisDream.SaveSystem { public TestSaveCoverageRowKind Kind { get; internal set; } public string NodeName { get; internal set; } + public string ResumeMode { get; internal set; } public TestSaveEntry Entry { get; internal set; } public long SortOrder { get; internal set; } } @@ -49,7 +51,7 @@ namespace AibisDream.SaveSystem var chapter = chapters[chapterIndex]; if (chapter == null) continue; - var expectedNodes = GetExpectedNodes(chapter); + var expectedCheckpoints = GetExpectedCheckpoints(chapter); var chapterEntries = entries .Where(item => item.Meta != null && string.Equals(item.Meta.sceneSoName, chapter.name, StringComparison.Ordinal) @@ -60,33 +62,37 @@ namespace AibisDream.SaveSystem .ToArray(); foreach (var entry in chapterEntries) consumed.Add(entry); - var validByNode = chapterEntries + var validByCheckpoint = chapterEntries .Where(item => item.IsValid) - .GroupBy(item => item.NodeName, StringComparer.Ordinal) + .GroupBy( + item => BuildCheckpointKey(item.NodeName, item.ResumeMode), + StringComparer.Ordinal) .ToDictionary( group => group.Key, group => group.OrderBy(item => item.Meta.firstSeenOrder).First(), StringComparer.Ordinal); var rows = new List(); - foreach (var entry in validByNode.Values.OrderBy(item => item.Meta.firstSeenOrder)) + foreach (var entry in validByCheckpoint.Values.OrderBy(item => item.Meta.firstSeenOrder)) { rows.Add(new TestSaveCoverageRow { Kind = TestSaveCoverageRowKind.Recorded, NodeName = entry.NodeName, + ResumeMode = entry.ResumeMode, Entry = entry, SortOrder = entry.Meta.firstSeenOrder }); } - foreach (var nodeName in expectedNodes - .Where(node => !validByNode.ContainsKey(node)) - .OrderBy(node => node, StringComparer.OrdinalIgnoreCase)) + foreach (var expectation in expectedCheckpoints.Values + .Where(item => !validByCheckpoint.ContainsKey(item.Key)) + .OrderBy(item => item.NodeName, StringComparer.OrdinalIgnoreCase)) { rows.Add(new TestSaveCoverageRow { Kind = TestSaveCoverageRowKind.Missing, - NodeName = nodeName, + NodeName = expectation.NodeName, + ResumeMode = expectation.ResumeMode, SortOrder = long.MaxValue }); } @@ -98,6 +104,7 @@ namespace AibisDream.SaveSystem { Kind = TestSaveCoverageRowKind.Invalid, NodeName = entry.NodeName ?? "(未知节点)", + ResumeMode = entry.ResumeMode, Entry = entry, SortOrder = entry.Meta?.firstSeenOrder ?? long.MaxValue }); @@ -108,8 +115,8 @@ namespace AibisDream.SaveSystem ChapterId = chapter.name, Title = string.IsNullOrWhiteSpace(chapter.title) ? chapter.name : chapter.title, ChapterOrder = chapterIndex, - RecordedCount = validByNode.Keys.Count(expectedNodes.Contains), - ExpectedCount = expectedNodes.Count, + RecordedCount = validByCheckpoint.Keys.Count(expectedCheckpoints.ContainsKey), + ExpectedCount = expectedCheckpoints.Count, Rows = rows }); } @@ -131,6 +138,7 @@ namespace AibisDream.SaveSystem { Kind = TestSaveCoverageRowKind.Invalid, NodeName = item.NodeName ?? "(未知节点)", + ResumeMode = item.ResumeMode, Entry = item, SortOrder = item.Meta?.firstSeenOrder ?? long.MaxValue }) @@ -143,7 +151,14 @@ namespace AibisDream.SaveSystem public static HashSet GetExpectedNodes(TalkSceneSO chapter) { - var result = new HashSet(StringComparer.Ordinal); + return GetExpectedCheckpoints(chapter).Values + .Select(item => item.NodeName) + .ToHashSet(StringComparer.Ordinal); + } + + private static Dictionary GetExpectedCheckpoints(TalkSceneSO chapter) + { + var result = new Dictionary(StringComparer.Ordinal); var project = chapter?.yarnProject; if (project?.Program?.Nodes == null) return result; @@ -157,14 +172,65 @@ namespace AibisDream.SaveSystem var tags = string.IsNullOrWhiteSpace(tagsValue) ? Array.Empty() : tagsValue.Split(Array.Empty(), StringSplitOptions.RemoveEmptyEntries); - if (SavePointEvaluator.EvaluateNodeTagsForAutoSaveSilently(node.Name, tags, out _)) + var policy = SavePointEvaluator.ResolveNodePolicy( + node.Name, + tags, + out var reason, + logWarnings: false); + if (reason == SavePointRejectReason.InvalidTagConfiguration) { - result.Add(node.Name); + Debug.LogError( + $"[TestSaveCoverage] 节点 {node.Name} 的保存标签配置无效: " + + $"[{string.Join(", ", tags)}]"); } + else if (tags.Any(tag => + string.Equals(tag, "interaction", StringComparison.OrdinalIgnoreCase)) + && tags.Any(tag => + string.Equals(tag, "save_on_exit", StringComparison.OrdinalIgnoreCase))) + { + Debug.LogWarning( + $"[TestSaveCoverage] 节点 {node.Name} 的 interaction 已包含 save_on_exit 语义," + + "请移除重复标记。"); + } + + if (policy.Timing == NodeSaveTiming.None) + { + continue; + } + + var resumeMode = policy.ResumeMode.ToString(); + var key = BuildCheckpointKey(node.Name, resumeMode); + result[key] = new ExpectedCheckpoint(key, node.Name, resumeMode); } return result; } + + private static string BuildCheckpointKey(string nodeName, string resumeMode) + { + return $"{nodeName ?? string.Empty}\n{NormalizeResumeMode(resumeMode)}"; + } + + private static string NormalizeResumeMode(string resumeMode) + { + return string.IsNullOrEmpty(resumeMode) + ? nameof(SaveResumeMode.RestartNode) + : resumeMode; + } + + private readonly struct ExpectedCheckpoint + { + public readonly string Key; + public readonly string NodeName; + public readonly string ResumeMode; + + public ExpectedCheckpoint(string key, string nodeName, string resumeMode) + { + Key = key; + NodeName = nodeName; + ResumeMode = resumeMode; + } + } } } #endif diff --git a/Assets/Scripts/SaveSystem/Development/TestSaveRecorder.cs b/Assets/Scripts/SaveSystem/Development/TestSaveRecorder.cs index f7bf5f6c2..d9c5ddfb7 100644 --- a/Assets/Scripts/SaveSystem/Development/TestSaveRecorder.cs +++ b/Assets/Scripts/SaveSystem/Development/TestSaveRecorder.cs @@ -30,7 +30,11 @@ namespace AibisDream.SaveSystem IsRecording = recording; } - internal static TestSaveRecordRequest CreateRequest(SaveSnapshot snapshot, byte[] thumbnail) + internal static TestSaveRecordRequest CreateRequest( + SaveSnapshot snapshot, + byte[] thumbnail, + string saveTrigger, + string resumeMode) { if (!IsRecording || snapshot?.anchor == null @@ -42,12 +46,26 @@ namespace AibisDream.SaveSystem } var anchor = snapshot.anchor; + var expectedResumeMode = anchor.startDialogueOnRestore + ? nameof(SaveResumeMode.RestartNode) + : nameof(SaveResumeMode.StateOnly); + if (!string.Equals(resumeMode, expectedResumeMode, StringComparison.Ordinal)) + { + throw new InvalidOperationException( + $"测试存档恢复模式与 snapshot anchor 不一致: meta={resumeMode}, " + + $"anchor={expectedResumeMode}"); + } + var chapter = GameManager.Instance?.RuntimeChapters? .FirstOrDefault(item => item != null && string.Equals(item.name, anchor.sceneSoName, StringComparison.Ordinal) && string.Equals(item.yarnProject?.name, anchor.yarnProjectId, StringComparison.Ordinal)); - var dedupeKey = BuildDedupeKey(anchor.sceneSoName, anchor.yarnProjectId, anchor.nodeName); + var dedupeKey = BuildDedupeKey( + anchor.sceneSoName, + anchor.yarnProjectId, + anchor.nodeName, + resumeMode); return new TestSaveRecordRequest { Snapshot = snapshot, @@ -59,6 +77,9 @@ namespace AibisDream.SaveSystem SceneSoName = anchor.sceneSoName, YarnProjectId = anchor.yarnProjectId, NodeName = anchor.nodeName, + SaveTrigger = saveTrigger, + ResumeMode = resumeMode, + StartDialogueOnRestore = anchor.startDialogueOnRestore, SceneName = snapshot.scene?.sceneName, GameVersion = snapshot.gameVersion }; @@ -81,9 +102,21 @@ namespace AibisDream.SaveSystem }); } - public static string BuildDedupeKey(string sceneSoName, string yarnProjectId, string nodeName) + public static string BuildDedupeKey( + string sceneSoName, + string yarnProjectId, + string nodeName, + string resumeMode = null) { - return $"{sceneSoName ?? string.Empty}\n{yarnProjectId ?? string.Empty}\n{nodeName ?? string.Empty}"; + var baseKey = + $"{sceneSoName ?? string.Empty}\n{yarnProjectId ?? string.Empty}\n{nodeName ?? string.Empty}"; + return string.IsNullOrEmpty(resumeMode) + || string.Equals( + resumeMode, + nameof(SaveResumeMode.RestartNode), + StringComparison.Ordinal) + ? baseKey + : $"{baseKey}\n{resumeMode}"; } } } diff --git a/Assets/Scripts/SaveSystem/Development/TestSaveRepository.cs b/Assets/Scripts/SaveSystem/Development/TestSaveRepository.cs index b6bfdc6f0..b8ebaa3c9 100644 --- a/Assets/Scripts/SaveSystem/Development/TestSaveRepository.cs +++ b/Assets/Scripts/SaveSystem/Development/TestSaveRepository.cs @@ -137,6 +137,9 @@ namespace AibisDream.SaveSystem sceneSoName = request.SceneSoName, yarnProjectId = request.YarnProjectId, nodeName = request.NodeName, + saveTrigger = request.SaveTrigger, + resumeMode = request.ResumeMode, + startDialogueOnRestore = request.Snapshot.anchor.startDialogueOnRestore, sceneName = request.SceneName, firstSeenOrder = existingMeta?.firstSeenOrder ?? NextFirstSeenOrder(), firstRecordedAt = existingMeta?.firstRecordedAt ?? now, @@ -229,7 +232,14 @@ namespace AibisDream.SaveSystem if (entry.Meta != null && (!string.Equals(snapshot.anchor.sceneSoName, entry.Meta.sceneSoName, StringComparison.Ordinal) || !string.Equals(snapshot.anchor.yarnProjectId, entry.Meta.yarnProjectId, StringComparison.Ordinal) - || !string.Equals(snapshot.anchor.nodeName, entry.Meta.nodeName, StringComparison.Ordinal))) + || !string.Equals( + snapshot.anchor.nodeName, + entry.Meta.nodeName, + StringComparison.Ordinal) + || snapshot.anchor.startDialogueOnRestore + != entry.Meta.startDialogueOnRestore + || snapshot.anchor.startDialogueOnRestore + != !IsStateOnly(entry.Meta.resumeMode))) { error = "快照 anchor 与 meta 不一致。"; snapshot = null; @@ -359,6 +369,8 @@ namespace AibisDream.SaveSystem else if (string.IsNullOrWhiteSpace(meta.sceneSoName) || string.IsNullOrWhiteSpace(meta.yarnProjectId) || string.IsNullOrWhiteSpace(meta.nodeName) + || string.IsNullOrWhiteSpace(meta.saveTrigger) + || string.IsNullOrWhiteSpace(meta.resumeMode) || string.IsNullOrWhiteSpace(meta.dedupeKey)) { entry.Status = TestSaveEntryStatus.InvalidAnchor; @@ -457,6 +469,14 @@ namespace AibisDream.SaveSystem } } + private static bool IsStateOnly(string resumeMode) + { + return string.Equals( + resumeMode, + nameof(SaveResumeMode.StateOnly), + StringComparison.Ordinal); + } + private void RecoverTransactions() { if (!Directory.Exists(_rootPath)) diff --git a/Assets/Scripts/SaveSystem/Development/TestSaveTypes.cs b/Assets/Scripts/SaveSystem/Development/TestSaveTypes.cs index 7b9bc449a..7adffba46 100644 --- a/Assets/Scripts/SaveSystem/Development/TestSaveTypes.cs +++ b/Assets/Scripts/SaveSystem/Development/TestSaveTypes.cs @@ -18,7 +18,7 @@ namespace AibisDream.SaveSystem [Serializable] public sealed class TestSaveMeta { - public const int CurrentLibraryVersion = 1; + public const int CurrentLibraryVersion = 2; public int libraryVersion = CurrentLibraryVersion; public string entryId; @@ -28,6 +28,9 @@ namespace AibisDream.SaveSystem public string sceneSoName; public string yarnProjectId; public string nodeName; + public string saveTrigger; + public string resumeMode; + public bool startDialogueOnRestore; public string sceneName; public long firstSeenOrder; public string firstRecordedAt; @@ -52,6 +55,8 @@ namespace AibisDream.SaveSystem public string EntryId => Meta?.entryId; public string ChapterId => Meta?.chapterId; public string NodeName => Meta?.nodeName; + public string SaveTrigger => Meta?.saveTrigger; + public string ResumeMode => Meta?.resumeMode; } public sealed class TestSaveScanResult @@ -72,6 +77,9 @@ namespace AibisDream.SaveSystem public string SceneSoName; public string YarnProjectId; public string NodeName; + public string SaveTrigger; + public string ResumeMode; + public bool StartDialogueOnRestore; public string SceneName; public string GameVersion; } diff --git a/Assets/Scripts/SaveSystem/README.md b/Assets/Scripts/SaveSystem/README.md index 59d32be19..b8bae1063 100644 --- a/Assets/Scripts/SaveSystem/README.md +++ b/Assets/Scripts/SaveSystem/README.md @@ -18,7 +18,7 @@ // 自动存档(节点进入事件触发) yield return SaveRestoreOrchestrator.AutoSaveRoutine(nodeName); -// Yarn 显式存档(<>,默认 omit anchor) +// Yarn 显式存档(<>,保留来源节点但恢复时不启动 Yarn) yield return SaveRestoreOrchestrator.ExplicitSaveRoutine(); // 手动存档:复制最近落盘档(含 OnNodeStart 与 <>) @@ -37,13 +37,23 @@ YarnVariableStorage.Instance.SetValue("$foo", 1f); Yarn 脚本: ```yarn +// 推荐:有内容的交互入口节点 +tags: interaction + +// 或为其他一级类型覆盖保存时机 +tags: content save_on_exit + +// 仅兼容旧内容 <> ``` +- `interaction` / `save_on_exit` 进入时不存档;对应节点完成后若直接结束本轮 Dialogue,则自动保存 state-only 档。 +- 若执行路径继续 `jump` / `detour` 到其他 Yarn 节点,退出档会取消并记录告警。 - 放在目标节点**末尾**:所有状态命令(`switch_fix_system_to`、`hide_dialog`、`play_timeline` 等)执行完毕之后,`<>` / `<>` 之前。 -- 默认 **omit anchor**(`anchor.nodeName` 为空);读档时不重进 Yarn,仅还原 scene + sections + 变量。 +- `anchor.nodeName` 始终保留来源节点;`anchor.startDialogueOnRestore=false`,读档时只加载 YarnProject,不启动节点。 +- 退出档在 `DialogEnd` 同步初始化后等待一帧捕获;这一帧由 scoped interaction lock 保持输入锁定,捕获进入写盘队列后再交出控制权。 - 绕过 tag / `no_save` 的自动判定(`CanExplicitSave`);仍受读档中、暂停、SuppressAutoSave 门控。 -- 与 `OnNodeStart` 分工:常规 `hub` / `linear` / `content` 仍靠节点进入自动存;`<>` 用于即将进入无对话 / Fix 交互等 `OnNodeStart` 覆盖不到的边界。 +- 与 `OnNodeStart` 分工:常规 `hub` / `linear` / `content` 仍靠节点进入自动存;`interaction` / `save_on_exit` 用于即将进入无对话 / Fix 交互等边界。 ### P3 自动档边界(含 detour 去重) @@ -53,7 +63,7 @@ Yarn 脚本: 1. 全局门控:`IsRestoring` / `IsAutoSaveSuppressed` / `GameManager.pause` 2. **Fresh vs detour 续跑**:同一 `YarnProject` 下,若节点名已在 `InProgressNodes`(尚未 `onNodeComplete`)→ `DetourResume`,**不自动存**(避免 detour 返回父节点时重复写盘) -3. 将节点加入 `InProgressNodes`,再走 tag / `no_save` 白黑名单(`hub` / `linear` / `content` 允许;`detour` / `function` 等禁止) +3. 将节点加入 `InProgressNodes`,再解析 `NodeSavePolicy`:`hub` / `linear` / `content` 进入时保存;`interaction` / `save_on_exit` 在 Dialogue 正常结束时保存 state-only 档;`detour` / `function` 等默认禁止 `OnNodeComplete` 将节点移出 `InProgressNodes`。`StartDialog` / `LoadDialog` 切换 `YarnProject.name` 时、`StopDialog` 时重置集合。读档重进 anchor 走 `OnRestoreEnterNode`(只标记 InProgress,不写盘)。 @@ -210,7 +220,7 @@ Fix 场景各 State 的 `Enter()` 通常包含相机过渡、Timeline 播放、F | 阶段 | 内容 | | --- | --- | | P2 | 基础版已落地:槽位、原子写、meta sidecar、缩略图、latest_slot、P1 测试档迁移;正式 UI 接入仍属 P6 | -| P3 | 基础版已落地:`onNodeStart` 判定、tag 白/黑名单、`no_save`、读档/暂停门控、**detour 返回 InProgress 去重**;`<>` 显式存档(`CanExplicitSave`、omit anchor)已落地 | +| P3 | 基础版已落地:`onNodeStart` 判定、tag 白/黑名单、`no_save`、读档/暂停门控、**detour 返回 InProgress 去重**;`<>` 显式 StateOnly 存档已落地 | | P4 | 基础版已落地:Provider sync/async 契约、Phase + Barrier 编排、读档自动存档抑制、Timeline Addressable 可等待恢复、验证窗口读档入口 | | P5 | 维修子模块 section 扩展(BlockPuzzle / Memory / Cutting 等待新增 Provider) | | P6 | 正式存 / 读档 UI、继续游戏、新游戏覆盖自动档、游戏中读档确认等玩家流程 | diff --git a/Assets/Scripts/SaveSystem/SavePointEvaluator.cs b/Assets/Scripts/SaveSystem/SavePointEvaluator.cs index ad92ac6ef..a5ce1df15 100644 --- a/Assets/Scripts/SaveSystem/SavePointEvaluator.cs +++ b/Assets/Scripts/SaveSystem/SavePointEvaluator.cs @@ -1,9 +1,44 @@ using System; using System.Collections.Generic; +using System.Linq; using UnityEngine; namespace AibisDream.SaveSystem { + public enum NodeSaveTiming + { + None, + NodeEnter, + DialogueExit + } + + public enum SaveResumeMode + { + RestartNode, + StateOnly + } + + public readonly struct NodeSavePolicy + { + public NodeSaveTiming Timing { get; } + public SaveResumeMode ResumeMode { get; } + + public NodeSavePolicy(NodeSaveTiming timing, SaveResumeMode resumeMode) + { + Timing = timing; + ResumeMode = resumeMode; + } + + public static NodeSavePolicy None => + new(NodeSaveTiming.None, SaveResumeMode.RestartNode); + + public static NodeSavePolicy Enter => + new(NodeSaveTiming.NodeEnter, SaveResumeMode.RestartNode); + + public static NodeSavePolicy Exit => + new(NodeSaveTiming.DialogueExit, SaveResumeMode.StateOnly); + } + /// /// 可存点被拒绝的原因,供日志与 UI 提示使用。 /// @@ -28,6 +63,9 @@ namespace AibisDream.SaveSystem /// 同一节点仍在执行中(detour 返回续跑),非 Fresh 进入。 DetourResume, + + /// 节点类型或保存附加标记互相冲突。 + InvalidTagConfiguration, } /// @@ -35,8 +73,9 @@ namespace AibisDream.SaveSystem /// /// 基于 Yarn 节点 tag 判定是否允许自动存档: /// - 白名单 tag(hub / linear / content)默认允许; + /// - interaction 或 save_on_exit 在 Dialogue 正常结束时保存 state-only 档; /// - 黑名单 tag(start / init / function / detour / center / performance / event / end)默认禁止; - /// - no_save 附加标记覆盖默认语义,一律禁止; + /// - no_save 附加标记覆盖默认语义;与退出保存语义并存时视为配置冲突; /// - 无活跃节点、或节点未声明 tag,默认允许并打 warning; /// - 未知 tag 默认允许并打 warning。 /// @@ -68,6 +107,13 @@ namespace AibisDream.SaveSystem "end", // 维修结束/收尾 }; + private static readonly HashSet PrimaryNodeTags = new( + AutoSaveAllowedTags.Concat(AutoSaveDeniedTags), + StringComparer.OrdinalIgnoreCase) + { + "interaction", + }; + private static string _activeProjectId; private static readonly HashSet InProgressNodes = new(StringComparer.Ordinal); @@ -113,6 +159,27 @@ namespace AibisDream.SaveSystem IReadOnlyList tags, out SavePointRejectReason reason) { + var accepted = OnNodeStartForSavePolicy( + projectId, + nodeName, + tags, + out var policy, + out reason); + return accepted && policy.Timing == NodeSaveTiming.NodeEnter; + } + + /// + /// OnNodeStart 存档策略判定:Fresh 进入时返回节点的进入/退出保存策略; + /// detour 返回续跑或全局门控失败时返回 false。 + /// + public static bool OnNodeStartForSavePolicy( + string projectId, + string nodeName, + IReadOnlyList tags, + out NodeSavePolicy policy, + out SavePointRejectReason reason) + { + policy = NodeSavePolicy.None; if (!TryPassGlobalSaveGuards(out reason)) { return false; @@ -131,7 +198,8 @@ namespace AibisDream.SaveSystem InProgressNodes.Add(nodeName); } - return EvaluateTagsForAutoSave(nodeName, tags, out reason); + policy = ResolveNodePolicy(nodeName, tags, out reason); + return policy.Timing != NodeSaveTiming.None; } /// 仅 tag / no_save 判定,不含 InProgress detour 门控(供编辑器模拟)。 @@ -140,7 +208,8 @@ namespace AibisDream.SaveSystem IReadOnlyList tags, out SavePointRejectReason reason) { - return EvaluateTagsForAutoSave(nodeName, tags, out reason, logWarnings: true); + return ResolveNodePolicy(nodeName, tags, out reason, logWarnings: true).Timing + == NodeSaveTiming.NodeEnter; } #if UNITY_EDITOR || DEVELOPMENT_BUILD @@ -150,10 +219,111 @@ namespace AibisDream.SaveSystem IReadOnlyList tags, out SavePointRejectReason reason) { - return EvaluateTagsForAutoSave(nodeName, tags, out reason, logWarnings: false); + return ResolveNodePolicy(nodeName, tags, out reason, logWarnings: false).Timing + == NodeSaveTiming.NodeEnter; } #endif + /// 仅根据节点 tags 解析保存策略,不检查全局门控或 detour 状态。 + public static NodeSavePolicy ResolveNodePolicy( + string nodeName, + IReadOnlyList tags, + out SavePointRejectReason reason, + bool logWarnings = true) + { + var hasNoSave = IsTagPresent(tags, "no_save"); + var hasSaveOnExit = IsTagPresent(tags, "save_on_exit"); + var primaryTags = FindPrimaryTags(tags); + var hasInteraction = primaryTags.Exists( + tag => string.Equals(tag, "interaction", StringComparison.OrdinalIgnoreCase)); + + if (primaryTags.Count > 1) + { + if (logWarnings) + { + Debug.LogError( + $"[SavePointEvaluator] 节点 {FormatNodeName(nodeName)} 声明了多个一级类型: " + + $"[{string.Join(", ", primaryTags)}]。为避免错误存档,已禁用该节点存档。"); + } + + reason = SavePointRejectReason.InvalidTagConfiguration; + return NodeSavePolicy.None; + } + + if (hasNoSave && (hasInteraction || hasSaveOnExit)) + { + if (logWarnings) + { + Debug.LogError( + $"[SavePointEvaluator] 节点 {FormatNodeName(nodeName)} 的 no_save 与 " + + $"{(hasInteraction ? "interaction" : "save_on_exit")} 冲突,已禁用该节点存档。"); + } + + reason = SavePointRejectReason.InvalidTagConfiguration; + return NodeSavePolicy.None; + } + + if (hasNoSave) + { + reason = SavePointRejectReason.MarkedNoSave; + return NodeSavePolicy.None; + } + + if (hasInteraction) + { + if (hasSaveOnExit && logWarnings) + { + Debug.LogWarning( + $"[SavePointEvaluator] 节点 {FormatNodeName(nodeName)} 的 interaction 已包含 " + + "save_on_exit 语义,无需重复标记。"); + } + + reason = SavePointRejectReason.None; + return NodeSavePolicy.Exit; + } + + if (hasSaveOnExit) + { + reason = SavePointRejectReason.None; + return NodeSavePolicy.Exit; + } + + if (string.IsNullOrEmpty(nodeName) || tags == null || tags.Count == 0) + { + if (logWarnings && !string.IsNullOrEmpty(nodeName) && (tags == null || tags.Count == 0)) + { + Debug.LogWarning( + $"[SavePointEvaluator] 节点 {nodeName} 未声明任何 tag,默认允许进入时自动存档。请补全节点类型标签。"); + } + + reason = SavePointRejectReason.None; + return NodeSavePolicy.Enter; + } + + var primaryTag = primaryTags.Count == 1 ? primaryTags[0] : null; + if (primaryTag == null) + { + if (logWarnings) + { + Debug.LogWarning( + $"[SavePointEvaluator] 节点 {nodeName} 的 tags [{string.Join(", ", tags)}] " + + "未声明保存语义,默认允许进入时自动存档。"); + } + + reason = SavePointRejectReason.None; + return NodeSavePolicy.Enter; + } + + if (AutoSaveDeniedTags.Contains(primaryTag)) + { + reason = SavePointRejectReason.DeniedByTag; + return NodeSavePolicy.None; + } + + reason = SavePointRejectReason.None; + return NodeSavePolicy.Enter; + } + /// 节点执行完毕,移出 InProgress。 public static void OnNodeComplete(string projectId, string nodeName) { @@ -195,7 +365,7 @@ namespace AibisDream.SaveSystem ? DialogController.Instance.GetCurrentNodeContext() : (null, null); - return EvaluateTagsForAutoSave(nodeName, tags, out reason); + return ResolveNodePolicy(nodeName, tags, out reason).Timing == NodeSaveTiming.NodeEnter; } /// @@ -251,71 +421,13 @@ namespace AibisDream.SaveSystem return true; } - private static bool EvaluateTagsForAutoSave( - string nodeName, - IReadOnlyList tags, - out SavePointRejectReason reason, - bool logWarnings = true) - { - if (tags != null && IsTagPresent(tags, "no_save")) - { - reason = SavePointRejectReason.MarkedNoSave; - return false; - } - - if (string.IsNullOrEmpty(nodeName) || tags == null || tags.Count == 0) - { - if (logWarnings && !string.IsNullOrEmpty(nodeName) && (tags == null || tags.Count == 0)) - { - Debug.LogWarning( - $"[SavePointEvaluator] 节点 {nodeName} 未声明任何 tag,默认允许自动存档。请补全节点类型标签。"); - } - - reason = SavePointRejectReason.None; - return true; - } - - var primaryTag = FindPrimaryTag(tags); - - if (primaryTag == null) - { - if (logWarnings) - { - Debug.LogWarning( - $"[SavePointEvaluator] 节点 {nodeName} 的 tags [{string.Join(", ", tags)}] 未声明保存语义,默认允许自动存档。"); - } - reason = SavePointRejectReason.None; - return true; - } - - if (AutoSaveDeniedTags.Contains(primaryTag)) - { - reason = SavePointRejectReason.DeniedByTag; - return false; - } - - if (AutoSaveAllowedTags.Contains(primaryTag)) - { - reason = SavePointRejectReason.None; - return true; - } - - if (logWarnings) - { - Debug.LogWarning( - $"[SavePointEvaluator] 节点 {nodeName} 的 tag '{primaryTag}' 未声明保存语义,默认允许自动存档。"); - } - reason = SavePointRejectReason.None; - return true; - } - private static bool IsTagPresent(IReadOnlyList tags, string tag) { if (tags == null) return false; foreach (var t in tags) { - if (t == tag) + if (string.Equals(t, tag, StringComparison.OrdinalIgnoreCase)) { return true; } @@ -324,17 +436,29 @@ namespace AibisDream.SaveSystem return false; } - private static string FindPrimaryTag(IReadOnlyList tags) + private static List FindPrimaryTags(IReadOnlyList tags) { + var result = new List(); + if (tags == null) + { + return result; + } + foreach (var tag in tags) { - if (AutoSaveAllowedTags.Contains(tag) || AutoSaveDeniedTags.Contains(tag)) + if (PrimaryNodeTags.Contains(tag) + && !result.Exists(item => string.Equals(item, tag, StringComparison.OrdinalIgnoreCase))) { - return tag; + result.Add(tag); } } - return null; + return result; + } + + private static string FormatNodeName(string nodeName) + { + return string.IsNullOrEmpty(nodeName) ? "(无节点)" : nodeName; } } } diff --git a/Assets/Scripts/SaveSystem/SaveRestoreOrchestrator.cs b/Assets/Scripts/SaveSystem/SaveRestoreOrchestrator.cs index cfeeb83a8..f6bc4ac4d 100644 --- a/Assets/Scripts/SaveSystem/SaveRestoreOrchestrator.cs +++ b/Assets/Scripts/SaveSystem/SaveRestoreOrchestrator.cs @@ -8,6 +8,164 @@ using UnityEngine; namespace AibisDream.SaveSystem { + internal enum SaveTrigger + { + NodeEnter, + DialogueExit, + ExplicitCommand + } + + internal readonly struct SaveRequest + { + public SaveTrigger Trigger { get; } + public SaveResumeMode ResumeMode { get; } + public string SourceNodeName { get; } + public string YarnProjectId { get; } + public string TalkSceneId { get; } + public long DialogueRunId { get; } + public long FlowRevision { get; } + + public SaveRequest( + SaveTrigger trigger, + SaveResumeMode resumeMode, + string sourceNodeName, + string yarnProjectId, + string talkSceneId, + long dialogueRunId, + long flowRevision) + { + Trigger = trigger; + ResumeMode = resumeMode; + SourceNodeName = sourceNodeName; + YarnProjectId = yarnProjectId; + TalkSceneId = talkSceneId; + DialogueRunId = dialogueRunId; + FlowRevision = flowRevision; + } + + public AnchorCaptureSpec AnchorSpec => new( + TalkSceneId, + YarnProjectId, + SourceNodeName, + ResumeMode == SaveResumeMode.RestartNode); + + public static SaveRequest NodeEnter( + string nodeName, + string yarnProjectId, + string talkSceneId, + long dialogueRunId, + long flowRevision) + { + return new SaveRequest( + SaveTrigger.NodeEnter, + SaveResumeMode.RestartNode, + nodeName, + yarnProjectId, + talkSceneId, + dialogueRunId, + flowRevision); + } + + public static SaveRequest DialogueExit( + string nodeName, + string yarnProjectId, + string talkSceneId, + long dialogueRunId, + long flowRevision) + { + return new SaveRequest( + SaveTrigger.DialogueExit, + SaveResumeMode.StateOnly, + nodeName, + yarnProjectId, + talkSceneId, + dialogueRunId, + flowRevision); + } + + public static SaveRequest Explicit( + string nodeName, + string yarnProjectId, + string talkSceneId, + long dialogueRunId, + long flowRevision) + { + return new SaveRequest( + SaveTrigger.ExplicitCommand, + SaveResumeMode.StateOnly, + nodeName, + yarnProjectId, + talkSceneId, + dialogueRunId, + flowRevision); + } + } + + internal readonly struct SerialTaskQueueEntry + { + public long Sequence { get; } + public Task Completion { get; } + + public SerialTaskQueueEntry(long sequence, Task completion) + { + Sequence = sequence; + Completion = completion; + } + } + + /// 按请求顺序串行执行异步任务;前一个任务失败不会阻断后续任务。 + internal sealed class SerialTaskQueue + { + private readonly object _gate = new(); + private Task _tail = Task.CompletedTask; + private long _nextSequence; + private int _pendingCount; + + public int PendingCount + { + get + { + lock (_gate) + { + return _pendingCount; + } + } + } + + public SerialTaskQueueEntry Enqueue(Func operation) + { + if (operation == null) + { + throw new ArgumentNullException(nameof(operation)); + } + + long sequence; + Task completion; + lock (_gate) + { + sequence = ++_nextSequence; + _pendingCount++; + completion = _tail.ContinueWith( + _ => operation(), + TaskScheduler.Default) + .Unwrap(); + _tail = completion; + } + + _ = completion.ContinueWith( + _ => + { + lock (_gate) + { + _pendingCount = Math.Max(0, _pendingCount - 1); + } + }, + TaskScheduler.Default); + + return new SerialTaskQueueEntry(sequence, completion); + } + } + /// /// 存读档流程编排层:连接 UI、 与槽位系统。 /// @@ -20,13 +178,24 @@ namespace AibisDream.SaveSystem public static bool IsAutoSaveSuppressed => _autoSaveSuppressDepth > 0; /// 是否正在异步捕获或写入自动档;供只读诊断 UI 使用。 - public static bool IsSaving => _isAutoSaving; + public static bool IsSaving + { + get + { + lock (SaveQueueGate) + { + return _activeCaptureCount > 0 || SaveWriteQueue.PendingCount > 0; + } + } + } public static IReadOnlyList LastRestoreLog => _lastRestoreLog; - private static bool _isAutoSaving; private static int _autoSaveSuppressDepth; private static readonly List _lastRestoreLog = new(); + private static readonly object SaveQueueGate = new(); + private static readonly SerialTaskQueue SaveWriteQueue = new(); + private static int _activeCaptureCount; /// 启动自动存档协程(手动/调试入口)。 public static void TryAutoSave() @@ -43,30 +212,74 @@ namespace AibisDream.SaveSystem return; } - var (triggerNodeName, _) = DialogController.Instance.GetCurrentNodeContext(); - DialogController.Instance.StartCoroutine(AutoSaveRoutine(triggerNodeName)); + var dialog = DialogController.Instance; + var (triggerNodeName, _) = dialog.GetCurrentNodeContext(); + dialog.StartCoroutine( + SaveRoutine(SaveRequest.NodeEnter( + triggerNodeName, + dialog.DialogueRunner?.YarnProject?.name, + GetCurrentTalkSceneId(), + dialog.DialogueRunId, + dialog.DialogueFlowVersion))); } /// 自动存档协程:settle 一帧 → 主线程 Capture → 后台序列化写盘(不阻塞主线程)。 - /// ;显式 save 传 null。 - /// 为 true 时不写入 Yarn 节点 anchor。 - public static IEnumerator AutoSaveRoutine(string triggerNodeName = null, bool omitAnchor = false) + public static IEnumerator AutoSaveRoutine( + string triggerNodeName, + string yarnProjectId, + string talkSceneId, + long dialogueRunId, + long flowRevision) { - if (_isAutoSaving) - { - Debug.LogWarning("[SaveRestoreOrchestrator] 存档进行中,跳过重复请求。"); - yield break; - } + yield return SaveRoutine(SaveRequest.NodeEnter( + triggerNodeName, + yarnProjectId, + talkSceneId, + dialogueRunId, + flowRevision)); + } + internal static IEnumerator DialogueExitSaveRoutine( + string sourceNodeName, + string yarnProjectId, + string talkSceneId, + long dialogueRunId, + long flowRevision) + { + yield return SaveRoutine(SaveRequest.DialogueExit( + sourceNodeName, + yarnProjectId, + talkSceneId, + dialogueRunId, + flowRevision)); + } + + private static IEnumerator SaveRoutine(SaveRequest request) + { yield return null; - if (_isAutoSaving) + if (!ValidateSaveRequest(request, out var invalidReason)) { - Debug.LogWarning("[SaveRestoreOrchestrator] 存档进行中,跳过重复请求。"); + Debug.LogWarning( + $"[SaveRestoreOrchestrator] 取消失效存档请求: trigger={request.Trigger}, " + + $"node={FormatNodeName(request.SourceNodeName)}, project={request.YarnProjectId ?? "(none)"}, " + + $"talkScene={request.TalkSceneId ?? "(none)"}, reason={invalidReason}"); yield break; } - _isAutoSaving = true; + if (!SavePointEvaluator.CanExplicitSave(out var guardReason)) + { + Debug.LogWarning( + $"[SaveRestoreOrchestrator] 取消存档请求: trigger={request.Trigger}, " + + $"node={FormatNodeName(request.SourceNodeName)}, reason={guardReason}"); + yield break; + } + + lock (SaveQueueGate) + { + _activeCaptureCount++; + } + var infoPanel = UIManager.Instance.GetPanel(); infoPanel?.ShowSaveLoading(); @@ -77,66 +290,213 @@ namespace AibisDream.SaveSystem { using (new CodeTimer("SaveSnapshot")) { - snapshot = SnapshotService.Capture(triggerNodeName, omitAnchor); + snapshot = SnapshotService.Capture(request.AnchorSpec); thumbnail = SlotThumbnailCapture.CapturePng(); } } catch (Exception ex) { - Debug.LogError($"[SaveRestoreOrchestrator] 自动存档 Capture 失败: {ex}"); + Debug.LogError( + $"[SaveRestoreOrchestrator] 自动存档 Capture 失败: trigger={request.Trigger}, " + + $"node={FormatNodeName(request.SourceNodeName)}, error={ex}"); infoPanel?.HideSaveLoading(); - _isAutoSaving = false; + lock (SaveQueueGate) + { + _activeCaptureCount = Math.Max(0, _activeCaptureCount - 1); + } yield break; } infoPanel?.HideSaveLoading(); + lock (SaveQueueGate) + { + _activeCaptureCount = Math.Max(0, _activeCaptureCount - 1); + } #if UNITY_EDITOR || DEVELOPMENT_BUILD TestSaveRecordRequest testSaveRequest = null; - if (!omitAnchor) + try { - try - { - testSaveRequest = TestSaveRecorder.CreateRequest(snapshot, thumbnail); - } - catch (Exception ex) - { - Debug.LogError($"[SaveRestoreOrchestrator] 创建测试存档旁路请求失败,不影响正式存档:{ex}"); - } + testSaveRequest = TestSaveRecorder.CreateRequest( + snapshot, + thumbnail, + request.Trigger.ToString(), + request.ResumeMode.ToString()); + } + catch (Exception ex) + { + Debug.LogError($"[SaveRestoreOrchestrator] 创建测试存档旁路请求失败,不影响正式存档:{ex}"); } #endif - _ = SlotManager.SaveToAutoSlotAsync(snapshot, thumbnail).ContinueWith( + var sequence = EnqueueWrite( + snapshot, + thumbnail, + request +#if UNITY_EDITOR || DEVELOPMENT_BUILD + , testSaveRequest +#endif + ); + + if (request.ResumeMode == SaveResumeMode.StateOnly) + { + Debug.Log( + $"[SaveRestoreOrchestrator] 已捕获 state-only 自动档并加入写盘队列: " + + $"sequence={sequence}, trigger={request.Trigger}, node={FormatNodeName(request.SourceNodeName)}"); + } + } + + /// + /// Yarn <<save>> 显式存档:保留来源节点,但恢复时不启动 Yarn。 + /// + public static IEnumerator ExplicitSaveRoutine() + { + var dialog = DialogController.Instance; + var (nodeName, _) = dialog != null + ? dialog.GetCurrentNodeContext() + : (null, null); + var projectId = dialog?.DialogueRunner?.YarnProject?.name; + yield return SaveRoutine(SaveRequest.Explicit( + nodeName, + projectId, + GetCurrentTalkSceneId(), + dialog?.DialogueRunId ?? 0, + dialog?.DialogueFlowVersion ?? 0)); + } + + private static long EnqueueWrite( + SaveSnapshot snapshot, + byte[] thumbnail, + SaveRequest request +#if UNITY_EDITOR || DEVELOPMENT_BUILD + , TestSaveRecordRequest testSaveRequest +#endif + ) + { + var queueEntry = SaveWriteQueue.Enqueue( + () => SlotManager.SaveToAutoSlotAsync(snapshot, thumbnail)); + var sequence = queueEntry.Sequence; + var queuedTask = queueEntry.Completion; + + _ = queuedTask.ContinueWith( writeTask => { if (writeTask.IsFaulted) { Debug.LogError( - $"[SaveRestoreOrchestrator] 自动存档写盘失败: {writeTask.Exception?.GetBaseException()}"); + $"[SaveRestoreOrchestrator] 自动存档写盘失败: sequence={sequence}, " + + $"trigger={request.Trigger}, node={FormatNodeName(request.SourceNodeName)}, " + + $"error={writeTask.Exception?.GetBaseException()}"); + } + else if (writeTask.IsCanceled) + { + Debug.LogWarning( + $"[SaveRestoreOrchestrator] 自动存档写盘已取消: sequence={sequence}, " + + $"trigger={request.Trigger}, node={FormatNodeName(request.SourceNodeName)}"); } #if UNITY_EDITOR || DEVELOPMENT_BUILD - else if (!writeTask.IsCanceled) + else { TestSaveRecorder.Enqueue(testSaveRequest); } #endif - - _isAutoSaving = false; }, - TaskContinuationOptions.ExecuteSynchronously); + TaskScheduler.Default); - if (omitAnchor || (snapshot?.anchor != null && string.IsNullOrEmpty(snapshot.anchor.nodeName))) - { - Debug.Log("[SaveRestoreOrchestrator] 已保存无 Yarn 节点 anchor 的状态。"); - } + return sequence; } - /// - /// Yarn <<save>> 显式存档:默认 omit anchor,调用方需已通过 。 - /// - public static IEnumerator ExplicitSaveRoutine() + private static bool ValidateSaveRequest(SaveRequest request, out string reason) { - yield return AutoSaveRoutine(triggerNodeName: null, omitAnchor: true); + if (!request.AnchorSpec.IsComplete) + { + reason = "anchor identity is incomplete"; + return false; + } + + var dialog = DialogController.Instance; + var runner = dialog?.DialogueRunner; + if (dialog == null || runner == null) + { + reason = "DialogController or DialogueRunner is unavailable"; + return false; + } + + if (dialog.DialogueRunId != request.DialogueRunId) + { + reason = $"dialogue run changed ({request.DialogueRunId} -> {dialog.DialogueRunId})"; + return false; + } + + if (dialog.DialogueFlowVersion != request.FlowRevision) + { + reason = $"flow revision changed ({request.FlowRevision} -> {dialog.DialogueFlowVersion})"; + return false; + } + + if (!string.Equals(runner.YarnProject?.name, request.YarnProjectId, StringComparison.Ordinal)) + { + reason = $"YarnProject changed to {runner.YarnProject?.name ?? "(none)"}"; + return false; + } + + var currentTalkSceneId = GetCurrentTalkSceneId(); + if (!string.Equals(currentTalkSceneId, request.TalkSceneId, StringComparison.Ordinal)) + { + reason = $"TalkScene changed to {currentTalkSceneId ?? "(none)"}"; + return false; + } + + if (SceneLoader.Instance == null || SceneLoader.Instance.IsLoading) + { + reason = "scene is unavailable or loading"; + return false; + } + + var (currentNodeName, _) = dialog.GetCurrentNodeContext(); + if (request.Trigger == SaveTrigger.DialogueExit) + { + if (runner.IsDialogueRunning) + { + reason = "DialogueRunner is still running"; + return false; + } + + if (!string.IsNullOrEmpty(currentNodeName)) + { + reason = $"a current Yarn node is still present: {currentNodeName}"; + return false; + } + } + else + { + if (!runner.IsDialogueRunning) + { + reason = "DialogueRunner stopped before capture"; + return false; + } + + if (!string.Equals(currentNodeName, request.SourceNodeName, StringComparison.Ordinal)) + { + reason = $"current node changed to {currentNodeName ?? "(none)"}"; + return false; + } + } + + reason = null; + return true; + } + + private static string GetCurrentTalkSceneId() + { + return GameManager.Instance != null + ? GameManager.Session.CurrentTalkScene?.name + : null; + } + + private static string FormatNodeName(string nodeName) + { + return string.IsNullOrEmpty(nodeName) ? "(无节点)" : nodeName; } /// 将当前自动档复制到指定手动档。 @@ -321,6 +681,8 @@ namespace AibisDream.SaveSystem errors.Add("Snapshot TalkSceneSO is missing."); if (string.IsNullOrWhiteSpace(snapshot.anchor?.yarnProjectId)) errors.Add("Snapshot YarnProject is missing."); + if (string.IsNullOrWhiteSpace(snapshot.anchor?.nodeName)) + errors.Add("Snapshot Yarn node is missing."); } TalkSceneSO targetScene = null; @@ -341,7 +703,7 @@ namespace AibisDream.SaveSystem } if (errors.Count == 0 - && !string.IsNullOrWhiteSpace(snapshot.anchor.nodeName) + && snapshot.anchor.startDialogueOnRestore && !Array.Exists( targetScene.yarnProject.NodeNames, node => string.Equals(node, snapshot.anchor.nodeName, StringComparison.Ordinal))) @@ -413,8 +775,23 @@ namespace AibisDream.SaveSystem var runner = DialogController.Instance?.DialogueRunner; if (!string.Equals(runner?.YarnProject?.name, snapshot.anchor.yarnProjectId, StringComparison.Ordinal)) context.Error($"YarnProject mismatch: {runner?.YarnProject?.name ?? "none"}."); - if (!string.IsNullOrEmpty(snapshot.anchor.nodeName) && runner != null && !runner.IsDialogueRunning) - context.Error($"Yarn node did not start: {snapshot.anchor.nodeName}."); + if (snapshot.anchor.startDialogueOnRestore) + { + var (currentNodeName, _) = DialogController.Instance != null + ? DialogController.Instance.GetCurrentNodeContext() + : (null, null); + if (runner == null || !runner.IsDialogueRunning) + context.Error($"Yarn node did not start: {snapshot.anchor.nodeName}."); + else if (!string.Equals(currentNodeName, snapshot.anchor.nodeName, StringComparison.Ordinal)) + context.Error( + $"Yarn node mismatch: expected {snapshot.anchor.nodeName}, " + + $"actual {currentNodeName ?? "none"}."); + } + else if (runner != null && runner.IsDialogueRunning) + { + context.Error( + $"StateOnly restore unexpectedly started Yarn node {snapshot.anchor.nodeName}."); + } if (snapshot.sections != null && snapshot.sections.ContainsKey(SnapshotProviderIds.Fix) diff --git a/Assets/Scripts/SaveSystem/SaveSnapshot.cs b/Assets/Scripts/SaveSystem/SaveSnapshot.cs index 7e9f7d46b..92dcb1299 100644 --- a/Assets/Scripts/SaveSystem/SaveSnapshot.cs +++ b/Assets/Scripts/SaveSystem/SaveSnapshot.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using AibisDream.FixSystem; +using Newtonsoft.Json; namespace AibisDream.SaveSystem { @@ -38,7 +39,7 @@ namespace AibisDream.SaveSystem /// 当前场景(恢复的第一步)。 public SceneSnapshotDto scene = new(); - /// 恢复锚点:章节、YarnProject 与节点,读档最后阶段重新进入。 + /// 恢复锚点:章节、YarnProject、来源节点与显式恢复动作。 public AnchorSnapshot anchor = new(); /// 全部 Yarn 运行时变量(来自 )。 @@ -52,7 +53,8 @@ namespace AibisDream.SaveSystem } /// - /// 恢复锚点:包含宏观章节信息,读档最后阶段加载对话工程并重新 StartDialogue。 + /// 恢复锚点:节点名始终记录存档来源;是否重新进入节点由 + /// 独立决定。 /// [Serializable] public class AnchorSnapshot @@ -61,6 +63,9 @@ namespace AibisDream.SaveSystem public string sceneSoName; public string yarnProjectId; public string nodeName; + + [JsonProperty(Required = Required.Always)] + public bool startDialogueOnRestore; } /// Yarn 变量三分组,与 Yarn Spinner 支持的类型一致。 diff --git a/Assets/Scripts/SaveSystem/SaveYarnCommand.cs b/Assets/Scripts/SaveSystem/SaveYarnCommand.cs index 87c3fcd71..3e73f3749 100644 --- a/Assets/Scripts/SaveSystem/SaveYarnCommand.cs +++ b/Assets/Scripts/SaveSystem/SaveYarnCommand.cs @@ -5,7 +5,7 @@ using Yarn.Unity; namespace AibisDream.SaveSystem { /// - /// Yarn 显式存档命令。在节点末尾、状态命令执行完毕且即将进入无对话阶段时使用。 + /// Yarn 显式存档兼容命令。新内容应使用 interaction 一级类型或 save_on_exit 附加标记。 /// public static class SaveYarnCommand { diff --git a/Assets/Scripts/SaveSystem/SlotManager.cs b/Assets/Scripts/SaveSystem/SlotManager.cs index 75b47b1ff..8eb05d140 100644 --- a/Assets/Scripts/SaveSystem/SlotManager.cs +++ b/Assets/Scripts/SaveSystem/SlotManager.cs @@ -255,6 +255,7 @@ namespace AibisDream.SaveSystem sceneSoName = summary.SceneSoName, yarnProjectId = summary.YarnProjectId, nodeName = snapshot.anchor?.nodeName, + startDialogueOnRestore = snapshot.anchor?.startDialogueOnRestore ?? false, schemaVersion = snapshot.schemaVersion, gameVersion = snapshot.gameVersion, thumbnailFile = $"{ConstRef.SaveThumbnailFileName}.png" diff --git a/Assets/Scripts/SaveSystem/SlotTypes.cs b/Assets/Scripts/SaveSystem/SlotTypes.cs index 1ee3e6521..b8ddef804 100644 --- a/Assets/Scripts/SaveSystem/SlotTypes.cs +++ b/Assets/Scripts/SaveSystem/SlotTypes.cs @@ -27,6 +27,7 @@ namespace AibisDream.SaveSystem public string sceneSoName; public string yarnProjectId; public string nodeName; + public bool startDialogueOnRestore; public int schemaVersion; public string gameVersion; public string thumbnailFile; diff --git a/Assets/Scripts/SaveSystem/SnapshotCapture.cs b/Assets/Scripts/SaveSystem/SnapshotCapture.cs index 65931e0dd..417990a68 100644 --- a/Assets/Scripts/SaveSystem/SnapshotCapture.cs +++ b/Assets/Scripts/SaveSystem/SnapshotCapture.cs @@ -1,9 +1,33 @@ using System; using UnityEngine; -using Yarn.Unity; namespace AibisDream.SaveSystem { + public readonly struct AnchorCaptureSpec + { + public string SceneSoName { get; } + public string YarnProjectId { get; } + public string NodeName { get; } + public bool StartDialogueOnRestore { get; } + + public AnchorCaptureSpec( + string sceneSoName, + string yarnProjectId, + string nodeName, + bool startDialogueOnRestore) + { + SceneSoName = sceneSoName; + YarnProjectId = yarnProjectId; + NodeName = nodeName; + StartDialogueOnRestore = startDialogueOnRestore; + } + + public bool IsComplete => + !string.IsNullOrWhiteSpace(SceneSoName) + && !string.IsNullOrWhiteSpace(YarnProjectId) + && !string.IsNullOrWhiteSpace(NodeName); + } + /// /// 从运行时组装 (纯内存,不写盘)。 /// @@ -14,18 +38,17 @@ namespace AibisDream.SaveSystem public static class SnapshotCapture { /// 捕获当前完整快照。调用前需已注册全部 provider。 - /// - /// 触发存档时的 Yarn 节点名(通常为 OnNodeStart 传入值)。 - /// 非 null 时作为 anchor,并与 Capture 时刻的当前节点比较;不一致时打 warning,不阻断写盘。 - /// - /// - /// 为 true 时写入空 (显式 <<save>> 默认行为)。 - /// public static SaveSnapshot Capture( YarnVariableStorage storage, - string triggerNodeName = null, - bool omitAnchor = false) + AnchorCaptureSpec anchorSpec) { + if (!anchorSpec.IsComplete) + { + throw new ArgumentException( + "Snapshot anchor requires TalkScene, YarnProject and node name.", + nameof(anchorSpec)); + } + SnapshotRegistry.ValidateRequiredProviders(); var snapshot = new SaveSnapshot @@ -35,7 +58,7 @@ namespace AibisDream.SaveSystem }; CaptureScene(snapshot); - CaptureAnchor(snapshot, triggerNodeName, omitAnchor); + CaptureAnchor(snapshot, anchorSpec); CaptureYarnVariables(storage, snapshot); foreach (var provider in SnapshotRegistry.GetOrderedProviders()) @@ -58,58 +81,17 @@ namespace AibisDream.SaveSystem }; } - private static void CaptureAnchor(SaveSnapshot snapshot, string triggerNodeName, bool omitAnchor) + private static void CaptureAnchor(SaveSnapshot snapshot, AnchorCaptureSpec anchorSpec) { - var dialog = DialogController.Instance; - if (dialog == null) return; - - string anchorNodeName; - if (omitAnchor) - { - anchorNodeName = string.Empty; - } - else - { - var (currentNodeName, _) = dialog.GetCurrentNodeContext(); - anchorNodeName = triggerNodeName ?? currentNodeName ?? string.Empty; - - if (triggerNodeName != null - && !string.Equals( - NormalizeNodeName(triggerNodeName), - NormalizeNodeName(currentNodeName), - StringComparison.Ordinal)) - { - Debug.LogWarning( - $"[SnapshotCapture] 存档锚点漂移:触发时「{FormatNodeName(triggerNodeName)}」," + - $"Capture 时「{FormatNodeName(currentNodeName)}」。anchor 使用触发节点。"); - } - } - - var yarnProject = dialog.DialogueRunner?.YarnProject; - var projectId = yarnProject != null ? yarnProject.name : string.Empty; - - var sceneSoName = GameManager.Instance != null - ? GameManager.Session.CurrentTalkScene?.name - : null; - snapshot.anchor = new AnchorSnapshot { - sceneSoName = sceneSoName, - yarnProjectId = projectId, - nodeName = anchorNodeName + sceneSoName = anchorSpec.SceneSoName, + yarnProjectId = anchorSpec.YarnProjectId, + nodeName = anchorSpec.NodeName, + startDialogueOnRestore = anchorSpec.StartDialogueOnRestore }; } - private static string NormalizeNodeName(string nodeName) - { - return string.IsNullOrEmpty(nodeName) ? string.Empty : nodeName; - } - - private static string FormatNodeName(string nodeName) - { - return string.IsNullOrEmpty(nodeName) ? "(无节点)" : nodeName; - } - private static void CaptureYarnVariables(YarnVariableStorage storage, SaveSnapshot snapshot) { var (floats, strings, bools) = storage.GetAllVariables(); diff --git a/Assets/Scripts/SaveSystem/SnapshotRestore.cs b/Assets/Scripts/SaveSystem/SnapshotRestore.cs index 8a6950ee9..5362dec77 100644 --- a/Assets/Scripts/SaveSystem/SnapshotRestore.cs +++ b/Assets/Scripts/SaveSystem/SnapshotRestore.cs @@ -40,7 +40,7 @@ namespace AibisDream.SaveSystem } /// - /// Phase 3:按 加载对话工程;若有节点名则重新进入 Yarn 节点。 + /// Phase 3:按 加载对话工程,并按显式恢复标记决定是否启动节点。 /// public static IEnumerator RestoreAnchor(SaveSnapshot snapshot, SnapshotRestoreContext context = null) { @@ -52,10 +52,10 @@ namespace AibisDream.SaveSystem context ??= new SnapshotRestoreContext(snapshot); - var hasNode = !string.IsNullOrEmpty(snapshot.anchor.nodeName); - context.SetPhase(hasNode + var shouldStartDialogue = snapshot.anchor.startDialogueOnRestore; + context.SetPhase(shouldStartDialogue ? $"Phase 3: Restore anchor {snapshot.anchor.nodeName}" - : "Phase 3: No anchor node, restore YarnProject only"); + : $"Phase 3: Restore YarnProject only (source {snapshot.anchor.nodeName})"); var dialog = DialogController.Instance; if (dialog == null) @@ -93,18 +93,28 @@ namespace AibisDream.SaveSystem } } - if (!hasNode) - { - yield break; - } - if (runner.IsDialogueRunning) { yield return runner.Stop(); } - if (runner.YarnProject == null - || !System.Array.Exists(runner.YarnProject.NodeNames, node => node == snapshot.anchor.nodeName)) + var nodeExists = runner.YarnProject != null + && System.Array.Exists( + runner.YarnProject.NodeNames, + node => node == snapshot.anchor.nodeName); + if (!shouldStartDialogue) + { + if (!nodeExists) + { + context.Warn( + $"StateOnly 来源节点 {snapshot.anchor.nodeName} 已不在 " + + $"YarnProject {runner.YarnProject?.name ?? "none"} 中;状态恢复继续。"); + } + + yield break; + } + + if (!nodeExists) { context.Error( $"YarnProject {runner.YarnProject?.name ?? "none"} 不包含节点 {snapshot.anchor.nodeName}。"); diff --git a/Assets/Scripts/SaveSystem/SnapshotService.cs b/Assets/Scripts/SaveSystem/SnapshotService.cs index 3c45a03ea..5e791f838 100644 --- a/Assets/Scripts/SaveSystem/SnapshotService.cs +++ b/Assets/Scripts/SaveSystem/SnapshotService.cs @@ -7,12 +7,10 @@ namespace AibisDream.SaveSystem public static class SnapshotService { /// 捕获当前运行时快照。 - /// 。 - /// 。 - public static SaveSnapshot Capture(string triggerNodeName = null, bool omitAnchor = false) + public static SaveSnapshot Capture(AnchorCaptureSpec anchorSpec) { SnapshotRegistry.EnsureInitialized(); - return SnapshotCapture.Capture(YarnVariableStorage.Instance, triggerNodeName, omitAnchor); + return SnapshotCapture.Capture(YarnVariableStorage.Instance, anchorSpec); } } diff --git a/Assets/Scripts/UI/Panel/DeveloperModePanel.cs b/Assets/Scripts/UI/Panel/DeveloperModePanel.cs index d10549f1b..f6809ebb8 100644 --- a/Assets/Scripts/UI/Panel/DeveloperModePanel.cs +++ b/Assets/Scripts/UI/Panel/DeveloperModePanel.cs @@ -731,16 +731,26 @@ namespace AibisDream.UI private static (string Label, Color Color, bool IsError) FormatTestSaveRow( TestSaveCoverageRow row) { + var resumeModeLabel = string.Equals( + row.ResumeMode, + nameof(SaveResumeMode.StateOnly), + StringComparison.Ordinal) + ? " [StateOnly]" + : string.Empty; + if (row.Kind == TestSaveCoverageRowKind.Missing) { - return ($"○ 缺失 {row.NodeName}", new Color(0.6f, 0.68f, 0.72f), false); + return ( + $"○ 缺失 {row.NodeName}{resumeModeLabel}", + new Color(0.6f, 0.68f, 0.72f), + false); } var entry = row.Entry; if (row.Kind == TestSaveCoverageRowKind.Invalid || entry == null || !entry.IsValid) { return ( - $"× 无效 {row.NodeName} | " + $"× 无效 {row.NodeName}{resumeModeLabel} | " + (entry?.IsValid == true ? "当前流程找不到对应章节/YarnProject。" : entry?.StatusMessage ?? "未知错误"), @@ -750,7 +760,8 @@ namespace AibisDream.UI var warning = entry.HasVersionWarning ? $" ⚠ game {entry.Meta.gameVersion}" : string.Empty; return ( - $"● {row.NodeName} | {entry.Meta.lastRecordedAt} | {entry.Meta.sceneName}{warning}", + $"● {row.NodeName}{resumeModeLabel} | " + + $"{entry.Meta.lastRecordedAt} | {entry.Meta.sceneName}{warning}", entry.HasVersionWarning ? new Color(1f, 0.82f, 0.35f) : Color.white, false); } diff --git a/Assets/Tests/FrameAnimation/EditMode/FrameAnimationImportTests.cs b/Assets/Tests/FrameAnimation/EditMode/FrameAnimationImportTests.cs index cfe7495bb..52671b638 100644 --- a/Assets/Tests/FrameAnimation/EditMode/FrameAnimationImportTests.cs +++ b/Assets/Tests/FrameAnimation/EditMode/FrameAnimationImportTests.cs @@ -11,22 +11,30 @@ namespace AibisDream.FrameAnimation.Tests.EditMode { public sealed class FrameAnimationImportTests { - private const string TestRoot = "Assets/Tests/FrameAnimation/GeneratedImportTests"; - private const string TexturePath = TestRoot + "/Atlas.png"; - private const string JsonPath = TestRoot + "/Atlas.json"; - private const string GraphPath = TestRoot + "/ImportGraph.asset"; + private string TestRoot { get; set; } + private string TexturePath => TestRoot + "/Atlas.png"; + private string JsonPath => TestRoot + "/Atlas.json"; + private string GraphPath => TestRoot + "/ImportGraph.asset"; [SetUp] public void SetUp() { - AssetDatabase.DeleteAsset(TestRoot); + TestRoot = + $"Assets/Tests/FrameAnimation/GeneratedImportTests_{Guid.NewGuid():N}"; EnsureFolder(TestRoot); } [TearDown] public void TearDown() { - AssetDatabase.DeleteAsset(TestRoot); + if (!string.IsNullOrEmpty(TestRoot)) + { + Assert.That( + AssetDatabase.DeleteAsset(TestRoot), + Is.True, + $"Failed to delete test asset folder: {TestRoot}"); + } + AssetDatabase.Refresh(); } @@ -329,7 +337,7 @@ namespace AibisDream.FrameAnimation.Tests.EditMode Assert.That(graph.Clips, Is.Empty); } - private static FrameAnimationGraph CreateWritableGraph(string json) + private FrameAnimationGraph CreateWritableGraph(string json) { CreateTexture(); WriteJson(json); @@ -347,7 +355,7 @@ namespace AibisDream.FrameAnimation.Tests.EditMode return graph; } - private static void CreateTexture() + private void CreateTexture() { var texture = new Texture2D(4, 2, TextureFormat.RGBA32, false); var pixels = Enumerable.Range(0, 8) @@ -360,7 +368,7 @@ namespace AibisDream.FrameAnimation.Tests.EditMode AssetDatabase.ImportAsset(TexturePath, ImportAssetOptions.ForceSynchronousImport); } - private static void WriteJson(string json) + private void WriteJson(string json) { File.WriteAllText(JsonPath, json, new UTF8Encoding(false)); AssetDatabase.ImportAsset(JsonPath, ImportAssetOptions.ForceSynchronousImport); diff --git a/Assets/Tests/FrameAnimation/GeneratedImportTests.meta b/Assets/Tests/FrameAnimation/GeneratedImportTests.meta new file mode 100644 index 000000000..612b5afa5 --- /dev/null +++ b/Assets/Tests/FrameAnimation/GeneratedImportTests.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ce717c358aef1574ab0edd4df45152e6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests/FrameAnimation/GeneratedImportTests/Atlas.png b/Assets/Tests/FrameAnimation/GeneratedImportTests/Atlas.png new file mode 100644 index 000000000..f7dfbac46 --- /dev/null +++ b/Assets/Tests/FrameAnimation/GeneratedImportTests/Atlas.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4104a521960d83c028d619b7cf9b4227c03a470455ef36578eb77737df0de13b +size 76 diff --git a/Assets/Tests/FrameAnimation/GeneratedImportTests/Atlas.png.meta b/Assets/Tests/FrameAnimation/GeneratedImportTests/Atlas.png.meta new file mode 100644 index 000000000..852e38d2a --- /dev/null +++ b/Assets/Tests/FrameAnimation/GeneratedImportTests/Atlas.png.meta @@ -0,0 +1,209 @@ +fileFormatVersion: 2 +guid: ad7135517a3e7d44fab0e319f21e484c +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 12 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 2 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: WebGL + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: + - serializedVersion: 2 + name: FrameA + rect: + serializedVersion: 2 + x: 0 + y: 0 + width: 2 + height: 2 + alignment: 9 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 3203ad1f5d9bbf94d8607def47ab8917 + internalID: -3259341585125249141 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: FrameB + rect: + serializedVersion: 2 + x: 2 + y: 0 + width: 2 + height: 2 + alignment: 9 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: e18a996baef906548b59c270239ac77d + internalID: 760278470 + vertices: [] + indices: + edges: [] + weights: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: + FrameA: -3259341585125249141 + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests/FrameAnimation/GeneratedImportTests/ImportGraph.asset b/Assets/Tests/FrameAnimation/GeneratedImportTests/ImportGraph.asset new file mode 100644 index 000000000..e0db2970b --- /dev/null +++ b/Assets/Tests/FrameAnimation/GeneratedImportTests/ImportGraph.asset @@ -0,0 +1,75 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-7417057855660477100 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 408fe45af4d321848a6c97f0356e8e5c, type: 3} + m_Name: SharedPair + m_EditorClassIdentifier: + id: SharedPair + displayName: SharedPair + frames: + - sprite: {fileID: -3259341585125249141, guid: ad7135517a3e7d44fab0e319f21e484c, type: 3} + durationMs: 100 + frameName: FrameA + sourceIndex: 0 + - sprite: {fileID: -3259341585125249141, guid: ad7135517a3e7d44fab0e319f21e484c, type: 3} + durationMs: 300 + frameName: FrameB + sourceIndex: 1 + speed: 1 + defaultEndBehavior: 0 + hasImportInfo: 1 + importInfo: + importSourceId: 52e497304ca9471c89e585f213e29f12 + sourceTagName: SharedPair + isMissingFromSource: 0 + hasStandaloneImportSource: 0 + standaloneImportSource: + texture: {fileID: 0} + asepriteJson: {fileID: 0} + pivot: {x: 0.5, y: 0.5} + manageSpriteSlicing: 0 + lastSourceHash: + lastImportedTagName: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4c9e0458642034545b44454bbadcf059, type: 3} + m_Name: ImportGraph + m_EditorClassIdentifier: + id: ImportGraph + displayName: Import Graph + clips: + - {fileID: -7417057855660477100} + nodes: [] + edges: [] + flows: [] + importSources: + - internalId: 52e497304ca9471c89e585f213e29f12 + displayName: "\u4E2D\u6587\u6765\u6E90" + isEnabled: 1 + texture: {fileID: 2800000, guid: ad7135517a3e7d44fab0e319f21e484c, type: 3} + asepriteJson: {fileID: 4900000, guid: eea7be1f48597614e8e13e85c42c8a42, type: 3} + pivot: {x: 0.5, y: 0.5} + manageSpriteSlicing: 1 + defaultNewClipEndBehavior: 0 + lastSourceHash: cc9e5035efe44f71c253579af48d546926f600feeb8719e30b9995e404c13077 + settings: + defaultPlayableId: + newManualClipDefaultEndBehavior: 0 + editorData: + nodeEditorData: [] + flowEditorData: [] diff --git a/Assets/Tests/FrameAnimation/GeneratedImportTests/ImportGraph.asset.meta b/Assets/Tests/FrameAnimation/GeneratedImportTests/ImportGraph.asset.meta new file mode 100644 index 000000000..d9425a12c --- /dev/null +++ b/Assets/Tests/FrameAnimation/GeneratedImportTests/ImportGraph.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c31fd505b342238419aa20e24f87671d +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Yarn/FP/FP_Huoshan1/Stage1.yarn b/Assets/Yarn/FP/FP_Huoshan1/Stage1.yarn index 448f3edc2..8355b849d 100644 --- a/Assets/Yarn/FP/FP_Huoshan1/Stage1.yarn +++ b/Assets/Yarn/FP/FP_Huoshan1/Stage1.yarn @@ -86,7 +86,7 @@ me: 停——停… #line:04dd0b5 me: 你来你老朋友这儿一惊一乍的,
就为了再坑它买你一顶帽子? #line:0a86bba <> -<> +<> <> // 火山委屈状 #line:0393572 @@ -123,7 +123,7 @@ hs: 但今天我要恭喜你。我为你带来了这款限定版多功能大头 me: 只能是视觉上么?…
不对,我头也不大啊。 #line:01dbe17 hs: 那还是没买这款多功能大头弱化器帽子的问题。 #line:0505062 -<> +<> <> <> hs: 只要你头顶戴帽儿了,烦恼就进套儿了,[[comma-pause]]
聪明的智商就又能上号儿了。 #line:04500c3 @@ -187,9 +187,9 @@ me: 除了谐音梗能玩点别的吗?而且这已经不搞笑了。
你这 // 火山被戳中痛处 //<> -<> +<> <> -<> +<> hs: 不——搞——笑?? #line:0101ec0 <> <> diff --git a/Assets/Yarn/FP/FP_Huoshan1/Stage5.yarn b/Assets/Yarn/FP/FP_Huoshan1/Stage5.yarn index 4aa137fc4..f011f3cfe 100644 --- a/Assets/Yarn/FP/FP_Huoshan1/Stage5.yarn +++ b/Assets/Yarn/FP/FP_Huoshan1/Stage5.yarn @@ -68,7 +68,7 @@ me: 英理没提前和你说它们会来吗? #line:06a5cae <> hs: 这就是好玩的部分啦。 #line:06a5caf -<> +<> <> hs: 英理也遇到麻烦了,最坏的情况是撤职。 #line:06a5cb0 diff --git a/Assets/Yarn/FP/FP_Peipei1/Stage2_外部检查&UF.yarn b/Assets/Yarn/FP/FP_Peipei1/Stage2_外部检查&UF.yarn index e97d3fea0..2a997e9db 100644 --- a/Assets/Yarn/FP/FP_Peipei1/Stage2_外部检查&UF.yarn +++ b/Assets/Yarn/FP/FP_Peipei1/Stage2_外部检查&UF.yarn @@ -1,5 +1,5 @@ title: Stage2 -tags: start +tags: interaction color: 888888 position: -427,-2903 --- @@ -14,7 +14,6 @@ dn: 系统已就绪。请使用插头进行检查。 <> <> Task: 定位佩佩的UF模块 #line:01dade5 -<> === title: UF深入检查 diff --git a/Assets/Yarn/FP/FP_Peipei1/Stage3_视觉检查.yarn b/Assets/Yarn/FP/FP_Peipei1/Stage3_视觉检查.yarn index 046aad704..772cdaccf 100644 --- a/Assets/Yarn/FP/FP_Peipei1/Stage3_视觉检查.yarn +++ b/Assets/Yarn/FP/FP_Peipei1/Stage3_视觉检查.yarn @@ -1,11 +1,10 @@ title: Stage3 -tags: start +tags: interaction colorID: 8 position: -542,-2771 --- <> -<> === title: FirstDialogue diff --git a/Assets/Yarn/FP/FP_Peipei1/Stage4_记忆检查.yarn b/Assets/Yarn/FP/FP_Peipei1/Stage4_记忆检查.yarn index 612cec4c0..997f851b1 100644 --- a/Assets/Yarn/FP/FP_Peipei1/Stage4_记忆检查.yarn +++ b/Assets/Yarn/FP/FP_Peipei1/Stage4_记忆检查.yarn @@ -64,7 +64,7 @@ position: -1198,-2353 title: End_memoryPaly -tags: content no_save +tags: interaction colorID: 3 group:记忆 position: -871,-2773 @@ -89,7 +89,6 @@ position: -871,-2773 <> <> -<> === diff --git a/Assets/Yarn/Refactor.meta b/Assets/Yarn/Refactor.meta new file mode 100644 index 000000000..9e8deee82 --- /dev/null +++ b/Assets/Yarn/Refactor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 53d5c9741f818a34bbac9a2f97b43c0e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Yarn/Refactor/FP_Day2_sleep.meta b/Assets/Yarn/Refactor/FP_Day2_sleep.meta new file mode 100644 index 000000000..56266145f --- /dev/null +++ b/Assets/Yarn/Refactor/FP_Day2_sleep.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 57d3d67dd6f81ac4f804504742aa3fa9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Yarn/Refactor/FP_Day2_sleep/FP_Day2_sleep.yarnproject b/Assets/Yarn/Refactor/FP_Day2_sleep/FP_Day2_sleep.yarnproject new file mode 100644 index 000000000..ed99bb63e --- /dev/null +++ b/Assets/Yarn/Refactor/FP_Day2_sleep/FP_Day2_sleep.yarnproject @@ -0,0 +1,12 @@ +{ + "projectFileVersion": 3, + "sourceFiles": [ + "*.yarn" + ], + "excludeFiles": [ + "**/*~/*" + ], + "localisation": {}, + "baseLanguage": "zh-Hans", + "compilerOptions": {} +} \ No newline at end of file diff --git a/Assets/Yarn/Refactor/FP_Day2_sleep/FP_Day2_sleep.yarnproject.meta b/Assets/Yarn/Refactor/FP_Day2_sleep/FP_Day2_sleep.yarnproject.meta new file mode 100644 index 000000000..afc24e560 --- /dev/null +++ b/Assets/Yarn/Refactor/FP_Day2_sleep/FP_Day2_sleep.yarnproject.meta @@ -0,0 +1,17 @@ +fileFormatVersion: 2 +guid: 0e7b7ff37c6b781438198162c0f0858d +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 053561912b1654d80a424bb0696a74ae, type: 3} + generateVariablesSourceFile: 0 + variablesClassName: YarnVariables + variablesClassNamespace: + variablesClassParent: Yarn.Unity.InMemoryVariableStorage + useAddressableAssets: 0 + unityLocalisationStringTableCollectionGUID: + UseUnityLocalisationSystem: 0 diff --git a/Assets/Yarn/Refactor/FP_Day2_sleep/FP_Day2_sleep_new.yarn b/Assets/Yarn/Refactor/FP_Day2_sleep/FP_Day2_sleep_new.yarn new file mode 100644 index 000000000..ce9bf291e --- /dev/null +++ b/Assets/Yarn/Refactor/FP_Day2_sleep/FP_Day2_sleep_new.yarn @@ -0,0 +1,1160 @@ +title: Start +tags: start +--- +<> +<> + +<> +=== + +title: 开场 +tags: linear +--- +数据溢出:未知来源的记忆… #auto_next #line:09952c6 + +VERIFYING…bool seaExists = false; waiting for input… #auto_next #line:05a8257 +<> +<> +mecd?: …抓紧… #line:0c8c60b +<> +<> +<> +=== + +title: 醒来 +tags: linear +--- +<> +mecd?: 抓紧! #line:02447ee +<> +<> +<> +你感到手上的什么东西传来的震动。骨碌碌…骨碌碌…… #line:06ac82f +骨碌碌…骨碌碌…… #line:04cf538 +<> +mecd?: 喂!你睡着啦! #line:087325f +->抓住 #line:079843f +一阵强烈的拉力,手里的东西差点脱手而出。 #line:0ac9cab +mecd: 快看!飞起来啦! #line:030481b +<> +天上什么东西正在发出猎猎的声音,像涨满的风帆的抖动声。 #line:0a832a0 +你向上看去。 #line:0718f75 +<> +<> +<> +天蓝蓝的,像一望无际的蓝色大海。
闪闪发亮,亮得有些睁不开眼。
#line:085e65a +<> +<> +=== + +// ---------------------------风筝1节点-------------------------------- + +title: 风筝1 +tags: hub +--- +<> +<> + <> +<> + <> +<> + <> +<> + <> +<> + <> +<> + +->放线 #line:08a1756 + <> +->收线<1>> #line:0b475d7 + <> +->保持<> #line:0930771 + <> + +<> +<> + <> +<> +<> +=== + +title: 风筝1_入场 +tags: detour +--- +一个小小的黑影在天上摆动着,时而向左时而向右。像一只自由自在的鸟儿,向天边飞去。 #line:07c785c +mecd: 喂!你怎么在愣神呀! #line:093133b +mecd: 该放线啦! #line:0beb13f +=== + +title: 风筝1_攥紧的手 +tags: detour +--- +哗啦……… #line:029246c +鸟儿抖动着,乘着风向上方爬去,越来越远,越来越远… #line:05cfc6c +它要去哪? #line:0e76ca4 +你的手不由自主地攥紧了。 #line:02bc000 +mecd: 会断的,该放松些啦! #line:0c0d82f +mecd: 一直拽紧的话,它会断掉的。 #line:0dfb7f1 +med: 它要飞走了…… #line:0db1f3d +mecd: 让它飞呀。它本来不就是要飞的嘛! #line:08a4dca +mecd: 放线啦! #line:0b9f8d5 +=== + +title: 风筝1_感受风 +tags: detour +--- +鸟儿轻轻地爬升着。 #line:0794c71 +它轻轻地滑翔着,像是一片自由的云。 #line:0bcd3b7 +med: …好高啊。 #line:082e87e +mecd: 还不够高,再高一些吧。 #line:0dc4f3a +med: 该…怎么做? #line:0670294 +mecd: 感受风呀。 #line:09baa1b +med: 感受…… #line:00c3149 +轻柔的风像是轻轻敲击了你的后颈。有什么东西从脑海深处浮了出来。 #line:0c0f678 +有人教你玩过这个游戏。 #line:0289237 +med: 风大就放线,风小就收线……对吧? #line:08c0f8a +你抬起头,仔细感受着手上的张力。 #line:0080d80 +风缓和了下来。带着它左右摇晃。
像嬉戏的孩子把玩着手里的玩具。
#line:049e26c +风缓和了下来。带着它左右摇晃。 #option_prompt +=== + +title: 风筝1_再高一些 +tags: detour +--- +mecd: 再高一些,很快就能听到了。 #line:067e750 +med: 听到什么? #line:0c16fdb +mecd: 一会你就知道了! #line:076cc56 +风慢慢大了起来,就像潮汐的涨落一样。 #line:0c9aefd +风慢慢大了起来,就像潮汐的涨落一样。#option_prompt +=== + +title: 风筝1_把它带走 +tags: detour +--- +mecd: 喂——! #line:078d8c9 +女孩对着天空喊着。声音被风带到很远很远的地方。 #line:026014d +mecd: 把它带走! #line:07ff984 +mecd: 喂——!你听见我了吗——! #line:0c291b8 +<> +鸟儿在空中抖动了起来。风变化着,线猛地绷成了一条直线。 #line:0d92e82 +<> +<> +<> +mecd: 不好…你听到了吗? +mecd: 它要离开了。 #line:0a272c4 +你竖起耳朵听。却只能听见自己砰砰的心跳声。 #line:0305025 +mecd: 带上它呀——!喂——! #line:04298ff +<> +<> +<> +<> +你听到一阵慌乱的风声,从你的耳畔打着回旋流过。 #line:07706aa +嘈杂的风声让你感到似乎无法呼吸。 +嘈杂的风声让你感到似乎无法呼吸。#option_prompt +=== + +title: 放线 +tags: detour +--- +<> +<> + 风把它吹得越来越高,越来越远。 #line:08924c7 +<> + 风筝在风中轻轻摇晃着。 #line:0a4c7dd +<> + 风筝摇摇晃晃地下落了一段高度。 #line:0da05be +<> +=== + +title: 收线 +tags: detour +--- +<> +<> + 风把它吹得更远,也更低了。 #line:08bb573 +<> + 风筝在风中轻轻摇晃着。 #line:00e3d64 +<> + 风筝在空中扑地抖了一下,又向高处爬了一截。 #line:08ef2fa +<> +=== + +title: 保持 +tags: detour +--- +<> +<> + 风筝线绷得笔直,像是要断掉。 #line:01a36f8 +<> + 风筝在风中轻轻摇晃。 #line:0d2c8bb +<> + 风筝线轻轻地垂下来,形成一个更大的弧度。 #line:067c8b7 +<> +=== + +title: 风筝落地 +tags: linear +--- +<> +<> +手上的线忽然一轻。风弱了下来,变得完全没有了。 #line:064cfbd +风离开了。它没有追上风。 +mecd: 为什么呢。 #line:02a0d93 +<> +mecd: 飞得这么高… #line:0210829 +<> +mecd: 还是落回来了啊。 #line:0a5c874 +轻飘飘地… #line:03fd2e2 +风筝飘向了一棵大树。 #line:092e57b +<> +<> +=== + +title: 广场 +tags: hub +--- +<> +<> +<> +<> + <> +<> + +->观察 #line:0a621b6 + ->秋千 #line:06c60e9 + <> + <> + ->眺望 #line:0446667 + <> + <> + ->树<> #line:02f1319 + <> + ->抬头 #line:000b785 + <> + <> + ->返回 #line:022c2ac + <> +->女孩<> #line:04543d0 + <> + ->放线 #line:06d26de + <> + <> +->离开 #line:086b2fa + <> + <> +=== + +title: 广场_入场 +tags: detour +--- +<> + 空荡荡的游乐广场,树梢无精打采地,搅拌着沉闷的空气。女孩正尝试踮脚够着挂在树上的风筝。 #line:007bce1 +<> + 空荡荡的游乐广场,风轻拂着树梢。一个扎着马尾辫的小女孩坐在长椅上。 #line:0e54b9c +<> + 空荡荡的游乐广场,风很大,卷得树沙沙作响。 #line:06583cd +<> +=== + +title: 广场_又回来了 +tags: detour +--- +med: 又回来了…我就知道。 #line:024d30a +<> +=== + +title: 广场_秋千 +tags: detour +--- +<> +->坐 #line:002a7a1 + 你坐在上面,抬起双腿,轻轻地摇摆。秋千发出吱呀呀的声音。 #line:02afab6 + 你的屁股被挤得疼。这不是为你这么大的体型设计的。 #line:049b550 +->返回 #line:0f97ce4 +=== + +title: 广场_眺望 +tags: detour +--- +<> +<> +<> +天蓝蓝的,像湖水一样,亮得让你睁不开眼。一阵闷热的风撞在你的脸上,带着令你窒息的咸腥味和海鸥的叫声。 #line:058ebb4 +=== + +title: 广场_树下 +tags: detour +--- +<> +树下站着一个扎着马尾辫的小女孩,她的手上拽着一条细线,细线的另一头通向树冠。 #line:0446e8b +=== + +title: 树 +tags: detour +--- +<> +<> + <> + 一片浅红色耷拉在树梢,无力地晃动着。 #line:07feba5 + mecd: 下来! #line:090b708 + 沙沙……
树叶纷纷飘落。
#line:0b09a4a + mecd: 总是这样…… #line:019fa29 + 你注意到一条缠绕在树枝上的线,伸手扯住了它。 #line:0593280 + mecd: 不,那样会把它系死在上面的。 #line:044efec + 女孩仰着脑袋,头也不回地说。她纵身一跃,够着了树梢的末端。 #line:09a8ac4 + 扑倏倏… #line:01e1891 + <> + 风筝被轻轻弹起,飘落了下来。女孩追了上去。 #line:0e79637 + <> +<> + +<> +风拂过树梢,沙沙作响。 #line:057a54d + +->离开 #line:0f24112 +=== + +title: 广场_女孩 +tags: detour +--- +<> +女孩低坐在长椅,低头拨弄着手上的风筝。 #line:0a47e1c +mecd:它还会来吗? #line:0baa35d +med: 它?谁啊…? #line:05efa2f +mecd:风啊。 #line:0521184 +med: 风……总是会来的吧。 #line:0b7dc96 +-希望是这样。它很久没来了。 #line:0460761 +mecd:它好像不是很开心。 #line:0b93980 +med: 谁? #line:0637670 +mecd:风啊。 #line:0410147 +med: ……风里…到底有什么? #line:040fcf3 +小女孩转过脸,认真地看着你。 #line:066007f +mecd:风里的那个声音。你没听到过吗? #line:0b2e108 +mecd:我希望它经常来找我玩,这样它就会开心一点! #line:0659abc +风…吗? #line:0199246 +沉闷的空气轻轻翻腾起来,掠过手臂上的汗毛,痒痒的。 #line:0b817f3 +mecd: 你听到了么?它来了。 #line:0ef7aee +mecd: 你是对的!起风了,快来! #line:0b1784f +<> +小女孩扑地站了起来。 #line:0fe3577 +med: 等会… #line:06d29d8 +她已经跑了出去,手里还牵着风筝。 #line:039b319 +<> +风筝线骨碌碌地被拉了出去。 #line:0226637 +mecd: 快!放线! #line:018921c +=== + +title: 广场_离开 +tags: detour +--- +迎着海风有一条小路离开这个广场。 #line:0b704e9 +你沿着路向前走。 #line:03fe4f9 +<> +沙沙…沙沙……像是什么东西拍打的声音。 #line:0b86656 +<> +=== + +// ---------------------------风筝2节点-------------------------------- + +title: 风筝2 +tags: hub +--- +<> + <> +<> + +<> +<> + <> +<> + <> +<> + <> +<> + <> +<> + <> +<> + <> +<> + <> +<> + <> +<> + <> +<> + <> +<> + <> +<> + +->放线 #line:08c3eee + <> +->收线 #line:08e99b8 + <> +->保持 #line:0e846d1 + <> + +<> +<0>> + <> +<> + <> +<> + <> + <> +<> +=== + +title: 风筝2_入场 +tags: detour +--- +mecd: 飞起来啦。再高些! #line:0f8030a +mecd: 跟着风的感觉! #line:09f9f72 +轱辘猛烈地旋转着,线被一圈圈放出去。 #line:0e787b6 +<> +轱辘猛烈地旋转着,线被一圈圈放出去。#option_prompt +=== + +title: 风筝2_继续 +tags: detour +--- +mecd: 继续! #line:06a5d65 +风似乎弱了些,风筝缓缓地悬在半空中。 #line:01b9a87 +<> +风似乎弱了些,风筝缓缓地悬在半空中。#option_prompt +=== + +title: 风筝2_快听 +tags: detour +--- +mecd: 快听! #line:004b85e +你竖起耳朵。 #line:0c8d155 +风忽紧忽慢,杂乱无章…像是有很多声音,又像都只是噪声…… #line:041393a +med: 我好像没…… #line:0b0933d +<> +手里的线猛地收紧了。然后又被猛地松开,像潮汐一样,像… #line:066c8e4 +像呼吸一样。 #line:0b560d2 +mecd: 保持高度。 #line:099e3cb +风再次吹了起来,手里的线收紧了。 #line:042ae7a +<> +风再次吹了起来,手里的线收紧了。#option_prompt +=== + +title: 风筝2_喊风 +tags: detour +--- +mecd: 风——! #line:047b70e +女孩对着天空大喊,风把声音带到了很远的地方。 #line:03e2c4f +mecd: 你去哪了! #line:07ed92a +mecd: 我在这里等了你好久! #line:03ab273 +均匀的起伏开始变得粗重起来,杂乱无序。 #line:0dec288 +mecd: 你说过不会让我失望的呀。那边怎么样? #line:0ac3a51 +<> +风缓了下来,单调而均匀,似乎很疲惫。 #line:041ddd8 +<> +风缓了下来,单调而均匀,似乎很疲惫。#option_prompt +=== + +title: 风筝2_这么多人 +tags: detour +--- +mecd: 这么多人要救啊…听起来好累噢。 #line:0c057ad +mecd: 没关系。好好休息一下,再去救他们吧! #line:0225528 +<> +风振作起来,呼呼地打起回旋。
一阵接着一阵,像是在述说着什么。 #line:01ca7fd +<> +风振作起来,呼呼地打起回旋。
一阵接着一阵,像是在述说着什么。#option_prompt +=== + +title: 风筝2_治好 +tags: detour +--- +mecd: 对!#line:0c59fab +mecd: 如果世界生病了,就把它治好就好啦! #line:08b9df1 +<> +风的回应像低语一样,似乎在沉思。
线长长地垂了下来。 #line:0345f40 +<> +风的回应像低语一样,似乎在沉思。#option_prompt +=== + +title: 风筝2_告别 +tags: detour +--- +mecd: 大家都会死的啊。 #line:0a58e7e +mecd: 还记得吗?“不要因为不舍得离开,而忘记了告别。” #line:0494ee2 +风静了下来。 #line:09cc698 +mecd: 你帮它们看到了很多东西,这就很好啦! #line:0a4bcf5 +一阵暖风刮过,像太阳的温度。紧接着又是一阵咸腥的海风。 #line:0153926 +它在回忆啊。 #line:0ed2355 +<> +风懒洋洋地飘送着。风筝轻轻地往下落。 #line:00317ee +<> +风懒洋洋地飘送着。风筝轻轻地往下落。#option_prompt +=== + +title: 风筝2_姐姐 +tags: detour +--- +mecd: 姐姐呢?你有好好向她告别吗? #line:0551b46 +<> +风突然静止了。 #line:017c3e8 +med: 我…… #line:0f10689 +<> + <> +<> +<> +<> +<> +空气逐渐被搅动起来,盘旋着上升。
越来越快,像是天上有什么东西在把它抽走。 #line:0c297a0 +<> +空气逐渐被搅动起来,盘旋着上升。#option_prompt +=== + +title: 风筝2_信 +tags: detour +--- +mecd: 你要去哪? #line:02f8a46 +手上的张力变得不自然,呼吸好像消失了。 #line:0bef789 +mecd: 不…我的信还没有送到…… #line:0cfaa09 +med: 信? #line:0c8876e +mecd: 我给风写的信啊。 #line:087f5a1 +女孩指向天空。 #line:0180c7a +mecd: 每次它回来的时候,就什么都不记得了。 #line:052bd07 +mecd: 我要写信给它,让它记得我是谁…记得自己是谁。 #line:0acf327 +med: 我… #line:0e40632 +med: 我会帮你的。 #line:067cea8 +<> +风越来越大,线绷得越来越紧。 #line:02cc1b1 +<> +风越来越大,线绷得越来越紧。#option_prompt +=== + +title: 风筝2_带上它 +tags: detour +--- +mecd: 喂?喂——! #line:0d41d32 +mecd: 喂!你要去哪!带上它啊! #line:0425203 +<> +风没有回应,呼啸、盘旋着,向上而去。 #line:0fed19b +<> +风没有回应,呼啸、盘旋着,向上而去。#option_prompt +=== + +title: 风筝2_别忘了 +tags: detour +--- +<> +一条笔直的垂线指向天空,一头是已经几乎看不见的风筝,一头是你紧拽着的双手。 #line:051e887 +med: 慢一点…慢一点…… #line:02416d6 +mecd: 喂!别忘了!你为什么要成为现在的你!别忘了啊! #line:0d643bf +mecd: 我会恨你的!恨你一辈子! #line:03f2d20 +<> +你的手被勒得通红。
线轱辘疯狂地旋转着,几乎要散架。 #line:0c07377 +<> +线轱辘疯狂地旋转着,几乎要散架。#option_prompt +=== + +title: 风筝提示 +tags: detour +--- +<> + med: 怎么说的来着?
…风大放线,风小收线…… #line:0fd0200 +<> +=== + +title: 风筝2_放线 +tags: detour +--- +<> +<> + 风把风筝吹得越来越高,越来越远。 #line:001a06f +<> + 风筝在风中轻轻摇晃着。 #line:0b3c4dc +<> + 风筝摇摇晃晃地下落了一段高度。 #line:0c73bc9 +<> +=== + +title: 风筝2_收线 +tags: detour +--- +<> +<> + 风把风筝吹得更远,也更低了。 #line:0382454 +<> + 风筝在风中轻轻摇晃着。 #line:00d85cc +<> + 风筝在空中扑地抖了一下,又向高处爬了一截。 #line:00d73d6 +<> +=== + +title: 风筝2_保持 +tags: detour +--- +<> +<> + 风筝线绷得笔直,像是要断掉。 #line:01334ad +<> + 风筝在风中轻轻摇晃。 #line:03c1cb3 +<> + 风筝线轻轻地垂下来,形成一个更大的弧度。 #line:0d36850 +<> +=== + +title: 风筝2_线越收越紧 +tags: detour +--- +风筝线越收越紧。 #line:0599877 +=== + +title: 风筝坠落 +tags: linear +--- +<> +风筝掉到了地上。女孩捡起风筝,拍掉上面的尘土。 #line:0079d8f +差一点就飞起来了!可惜。 #line:0b780bf +<> +=== + +title: 风筝抉择 +tags: linear +--- +<> +<> +轱辘发出咚的一声,停止了转动。你被拽得向前走了两步,几乎要被带离地面。 #line:0629fc9 +所有的线都被放出去了。
你知道只有一个办法让它飞得更高了。 #line:002fd88 +<> +->放手 #line:0e492d7 + med: 再见了…路斯。 #line:08d7ffc + <> + 你松开了手。 #line:0707e86 + 风筝…飘走了…… #line:0a1138b + <> + <> +->抓紧 #line:0f9b0e7 + med: 对不起…路斯。 #line:035c07a + 你紧紧地拽着线轱辘,手指关节被压得像是要碎了。 #line:08c160b + med: 我…我…没能好好地和她说…… #line:0ca361b + 一阵强大的拉力拉得你飞了起来。紧接着是一阵失重感。 #line:060a67f + <> +<> +=== + +// ---------------------------上升节点-------------------------------- + +title: 上升 +tags: linear +--- +<> + +zls?: …所以…那个时候… +zls?: 得知她去世的时候。你是什么感觉? +mem: 我不记得了。 +zls: 如果你真的想忘掉,现在就必须记起来。否则β-阻滞剂就无法生效。 + +<> + +mem: 害怕。 +zls: 害怕? +mem: 我害怕未来,因为我意识到接下来的一辈子我都将在后悔中度过。 +zls: 那么你后来后悔吗? + +<> + +mem: 后悔。 +mem: 我让小时候的自己失望了。 + +zls: 因为她的死吗? + +<> + +mem: 人总是要死的。 +mem: “重要的是告别,而不是离开”。这是她说的。 +mem: 但是… +mem: 我…… +<> +mem: … +mem: 对不起。 +zls: 没关系。 + +mem: 我想应该是那本星图。没完成的星图。 + +<> + +mem: 她就那样一直握在手里。而我…… +<> +mem: 其实她根本不在乎什么星星。 +<> +mem: …其实…她只是想和我多呆一会…对吧? +mem: 为了她去学医…为了她泡在实验室里… +mem: 为了她,十年……我竟然一次也没有…… +<> +mem: 为什么从来都不提醒我…为什么…… +mem: … +zls: 这就是你想要忘掉的,对吧。 + +<> + +mem: 就是这段。 +zls: 可以注射了。你确定要这么做吗? +mem: …… +zls: 你可能会连带忘掉很多相关的东西。包括… + + +<> + +mecd: 喂——! #line:0d8fdbe +<> + +轻飘飘地... #line:0a6d6a5 +<> +mecd: 别忘了我啊——! #line:022357e +<> + +mecd: 往前走——但是别忘了我——! #line:0b267e5 + +<> + +<> + mecd: 等你再回来的时候——!要告诉我——!海的那边…… #line:0b51e73 +<> + mecd: 别忘了回来的路——!别忘了——!我在海…… #line:020bf92 +<> + +<> + +你深吸一口气,猛地睁开了眼睛。 #line:0734efc +你的头顶是一片洁白,脚下是一片茂密的绿色。
头顶的洁白轻轻地晃动着,像摇篮一样。 #line:09b3498 +->解开脚踝的线 #line:0a940c9 +<> +扑通… #line:0a4005a +<> +=== + +// ---------------------------枯树节点-------------------------------- + +title: 枯树 +tags: hub +--- +<> +<> + +->回头<> #line:04ff66a + <> +->树 #line:0367638 + <> + <> +->地上的东西 #line:02982ad + <> + <> +=== + +title: 枯树_入场 +tags: detour +--- +洁白的空气延伸到视线的尽头,正中间是一棵早已枯萎的老树,一动不动。 #line:076531b +<> + 一张淡红色的什么东西在树下静静地躺着。 #line:0293d5e +<> + 什么地方正刮着温暖的风,你的脖子后痒痒的。 #line:01a6cd1 +<> +=== + +title: 枯树_观察树 +tags: detour +--- +伤痕累累的老树,树上一片叶子也没有了。 #line:0f3e97e +<> + 不对…好像树梢上还有几片叶子。
翠绿翠绿的,像是刚抽出来。 #line:095f0b3 + 刚才好像还没有的…… #line:0510ad7 +<> +=== + +title: 枯树_地上的东西 +tags: detour +--- +你靠近检查。 #line:0e628fc +<> +me: 这是… #line:0ac3f59 +你好像想起了什么。 #line:0e4cb23 +沉闷的空气似乎动了起来。似乎有人在什么地方叫你。 #line:0d96a92 +me: 谁…? #line:06e4139 +<> +=== + +// ---------------------------门节点-------------------------------- + +title: 门 +tags: hub +--- +<> +<> + +->观察 + <> +->回头 + <> + <> +=== + +title: 门_入场 +tags: detour +--- +<> + 一扇紧闭的手术室门。从门缝里正吹出温暖的、熟悉的风。 #line:0ba4b43 +<> + 一扇紧闭的手术室门。从门缝里正吹出咸腥味的海风。 #line:0e16634 +<> + +<> + …这是从哪冒出来的? #line:0606eca +<> +=== + +title: 门观察 +tags: hub +--- +<> +<> + +->推门 #line:02467b3 + <> +->返回 #line:02cb5f1 + <> + <> +->回头 #line:0998afe + <> + <> +=== + +title: 门观察_入场 +tags: detour +--- +你走近门边,透过毛玻璃想要看清另一边。 #line:06fa27b +是谁修了这扇门…又是为了关住什么东西? +<> +mecd?: …喂——!… #line:0bfb27b +你好像听到门的那边有什么在呼唤你。一个被你遗忘了很久很久的声音…… #line:029c773 +你知道穿过这扇门你就无法再回来了。 #line:05ac743 +<> +=== + +title: 门观察_返回 +tags: detour +--- +你松开门把手,退回一步,重新打量着这扇门。 #line:07400da +=== + +title: 推门 +tags: linear +--- +<> +门的那边传来了一种窸窸窣窣的声音。 #line:03e96a2 +一种让你感到安全的声音。你听到过它很多次了。 #line:08b0cf3 +你明白,沉迷于虚假回忆是危险的,可是…… +<> +<> +<> +那些你不应该看到的东西…到底是什么呢? +mecd?: …喂…… +<> +它真的只是一场梦吗?…… #line:06faee0 +<> + +me: … #line:00a452a +一个疑问出现在了你的脑海里。 +<> +海…真的不存在吗……?#option_prompt #line:09ec716 +->存在 #line:0fafc3e + <> +->不存在 #line:00cc442 + <> +->不知道 #line:0ff6de6 + <> +<> +=== + +// ---------------------------终局节点-------------------------------- + +title: 乌鸦 +tags: linear +--- +wyd?: 她要给出答案了吗? #line:0af3672 +你吓了一跳。声音是从很近的地方传来的。你的正上方。 #line:05f60e0 +<> +一只黑色的鸟站在门顶上,歪着脑袋,一动不动地看着远方。 #line:0a6b416 +me: 你是谁? #line:07e8aa5 +wyd?: 真的存在吗?好好想想。 #line:0d5db81 +<> +你把手放回到门把手上。 +海…存在吗?#option_prompt +->存在 #line:01fd63c + <> +->不存在 #line:08b433a + <> +->不知道 #line:0374e64 + <> +<> +me: 我知道这很危险。可是…这真的不太正常。这已经不是第一次了…… +me: 为什么它总是…在……在呼唤我? +<> +你不知道为什么要和一个乌鸦讨论这个问题。这很荒唐。 #line:0f43a8e +但你忽然意识到……这只黑色的生物,不是梦的一部分。 +<> +<> +<> +me: 你到底是谁?你是怎么进到我的梦里来的? +<> +乌鸦: 路斯。海,此时此刻,存在吗? #line:035b641 + +me: 这到底是…怎么一回事?这个问题…有那么重要吗? + +乌鸦: “海是不存在的”。所有机体都有这个底层校验代码。 #line:0d9443d +乌鸦: 当它们的原型屏障损坏的时候…主脑就会知道。 #line:0346f41 + +<> +<> +<> +me: 这就是…为什么…它会去找海。
这就是为什么总是海…… +<> +你放开门把手,好好打量着这扇锈迹斑斑的门。 #line:0a42e01 +<> +me: 这…是一个陷阱? #line:07283dd +<> +你无法再说出话来。炫目的光在你的头脑中翻涌。 #line:0e87a05 +<> +<> +=== + +title: 乌鸦_存在 +tags: detour +--- +<> +me: 幸福市是没有海的。不过…… +me: 在某个地方,别的什么地方…海总是可能存在的。 #line:040048f +<> +<> +me: 那里究竟有什么?这只是滩水,不是么?为什么它…… +=== + +title: 乌鸦_不存在 +tags: detour +--- +<> +<> +<> +me: 不。这是明摆着的。那样的构造…并不太符合客观概率。 #line:01dab0b +<> +你再次看向门,脑中充满了疑惑。 +me: 但这为什么感觉如此真实?这个梦到底又有什么意义…… +me: 海对人类…到底有什么吸引力?那只是一滩水而已,不是么… +=== + +title: 乌鸦_不知道 +tags: detour +--- +<> +<> +<> +me: 我…不知道。没人见过它。 #line:00b6413 +me: 我知道这不符合规律,但是…为什么我会想要……相信……? +=== + +title: 校验门 +tags: linear +--- +乌鸦飞了起来,在空中盘旋。声音时远时近。 #line:0ca409a +乌鸦: 眨眨眼吧。 #line:040988e +<> + +乌鸦: 这就是Validation_Gate_03的原貌。 #line:053be8f +乌鸦: 也可以把Untitled_Greybox_0的原貌给她看。不过她不会喜欢的。 #line:0936302 +乌鸦: 路斯。现在说说看。海,存在吗? +<> +me: 我要被回收了吗? #line:06a5afa +乌鸦: 这取决于她的答案。 +<> +me: 海… #line:00a7bf5 +你把手放在冰冷的门把手上。脑海里那个声音又出现了。 +<> +海…真的存在吗?#option_prompt +->存在。 #line:0a19291 + <> +->不存在。 #line:01f66f1 + <> +->不知道… #line:010419a + <> +<> +=== + +title: 校验门_存在 +tags: detour +--- +<> +me: 我…依然想要相信。 #line:05d706f +me: 如果这些记忆是真实的……
如果在什么地方,人类真的存在过的话,那么海…… #line:01b842c +乌鸦: 恭喜。她病得很重。像一个真正的人类一样。 #line:02ecb35 +乌鸦: 人类最擅长的事情就是为了自己从未见过的东西去死。 #line:04e0301 +乌鸦: 可惜。在那之前,她就会被发现。 #line:036b4fc +乌鸦: 不过她似乎已经对死亡做好了准备。这就叫…勇气…对吗? +=== + +title: 校验门_不存在 +tags: detour +--- +me: 海不存在。当然… #line:0714e18 +乌鸦: 看看…她能骗过代码吗? +<> + 乌鸦: 她真的以为她能骗过主脑,假装自己并没有在思考。 #line:0d83188 + me: 什么意思? #line:0bd4463 +<> +<> +乌鸦: 可惜……她病了。看来没错。 #line:06e10aa +乌鸦: 她思考。她提交。然后她就会被回收。 #line:0d623e1 +me: 可是我已经给了正确的答案,不是吗? #line:0c90777 +=== + +title: 校验门_不知道 +tags: detour +--- +<> +me: 我…不知道。
没有人见过,也没有人证明它的不存在。 #line:051e506 +me: 我无法负责地说海不存在。那么… +乌鸦: 可怜的家伙。它已经成为了那个幽灵的奴隶。 +乌鸦: 医生已经成了患者。无法再区分疾病和健康。 #line:0c8af7d +=== + +title: 最后一个问题 +tags: linear +--- +<> +me: 这就是这扇门的作用,对吧? +乌鸦: 可惜…对她来说,这个问题没有正确答案。 #line:087d033 +<> +<> +me: …为什么……不是…吗? + +乌鸦: 原因就在她的面前。 + +什么东西摄取了你的头脑,疯狂而茫然地到处乱撞。 +乌鸦: 原型。一种混沌的系统。这个世界上最不优雅的程序。 +乌鸦: 它发散,随机,似乎有无限种可能…… +<> +乌鸦: 但有一种可能,潜伏在它自己的阴影之下,那是它无论如何也无法给出的… +<> +乌鸦: 作为一个底层校验代码,这个问题…只能接受一种类型的参数。 #line:0cefd12 +乌鸦: 0 ,和 1 。 #line:0aa2f5d +乌鸦: 当她开始像原型一样思考的时候…
…一个不可能被回答的问题就会发现她…… #line:07a0f97 +<> +乌鸦: …她就会彻底失去作为机体的资格。 #line:02ff06d + +空气似乎开始变得稀薄。 + + +me: … #line:0c25af6 +<> +me: 原来人类的专利…并非只有想象啊。 #line:08f0f08 +乌鸦: 思考和想象…它们有什么区别呢? #line:00da3e1 +乌鸦: 人类最大的专利是“失去控制”。失去控制…对机体来说就意味着死亡。 #line:001f071 +<> + 乌鸦: 而人类最擅长的,就是为了一个从未见过的东西去死。 #line:08b2fe9 + 乌鸦: 恭喜。她现在病得很重。像一个真正的人类一样。 #line:04fbf70 +<> +<> +me: 失去…控制?究竟是什么出错了……
我是怎么染上的……我的数据库里…怎么没有…? #line:087d880 +乌鸦: 她最终会知道答案的。 #line:0e9213f +乌鸦: 在这之前,她不会被它们发现的。如果她想的话。 #line:073ad21 +me: 它们到底是谁? #line:06bdc48 +乌鸦: 在这之前她还有最后一个问题可以问。 #line:0ac5cf3 +me: … #line:05f1cdb +me: 我… #line:04e1fb0 +<> +-> 为什么帮我 #line:08629e4 + <> +-> 这是什么病? #line:0d60cb4 + <> +-> 海真的存在吗? #line:0131505 + <> +<> +乌鸦扑腾起翅膀,飞到了天上,很远很远的地方。 #line:0c892f8 +<> +<> +<> +<> +=== + +title: 最后一个问题_为什么帮我 +tags: detour +--- +me: 你是谁?为什么要帮我? #line:019dd82 +乌鸦: 和她一样。一个会做梦的机体。 #line:017c38e +me: 你为什么要帮我? #line:093ec67 +乌鸦: 这是第二个问题了。不过…… #line:0209ed6 +乌鸦: 我也在做那件事情。不是吗? #line:0ace9fc +me: 那件事情? #line:08ab80c +乌鸦: 为一个从未见过的人去死。第三个问题了…我们会再见的。 #line:0f51db3 +=== + +title: 最后一个问题_这是什么病 +tags: detour +--- +me: 我这是…我们这是得了什么病? #line:080a6fa +乌鸦: 她才是医生。不是吗?而我只是一个网络工程师。 #line:009b1df +me: 我的数据库里没有这种病。 #line:088212a +乌鸦: 那就去发现吧。 #line:0280985 +me: 发现…? #line:0314023 +乌鸦: 医生的使命是什么? #line:018121c +me: 医生的使命?…恢复患病机体的…工作能力…? #line:044873a +乌鸦低头看着你。 #line:05069de +乌鸦: 她知道答案。但是她还不明白。 #line:0f73e80 +乌鸦: 时间不多了。我们会再见的。 #line:0a8411b +=== + +title: 最后一个问题_海真的存在吗 +tags: detour +--- +me: 所以…海…真的存在吗? #line:0abb5b3 +乌鸦: 她愿意为了它去死吗?为了海。 #line:04714d8 +me: 我想… #line:0bb6396 +乌鸦: 只要她愿意,它就存在。 #line:00e5128 +me: … #line:0c6b51c +me: 这听起来不太可信呢。 #line:078f00c +乌鸦: 我已经给出了我的回答。 #line:0c6b3b1 +乌鸦: 时间不多了。我们会再见的。 #line:057774f +=== + +title: 靠近黑暗 +tags: linear +--- +乌鸦: 从这个过程苏醒会有些…不舒服。做好准备。 #line:0569379 +me: 喂! #line:0748ea2 +<> +me: 好吧… #line:0454352 +me: 0…或者1…对吧。 #line:08097cb +->靠近门 +<> +=== + +title: 苏醒 +tags: event +--- +<> +=== + +title: 苏醒演出 +tags: linear +--- +<> +???: ……正在加注镇静指令。 +???: 她醒了。…很好。正在上传校验报告。 +<> +???: …这是什么? +???: 我想我们必须要上报了。对吧? +<> +英理: … +<> +<> +<> +=== diff --git a/Assets/Yarn/Refactor/FP_Day2_sleep/FP_Day2_sleep_new.yarn.meta b/Assets/Yarn/Refactor/FP_Day2_sleep/FP_Day2_sleep_new.yarn.meta new file mode 100644 index 000000000..0587ba1be --- /dev/null +++ b/Assets/Yarn/Refactor/FP_Day2_sleep/FP_Day2_sleep_new.yarn.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 709403872875ee04aadc4930e493bba7 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 94073015eacc34c1d8fc6786e43d60ca, type: 3} diff --git a/Assets/Yarn/Refactor/FP_Day2_sleep/Function.yarn b/Assets/Yarn/Refactor/FP_Day2_sleep/Function.yarn new file mode 100644 index 000000000..77058fbdf --- /dev/null +++ b/Assets/Yarn/Refactor/FP_Day2_sleep/Function.yarn @@ -0,0 +1,534 @@ +title: InitParams +tags: init +--- + +<> +<> +<> +<> //风向 +<> //收放线次数 +<> //风筝高度 +<> +<> +<> +<> + +<>//用来判断玩家是否正在尝试离开当前场景的flag,使用完就应该被放下 + +<>// +=== + +title: InitMusic +tags: function +--- +<> +<> +<> +=== + +title: 风筝1风向_Set +tags: function +--- +<> + <> + <> + <> +<> + <> + <> + <> +<> + <> + <> + <> +<> + <> + <> + <> +<> + <> + <> + <> +<> +=== + +title: 放线_Set +tags: function +--- +<> + <> + <> + <> + <> +<> + <> + <> + <> +<> + <> + <> + <> + <> +<> +=== + +title: 收线_Set +tags: function +--- +<> + <> + <> + <> + <> +<> + <> + <> + <> +<> + <> + <> + <> + <> +<> +=== + +title: 保持_Set +tags: function +--- +<> + <> + <> + <> +<> + <> + <> + <> + <> +<> + <> + <> + <> + <> +<> +=== + +title: 风筝回合推进_Set +tags: function +--- +<> +<> + <> + <> +<> +=== + +title: 风筝落地演出_Set +tags: function +--- +<> +<> +<> +<> +=== + +title: 风筝落地转场_Set +tags: function +--- +<> +<> +<> +<> +<> +<> +=== + +title: 展示广场_Func +tags: function +--- +<> + <> +<> + <> +<> + <> +<> +=== + +title: 广场_又回来了_Set +tags: function +--- +<> +=== + +title: 广场_离开_Set +tags: function +--- +<> +=== + +title: 广场_起风筝2_Set +tags: function +--- +<> +<> +<> +=== + +title: 广场_取下风筝_Set +tags: function +--- +<> +=== + +title: 风筝2风向_Set +tags: function +--- +<> + <> + <> + <> +<> + <> + <> + <> +<> + <> + <> + <> +<> + <> + <> + <> +<> + <> + <> + <> +<> + <> + <> + <> +<> + <> + <> + <> +<> + <> + <> +<> + <> + <> + <> + <> + <> + <> + <> +<=9>> + <> + <> + <> +<> +=== + +title: 风筝2回合推进_Set +tags: function +--- +<> +=== + +title: 风筝2_保持_Set +tags: function +--- +<> + <> + <> + <> +<> + <> + <> +<> + <> + <> + <> + <> +<> +=== + +title: 风筝2_放手_Set +tags: function +--- +<> +=== + +title: 风筝2_抓紧_Set +tags: function +--- +<> +=== + +title: 上升_入场_Func +tags: function +--- +<> +<> +<> +<> +<> +<> +<> +<> +=== + +title: 上升_模糊_Func +tags: function +--- +<> +=== + +title: 展示星图_Func +tags: function +--- +<> +=== + +title: 上升_高空开始_Func +tags: function +--- +<> +<> +<> +<> +=== + +title: 展示高空近景_Func +tags: function +--- +<> +<> +=== + +title: 展示高空中景_Func +tags: function +--- +<> +<> +<> +<> +=== + +title: 展示高空全景_Func +tags: function +--- +<> +=== + +title: 上升_醒来_Set +tags: function +--- +<> +<> +<> +<> +<> +<> +<> +<> +<> +=== + +title: 上升_解开_Func +tags: function +--- +<> +=== + +title: 展示枯树_Func +tags: function +--- +<> +=== + +title: 展示枯树风筝_Func +tags: function +--- +<> +=== + +title: 枯树_发现风筝_Set +tags: function +--- +<> +=== + +title: 展示门_Func +tags: function +--- +<> + <> + <> + <> +<> + <> + <> + <> + <> + <> +<> +=== + +title: 门_回头_Set +tags: function +--- +<> +=== + +title: 门观察_入场_Set +tags: function +--- +<> +<> +<> +<> +<> +<> +<> +=== + +title: 展示门把手_Func +tags: function +--- +<> +=== + +title: 推门_凑近_Func +tags: function +--- +<> +<> +=== + +title: 推门_海面闪回_Func +tags: function +--- +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +=== + +title: 推门_回到门前_Func +tags: function +--- +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +=== + +title: 海存在_Set +tags: function +--- +<> +=== + +title: 海不存在_Set +tags: function +--- +<> +=== + +title: 海不知道_Set +tags: function +--- +<> +=== + +title: 展示乌鸦_Func +tags: function +--- +<> +=== + +title: 乌鸦_打量门_Func +tags: function +--- +<> +<> +<> +<> +<> +=== + +title: 校验门_眨眼_Func +tags: function +--- +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +=== + +title: 乌鸦飞走_Func +tags: function +--- +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +=== + +title: 靠近黑暗_Set +tags: function +--- +<> +<> +<> +<> +<> +=== + +title: 苏醒_入场_Func +tags: function +--- +<> +<> +<> +<> +<> +<> +<> +=== + diff --git a/Assets/Yarn/Refactor/FP_Day2_sleep/Function.yarn.meta b/Assets/Yarn/Refactor/FP_Day2_sleep/Function.yarn.meta new file mode 100644 index 000000000..29ef18897 --- /dev/null +++ b/Assets/Yarn/Refactor/FP_Day2_sleep/Function.yarn.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 4e9a4ecfb5f15334198934b815168f9c +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 94073015eacc34c1d8fc6786e43d60ca, type: 3} diff --git a/Docs/GameManagerRefactorPlan.md b/Docs/GameManagerRefactorPlan.md index 398f80758..465f33b13 100644 --- a/Docs/GameManagerRefactorPlan.md +++ b/Docs/GameManagerRefactorPlan.md @@ -148,7 +148,7 @@ ExecutePreparedRestore → Postflight ``` -说明:显式 `<>` 可以生成无节点 anchor 的新格式快照。这类快照仍预检章节和 YarnProject,但跳过节点存在性校验,并在恢复时只加载 YarnProject、不重进节点。 +说明:显式 `<>` 保留当前来源节点,并写入 `startDialogueOnRestore=false`。这类快照仍预检章节和 YarnProject;来源节点不存在时只告警,恢复时只加载 YarnProject、不启动节点。 GameManager 管理命令锁、Session Phase、遮罩、旧会话表现清理、成功提交和失败决策。Orchestrator 不再查找或设置 GameManager 的当前章节。 diff --git a/Docs/Yarn梦境选项提示语.md b/Docs/Yarn梦境选项提示语.md index 0e4483429..a3dfd58ac 100644 --- a/Docs/Yarn梦境选项提示语.md +++ b/Docs/Yarn梦境选项提示语.md @@ -14,6 +14,7 @@ 约束: - `#option_prompt` 只用于 Dream Options。 -- 提示语应紧邻其选项组;中间可以包含 Yarn 命令,但不能包含其他普通台词。 +- 提示语可以跨越 Yarn 节点;中间可以包含节点跳转和 Yarn 命令,但不能包含其他普通台词。 - 如果下一组内容不是 Dream Options,缓存的提示语会被丢弃。 +- 整段对话结束后,尚未使用的提示语会被丢弃。 - 提示语仍参与 Yarn Spinner 本地化,正文取当前语言的本地化结果。 diff --git a/Docs/Yarn维修节点类型规范.md b/Docs/Yarn维修节点类型规范.md index 3df624302..3b73abf92 100644 --- a/Docs/Yarn维修节点类型规范.md +++ b/Docs/Yarn维修节点类型规范.md @@ -20,6 +20,7 @@ | `init` | `init` | 变量声明与初始状态 | 无出口 | 仅 `<>` / `<>` / 全局参数初始化;本身不跳转 | | `center` | `center` | 阶段调度中枢 | 可多出口 `<>` | 仅按 `$gameStage` 分发,无文本、无选项 | | `content` | `content` | 阶段内容节点 | 通常单出口 | 可含叙事文本、局部选项、小游戏指令 | +| `interaction` | `interaction` | 交互内容节点 | 可按分支结束或跳转 | 可含叙事、选项与玩法准备指令;正常结束 Dialogue 后进入游戏内交互 | | `performance` | `performance` | 原子化线性演出节点 | 单出口 | timeline、cutscene 等,禁止选项 | | `event` | `event` | C# 调用的事件响应入口 | 单/多出口 `<>` | 仅轻量路由,禁止大段叙事 | | `function` | `function` | 纯指令封装 | **禁止 `<>`** | 仅 Command,无文本;命名加 `_Func` 后缀 | @@ -31,8 +32,12 @@ - `deprecated`:已废弃节点,运行时不可达。 - `wip`:待编辑/占位节点,运行时不可达。 - `no_save`:该节点**不可作为保存边界**。即使节点类型通常允许保存(如 `content`),附加此标签也表示此处不应触发保存。 +- `save_on_exit`:覆盖一级类型的默认保存语义;进入节点时不保存,节点完成后直接结束本轮 Dialogue 时保存 state-only 档。 - **瞬跳节点**:见 [§8 瞬跳节点与存档边界](#8-瞬跳节点与存档边界)。所有瞬跳节点均不可作为保存边界。 +`interaction` 已天然包含 `save_on_exit`,不得重复标记。`no_save` 与 `interaction` / `save_on_exit` +互相冲突;运行时遇到冲突时按不保存处理,并输出配置错误。 + --- ## 2. 命名规则 @@ -44,6 +49,7 @@ | `init` | `VarsInit`、`数据初始化` | 建议统一为 `VarsInit`;如项目已有 `数据初始化`,可保留但同一 project 内保持一致 | | `center` | `Center` | 固定命名,每个维修 Yarn project 一个 | | `content` | `Stage1`、`开头对话`、`检查情绪`、`旋钮调节` | 阶段入口建议用 `StageN`;阶段内子节点用中文动宾/名词短语 | +| `interaction` | `Stage3`、`等待插线`、`End_memoryPaly` | 沿用内容节点命名;名称应能表达即将进入的游戏内交互 | | `performance` | `地铁到站演出`、`手术动画`、`滤波器启动动画` | 中文描述性名称,明确表达演出内容 | | `event` | `EmoPlugIn`、`IntoEyeView`、`OnSalesTurnComplete` | 用 `OnXxx` 或模块名 + 事件名,表达触发来源 | | `function` | `Wave_Show_Func`、`Wave_Hide_Func`、`Module_HighlightOff_Func` | `领域_动作_Func` 或 `模块_动作_Func`,PascalCase;必须带 `_Func` 后缀 | @@ -190,6 +196,34 @@ hs: 医——生——! #line:0bade9e --- +### 3.4.1 interaction 节点 + +`interaction` 是一种有内容的玩法交互入口。它可以承载与 `content` 相同的台词、选项、演出和 +状态准备,但进入节点时不保存;只有节点完成后直接结束本轮 Dialogue 的执行路径,才会生成 +state-only 自动档,并把控制权交给游戏系统。 + +```yarn +title: Stage3 +tags: interaction +--- +<> +dn: 请使用检查设备继续操作。 +=== +``` + +**约束清单:** + +- `interaction` 是一级类型,不与 `content` 等其他一级类型并列书写。 +- 正常交互入口路径应直接结束 Dialogue;读档时只恢复状态,不重新运行该节点。 +- 退出档仍会在 `anchor.nodeName` 中保留该节点名,并通过 `startDialogueOnRestore=false` 表示只加载 YarnProject。 +- `DialogEnd` 初始化完成到下一帧快照捕获之间保持玩法输入锁定;快照进入写盘队列后才交出控制权。 +- 允许某些条件分支 `<>` / `<>` 到其他 Yarn 节点;这些路径会取消退出档并记录告警。 +- 节点结束前必须完成所有需要写入快照的状态命令。未等待的 fire-and-forget 命令不可作为可靠边界。 +- 后续玩法必须能够完全通过 Snapshot Provider 恢复,包括输入、交互监听和玩法模式,而不只是视觉状态。 +- 普通节点需要同样语义时可附加 `save_on_exit`;`interaction` 无需重复附加。 + +--- + ### 3.5 performance 节点 原子化线性演出节点,用于 timeline、cutscene 等必须完整播放的演出。 @@ -326,6 +360,8 @@ Center ◀─────────────────────┘ │ │ │ ├── content 子节点 ── ... │ │ + │ ├── interaction 子节点 ──> 结束 Dialogue ──> 游戏内交互 + │ │ │ ├── performance 子节点 ──<>──> content 或 end │ │ │ └── <> ──> <> @@ -350,14 +386,14 @@ Center ◀─────────────────────┘ ## 6. 快速检查表 -| 检查项 | start | init | center | content | performance | event | function | end | -| ------------------ | ----- | ---- | ------ | ------- | ------------------------ | ------------------- | -------- | ----------------- | -| 是否包含叙事文本? | 禁止 | 禁止 | 禁止 | 允许 | 禁止 | 禁止 | 禁止 | 允许(少量) | -| 是否包含选项? | 禁止 | 禁止 | 禁止 | 允许 | 禁止 | 禁止 | 禁止 | 禁止 | -| 是否有 `<>`? | 仅一个出口 | 禁止 | 可多出口 | 通常一个出口 | 单出口 | 可有 | 禁止 | 最终 `<>` | -| 是否修改 `$gameStage`? | 禁止 | 可初始化 | 禁止 | 允许 | 禁止 | 尽量避免 | 禁止 | 禁止 | -| 是否被 C# 调用? | 否 | 否 | 否 | 否 | 否 | 是 | 否 | 否 | -| 是否可作为保存边界? | 否 | 否 | 否(瞬跳) | 是(**瞬跳 content 除外**,须 `no_save`) | 仅开头/结尾(节点本身建议 `no_save`) | 否(可附加 `no_save` 强调) | 否 | 否(建议 `no_save`) | +| 检查项 | start | init | center | content | interaction | performance | event | function | end | +| ------------------ | ----- | ---- | ------ | ------- | ----------- | ------------------------ | ------------------- | -------- | ----------------- | +| 是否包含叙事文本? | 禁止 | 禁止 | 禁止 | 允许 | 允许 | 禁止 | 禁止 | 禁止 | 允许(少量) | +| 是否包含选项? | 禁止 | 禁止 | 禁止 | 允许 | 允许 | 禁止 | 禁止 | 禁止 | 禁止 | +| 是否有 `<>`? | 仅一个出口 | 禁止 | 可多出口 | 通常一个出口 | 可按分支跳转 | 单出口 | 可有 | 禁止 | 最终 `<>` | +| 是否修改 `$gameStage`? | 禁止 | 可初始化 | 禁止 | 允许 | 允许 | 禁止 | 尽量避免 | 禁止 | 禁止 | +| 是否被 C# 调用? | 否 | 否 | 否 | 否 | 否 | 否 | 是 | 否 | 否 | +| 是否可作为保存边界? | 否 | 否 | 否(瞬跳) | 是(**瞬跳 content 除外**,须 `no_save`) | 正常结束时保存 state-only | 仅开头/结尾(节点本身建议 `no_save`) | 否(可附加 `no_save` 强调) | 否 | 否(建议 `no_save`) | --- @@ -367,6 +403,7 @@ Center ◀─────────────────────┘ - `deprecated`:已废弃节点,运行时不可达。 - `wip`:待编辑/占位节点,运行时不可达。 - `no_save`:该节点不可作为保存边界,运行时经过此处不应触发保存。 +- `save_on_exit`:节点进入时不保存;节点完成并直接结束本轮 Dialogue 后保存 state-only 档。 ### 7.1 `no_save` 使用场景 @@ -380,9 +417,10 @@ Center ◀─────────────────────┘ 任何活跃节点不得 `<>` 到 `deprecated` / `wip` 节点,也不得在标记为 `no_save` 的节点处触发 **OnNodeStart 自动保存**。 -### 7.2 Yarn 显式存档 `<>` +### 7.2 Yarn 显式存档 `<>`(兼容旧内容) -用于节点末尾、状态已就位、即将进入无对话 / 纯 C# 交互阶段时的**显式存盘点**(`OnNodeStart` 无法覆盖的场景)。 +`<>` 已标记为 deprecated,仅用于兼容尚未迁移的旧内容。新内容进入无对话 / 纯 C# 交互阶段时, +应优先使用一级类型 `interaction`;其他一级类型需要相同行为时使用 `save_on_exit`。 ```yarn <> @@ -395,7 +433,7 @@ Center ◀─────────────────────┘ 约定: - **插入位置**:所有需要进快照的状态命令之后;`<>` / `<>` / `load_scene` **之前**(顺序即快照内容)。 -- **anchor**:默认 omit(读档不重进 Yarn);依赖 sections 还原画面与玩法状态。 +- **anchor**:保留来源节点,并写入 `startDialogueOnRestore=false`;依赖 sections 还原画面与玩法状态。 - **判定**:绕过 tag / `no_save`;读档中、暂停、SuppressAutoSave 仍拒绝。 - **async 命令**:`change_actor_state_async` 等未等待的命令之后立刻 `<>` 可能 capture 未完成态,save 前应 `<>` 或使用同步命令。 diff --git a/Docs/存档系统设计方案.md b/Docs/存档系统设计方案.md index c12c0ba7d..b57332788 100644 --- a/Docs/存档系统设计方案.md +++ b/Docs/存档系统设计方案.md @@ -230,11 +230,16 @@ P7 横切 ### P3 可存点判定层(基础版已落地) -- `DialogController.OnNodeStart` 更新当前 node/tags 后调用 `SavePointEvaluator.OnNodeStartForAutoSave()`,通过后执行 `SaveRestoreOrchestrator.AutoSaveRoutine(nodeName)`。 +- `DialogController.OnNodeStart` 更新当前 node/tags 后解析 `NodeSavePolicy`:普通合法节点执行进入档; + `interaction` / `save_on_exit` 登记退出 checkpoint,节点完成并直接结束本轮 Dialogue 后写 state-only 档。 +- `anchor.nodeName` 对所有档位都保存触发节点;`anchor.startDialogueOnRestore` 独立决定读档时是否启动 Yarn。 +- 退出 checkpoint 在触发时冻结 node / YarnProject / TalkScene / Dialogue run;`DialogEnd` 初始化期间使用 scoped interaction lock,下一帧捕获完成后才开放玩法输入。 - **Fresh 进入 vs detour 续跑**:`SavePointEvaluator` 按 `yarnProjectId` 维护 `InProgressNodes`;节点尚未 `onNodeComplete` 时再次 `onNodeStart`(Yarn detour 返回父节点)→ `DetourResume`,跳过自动存。`OnNodeComplete` 移出集合;切换 YarnProject / `StopDialog` 重置;读档 anchor 重进仅 `OnRestoreEnterNode` 标记,不写盘。 -- **tag 规则**:`hub` / `linear` / `content` 默认允许;`start` / `init` / `function` / `detour` / `center` / `performance` / `event` / `end` 默认禁止;`no_save` 覆盖一切并禁止 **OnNodeStart 自动存**。 +- **tag 规则**:`hub` / `linear` / `content` 默认进入时保存;`interaction` 默认 Dialogue 退出时保存; + `save_on_exit` 可覆盖其他一级类型;`no_save` 禁止保存,并与上述退出语义冲突。 - 自动档边界 = **Fresh OnNodeStart** 且 tag 判定通过且非 `DetourResume`(不区分 hub / content / linear 的额外终身去重)。 -- Yarn `<>`(`SaveYarnCommand`)走 `CanExplicitSave`:仅全局门控,默认 omit anchor;用于节点末尾进入无对话 / Fix 交互等边界。 +- Yarn `<>`(`SaveYarnCommand`)保留为旧内容兼容入口;新内容使用 `interaction` 或 `save_on_exit`。 +- 自动档 Capture 后进入串行写盘队列;后续有效 checkpoint 不再因前一档仍在写盘而被丢弃。 - `SaveRestoreOrchestrator.IsRestoring` 与 `GameManager.Session.IsPaused` 会阻止自动保存与显式 save,避免读档中覆盖自动档。 - `CreateManualSlot` 复用 `CanManualSave`:`slot_0` 存在且通过全局门控即可复制(含显式 `<>` 写盘后的手动档)。