com.amanotes.magictilescore 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +240 -0
- package/CHANGELOG.md.meta +7 -0
- package/Docs/Class-Hierarchy.md +729 -0
- package/Docs/Class-Hierarchy.md.meta +7 -0
- package/Docs/Component-Architecture.md +43 -0
- package/Docs/Component-Architecture.md.meta +7 -0
- package/Docs/File-Structure.md +327 -0
- package/Docs/File-Structure.md.meta +7 -0
- package/Docs/Game-Architecture.md +41 -0
- package/Docs/Game-Architecture.md.meta +7 -0
- package/Docs/Input-System-Guide.md +419 -0
- package/Docs/Input-System-Guide.md.meta +7 -0
- package/Docs/Knot-System-Guide.md +309 -0
- package/Docs/Knot-System-Guide.md.meta +7 -0
- package/Docs/Meta-System-Guide.md +249 -0
- package/Docs/Meta-System-Guide.md.meta +7 -0
- package/Docs/New-Game-Checklist.md +102 -0
- package/Docs/New-Game-Checklist.md.meta +7 -0
- package/Docs/README.md +37 -0
- package/Docs/README.md.meta +7 -0
- package/Docs/RhythmCore-Architecture.md +373 -0
- package/Docs/RhythmCore-Architecture.md.meta +7 -0
- package/Docs/RhythmCore-Customize-Guide.md +391 -0
- package/Docs/RhythmCore-Customize-Guide.md.meta +7 -0
- package/Docs/Understanding-Rhythm-Core.md +483 -0
- package/Docs/Understanding-Rhythm-Core.md.meta +7 -0
- package/Docs/VisualWarp-System-Guide.md +377 -0
- package/Docs/VisualWarp-System-Guide.md.meta +7 -0
- package/Docs/Widget2D-System-Guide.md +450 -0
- package/Docs/Widget2D-System-Guide.md.meta +7 -0
- package/Docs.meta +8 -0
- package/Editor/AdjustHueEditor.cs +90 -0
- package/Editor/AdjustHueEditor.cs.meta +11 -0
- package/Editor/ClassInstanceDrawer.cs +256 -0
- package/Editor/ClassInstanceDrawer.cs.meta +11 -0
- package/Editor/CollapsibleGroupEditor.cs +142 -0
- package/Editor/CollapsibleGroupEditor.cs.meta +11 -0
- package/Editor/ListSongNoteEditor.cs +317 -0
- package/Editor/ListSongNoteEditor.cs.meta +11 -0
- package/Editor/MagicTilesCore.Editor.asmdef +20 -0
- package/Editor/MagicTilesCore.Editor.asmdef.meta +7 -0
- package/Editor/MetaLogicDrawer.cs +488 -0
- package/Editor/MetaLogicDrawer.cs.meta +11 -0
- package/Editor/RhythmContextEditor.EditorDrawer.cs +46 -0
- package/Editor/RhythmContextEditor.EditorDrawer.cs.meta +3 -0
- package/Editor/RhythmContextEditor.cs +587 -0
- package/Editor/RhythmContextEditor.cs.meta +3 -0
- package/Editor/RhythmGameEditor.cs +45 -0
- package/Editor/RhythmGameEditor.cs.meta +11 -0
- package/Editor/RhythmTileEditor.cs +93 -0
- package/Editor/RhythmTileEditor.cs.meta +11 -0
- package/Editor/TagConfigDrawer.cs +30 -0
- package/Editor/TagConfigDrawer.cs.meta +11 -0
- package/Editor.meta +8 -0
- package/LICENSE.md +7 -0
- package/LICENSE.md.meta +7 -0
- package/README.md +88 -0
- package/README.md.meta +7 -0
- package/Runtime/AssemblyInfo.cs +4 -0
- package/Runtime/AssemblyInfo.cs.meta +11 -0
- package/Runtime/Input/Base/BaseTileInput.cs +44 -0
- package/Runtime/Input/Base/BaseTileInput.cs.meta +11 -0
- package/Runtime/Input/Base/IInputHandler.cs +11 -0
- package/Runtime/Input/Base/IInputHandler.cs.meta +11 -0
- package/Runtime/Input/Base/InputData.cs +94 -0
- package/Runtime/Input/Base/InputData.cs.meta +3 -0
- package/Runtime/Input/Base/InputDirection.cs +17 -0
- package/Runtime/Input/Base/InputDirection.cs.meta +3 -0
- package/Runtime/Input/Base/InputPhase.cs +4 -0
- package/Runtime/Input/Base/InputPhase.cs.meta +3 -0
- package/Runtime/Input/Base.meta +3 -0
- package/Runtime/Input/Components/DragInput.cs +44 -0
- package/Runtime/Input/Components/DragInput.cs.meta +11 -0
- package/Runtime/Input/Components/HoldInput.cs +75 -0
- package/Runtime/Input/Components/HoldInput.cs.meta +12 -0
- package/Runtime/Input/Components/SwipeInput.cs +45 -0
- package/Runtime/Input/Components/SwipeInput.cs.meta +12 -0
- package/Runtime/Input/Components/TouchInput.cs +31 -0
- package/Runtime/Input/Components/TouchInput.cs.meta +11 -0
- package/Runtime/Input/Components.meta +8 -0
- package/Runtime/Input.meta +8 -0
- package/Runtime/MagicTilesCore.asmdef +24 -0
- package/Runtime/MagicTilesCore.asmdef.meta +7 -0
- package/Runtime/MoodChange/AdjustHue.ComponentInfo.cs +12 -0
- package/Runtime/MoodChange/AdjustHue.ComponentInfo.cs.meta +3 -0
- package/Runtime/MoodChange/AdjustHue.MaterialInfo.cs +115 -0
- package/Runtime/MoodChange/AdjustHue.MaterialInfo.cs.meta +3 -0
- package/Runtime/MoodChange/AdjustHue.ParticleSystemInfo.cs +36 -0
- package/Runtime/MoodChange/AdjustHue.ParticleSystemInfo.cs.meta +3 -0
- package/Runtime/MoodChange/AdjustHue.SpriteRendererInfo.cs +28 -0
- package/Runtime/MoodChange/AdjustHue.SpriteRendererInfo.cs.meta +3 -0
- package/Runtime/MoodChange/AdjustHue.TrailRendererInfo.cs +37 -0
- package/Runtime/MoodChange/AdjustHue.TrailRendererInfo.cs.meta +3 -0
- package/Runtime/MoodChange/AdjustHue.cs +219 -0
- package/Runtime/MoodChange/AdjustHue.cs.meta +11 -0
- package/Runtime/MoodChange/ColorHueExtensions.cs +227 -0
- package/Runtime/MoodChange/ColorHueExtensions.cs.meta +3 -0
- package/Runtime/MoodChange/HueCache.cs +167 -0
- package/Runtime/MoodChange/HueCache.cs.meta +11 -0
- package/Runtime/MoodChange/MoodChange.cs +52 -0
- package/Runtime/MoodChange/MoodChange.cs.meta +3 -0
- package/Runtime/MoodChange.meta +3 -0
- package/Runtime/Physics/TriggerCallback.cs +21 -0
- package/Runtime/Physics/TriggerCallback.cs.meta +3 -0
- package/Runtime/Physics.meta +8 -0
- package/Runtime/Preset/AudioSourcePlayer/AudioSourcePlayer.cs +153 -0
- package/Runtime/Preset/AudioSourcePlayer/AudioSourcePlayer.cs.meta +11 -0
- package/Runtime/Preset/AudioSourcePlayer/AudioSourcePlayer.prefab +145 -0
- package/Runtime/Preset/AudioSourcePlayer/AudioSourcePlayer.prefab.meta +7 -0
- package/Runtime/Preset/AudioSourcePlayer.meta +8 -0
- package/Runtime/Preset/AudioTimeText/AudioTimeText.cs +22 -0
- package/Runtime/Preset/AudioTimeText/AudioTimeText.cs.meta +11 -0
- package/Runtime/Preset/AudioTimeText/AudioTimeText.prefab +188 -0
- package/Runtime/Preset/AudioTimeText/AudioTimeText.prefab.meta +7 -0
- package/Runtime/Preset/AudioTimeText.meta +8 -0
- package/Runtime/Preset/ParticleSystemPlayer/ParticleSystemPlayer.cs +32 -0
- package/Runtime/Preset/ParticleSystemPlayer/ParticleSystemPlayer.cs.meta +11 -0
- package/Runtime/Preset/ParticleSystemPlayer.meta +8 -0
- package/Runtime/Preset/RendererAlpha.cs +56 -0
- package/Runtime/Preset/RendererAlpha.cs.meta +11 -0
- package/Runtime/Preset/ScoreText/ScoreText.anim +198 -0
- package/Runtime/Preset/ScoreText/ScoreText.anim.meta +8 -0
- package/Runtime/Preset/ScoreText/ScoreText.cs +32 -0
- package/Runtime/Preset/ScoreText/ScoreText.cs.meta +11 -0
- package/Runtime/Preset/ScoreText/ScoreText_2D.prefab +170 -0
- package/Runtime/Preset/ScoreText/ScoreText_2D.prefab.meta +7 -0
- package/Runtime/Preset/ScoreText/ScoreText_3D.prefab +206 -0
- package/Runtime/Preset/ScoreText/ScoreText_3D.prefab.meta +7 -0
- package/Runtime/Preset/ScoreText.meta +8 -0
- package/Runtime/Preset/StartHint/StartHint.cs +26 -0
- package/Runtime/Preset/StartHint/StartHint.cs.meta +3 -0
- package/Runtime/Preset/StartHint.meta +8 -0
- package/Runtime/Preset/WowText/WowText.cs +38 -0
- package/Runtime/Preset/WowText/WowText.cs.meta +3 -0
- package/Runtime/Preset/WowText.meta +8 -0
- package/Runtime/Preset.meta +8 -0
- package/Runtime/Rhythm/Components/Controls.meta +8 -0
- package/Runtime/Rhythm/Components/Helper/CameraFollow.cs +28 -0
- package/Runtime/Rhythm/Components/Helper/CameraFollow.cs.meta +11 -0
- package/Runtime/Rhythm/Components/Helper/MeshSpriteSorter.cs +89 -0
- package/Runtime/Rhythm/Components/Helper/MeshSpriteSorter.cs.meta +11 -0
- package/Runtime/Rhythm/Components/Helper/RecycleLayoutZ.cs +74 -0
- package/Runtime/Rhythm/Components/Helper/RecycleLayoutZ.cs.meta +11 -0
- package/Runtime/Rhythm/Components/Helper.meta +8 -0
- package/Runtime/Rhythm/Components.meta +8 -0
- package/Runtime/Rhythm/Core/GameMode.cs +10 -0
- package/Runtime/Rhythm/Core/GameMode.cs.meta +3 -0
- package/Runtime/Rhythm/Core/IAudioPlayer.cs +16 -0
- package/Runtime/Rhythm/Core/IAudioPlayer.cs.meta +3 -0
- package/Runtime/Rhythm/Core/IRhythmBehaviour.cs +10 -0
- package/Runtime/Rhythm/Core/IRhythmBehaviour.cs.meta +3 -0
- package/Runtime/Rhythm/Core/RhythmBehaviour.cs +57 -0
- package/Runtime/Rhythm/Core/RhythmBehaviour.cs.meta +11 -0
- package/Runtime/Rhythm/Core/RhythmDebug.cs +48 -0
- package/Runtime/Rhythm/Core/RhythmDebug.cs.meta +11 -0
- package/Runtime/Rhythm/Core/RhythmGameT.cs +323 -0
- package/Runtime/Rhythm/Core/RhythmGameT.cs.meta +3 -0
- package/Runtime/Rhythm/Core/RhythmMatch.cs +65 -0
- package/Runtime/Rhythm/Core/RhythmMatch.cs.meta +11 -0
- package/Runtime/Rhythm/Core/RhythmTile.cs +77 -0
- package/Runtime/Rhythm/Core/RhythmTile.cs.meta +3 -0
- package/Runtime/Rhythm/Core/RhythmTileHandler.cs +59 -0
- package/Runtime/Rhythm/Core/RhythmTileHandler.cs.meta +3 -0
- package/Runtime/Rhythm/Core.meta +8 -0
- package/Runtime/Rhythm/Extensions/CollectionExtensions.cs +120 -0
- package/Runtime/Rhythm/Extensions/CollectionExtensions.cs.meta +11 -0
- package/Runtime/Rhythm/Extensions/ColliderExtensions.cs +27 -0
- package/Runtime/Rhythm/Extensions/ColliderExtensions.cs.meta +11 -0
- package/Runtime/Rhythm/Extensions/GameHandlerExtensions.cs +56 -0
- package/Runtime/Rhythm/Extensions/GameHandlerExtensions.cs.meta +11 -0
- package/Runtime/Rhythm/Extensions/GameObjectExtensions.cs +61 -0
- package/Runtime/Rhythm/Extensions/GameObjectExtensions.cs.meta +11 -0
- package/Runtime/Rhythm/Extensions/InputDirectionExtensions.cs +76 -0
- package/Runtime/Rhythm/Extensions/InputDirectionExtensions.cs.meta +11 -0
- package/Runtime/Rhythm/Extensions/MTCListExtensions.cs +127 -0
- package/Runtime/Rhythm/Extensions/MTCListExtensions.cs.meta +11 -0
- package/Runtime/Rhythm/Extensions/MeshRendererExtensions.cs +81 -0
- package/Runtime/Rhythm/Extensions/MeshRendererExtensions.cs.meta +11 -0
- package/Runtime/Rhythm/Extensions/ParticleSystemExtensions.cs +54 -0
- package/Runtime/Rhythm/Extensions/ParticleSystemExtensions.cs.meta +11 -0
- package/Runtime/Rhythm/Extensions.meta +8 -0
- package/Runtime/Rhythm/Game/MTCSongAutoStart.cs +40 -0
- package/Runtime/Rhythm/Game/MTCSongAutoStart.cs.meta +11 -0
- package/Runtime/Rhythm/Game/RhythmConfig.cs +68 -0
- package/Runtime/Rhythm/Game/RhythmConfig.cs.meta +11 -0
- package/Runtime/Rhythm/Game/RhythmContext.Api.cs +533 -0
- package/Runtime/Rhythm/Game/RhythmContext.Api.cs.meta +11 -0
- package/Runtime/Rhythm/Game/RhythmContext.Dev.cs +121 -0
- package/Runtime/Rhythm/Game/RhythmContext.Dev.cs.meta +11 -0
- package/Runtime/Rhythm/Game/RhythmContext.Initialization.cs +114 -0
- package/Runtime/Rhythm/Game/RhythmContext.Initialization.cs.meta +11 -0
- package/Runtime/Rhythm/Game/RhythmContext.Runtime.cs +126 -0
- package/Runtime/Rhythm/Game/RhythmContext.Runtime.cs.meta +11 -0
- package/Runtime/Rhythm/Game/RhythmContext.State.cs +221 -0
- package/Runtime/Rhythm/Game/RhythmContext.State.cs.meta +11 -0
- package/Runtime/Rhythm/Game/RhythmContext.Tile.cs +90 -0
- package/Runtime/Rhythm/Game/RhythmContext.Tile.cs.meta +11 -0
- package/Runtime/Rhythm/Game/RhythmContext.TimeMachine.cs +315 -0
- package/Runtime/Rhythm/Game/RhythmContext.TimeMachine.cs.meta +11 -0
- package/Runtime/Rhythm/Game/RhythmContext.cs +312 -0
- package/Runtime/Rhythm/Game/RhythmContext.cs.meta +11 -0
- package/Runtime/Rhythm/Game/RhythmContextExtensions.cs +91 -0
- package/Runtime/Rhythm/Game/RhythmContextExtensions.cs.meta +11 -0
- package/Runtime/Rhythm/Game/Tile/ITileProgress.cs +7 -0
- package/Runtime/Rhythm/Game/Tile/ITileProgress.cs.meta +3 -0
- package/Runtime/Rhythm/Game/Tile/TileContext.cs +194 -0
- package/Runtime/Rhythm/Game/Tile/TileContext.cs.meta +11 -0
- package/Runtime/Rhythm/Game/Tile.meta +3 -0
- package/Runtime/Rhythm/Game.meta +3 -0
- package/Runtime/Rhythm/Math/Parabol.cs +35 -0
- package/Runtime/Rhythm/Math/Parabol.cs.meta +11 -0
- package/Runtime/Rhythm/Math.meta +8 -0
- package/Runtime/Rhythm/System/Event/GameEvent.cs +82 -0
- package/Runtime/Rhythm/System/Event/GameEvent.cs.meta +3 -0
- package/Runtime/Rhythm/System/Event.meta +8 -0
- package/Runtime/Rhythm/System/Meta/MetaLogic.cs +121 -0
- package/Runtime/Rhythm/System/Meta/MetaLogic.cs.meta +11 -0
- package/Runtime/Rhythm/System/Meta/VisualSpeedMeta.cs +132 -0
- package/Runtime/Rhythm/System/Meta/VisualSpeedMeta.cs.meta +11 -0
- package/Runtime/Rhythm/System/Meta.meta +8 -0
- package/Runtime/Rhythm/System/SongData/ListSongNote.cs +45 -0
- package/Runtime/Rhythm/System/SongData/ListSongNote.cs.meta +3 -0
- package/Runtime/Rhythm/System/SongData.meta +8 -0
- package/Runtime/Rhythm/System/StateMachine/RhythmStateMachine.State.cs +22 -0
- package/Runtime/Rhythm/System/StateMachine/RhythmStateMachine.State.cs.meta +11 -0
- package/Runtime/Rhythm/System/StateMachine/RhythmStateMachine.cs +138 -0
- package/Runtime/Rhythm/System/StateMachine/RhythmStateMachine.cs.meta +11 -0
- package/Runtime/Rhythm/System/StateMachine.meta +8 -0
- package/Runtime/Rhythm/System/TimeKnot/ListTimeKnots.cs +135 -0
- package/Runtime/Rhythm/System/TimeKnot/ListTimeKnots.cs.meta +11 -0
- package/Runtime/Rhythm/System/TimeKnot.meta +8 -0
- package/Runtime/Rhythm/System/TimeMachine/MTCTimeInterpolator.cs +365 -0
- package/Runtime/Rhythm/System/TimeMachine/MTCTimeInterpolator.cs.meta +11 -0
- package/Runtime/Rhythm/System/TimeMachine/MTCTimeMachine.TimeMarker.cs +107 -0
- package/Runtime/Rhythm/System/TimeMachine/MTCTimeMachine.TimeMarker.cs.meta +3 -0
- package/Runtime/Rhythm/System/TimeMachine/MTCTimeMachine.TimeNode.cs +14 -0
- package/Runtime/Rhythm/System/TimeMachine/MTCTimeMachine.TimeNode.cs.meta +3 -0
- package/Runtime/Rhythm/System/TimeMachine/MTCTimeMachine.TimeSpanNode.cs +21 -0
- package/Runtime/Rhythm/System/TimeMachine/MTCTimeMachine.TimeSpanNode.cs.meta +3 -0
- package/Runtime/Rhythm/System/TimeMachine/MTCTimeMachine.ZLaneSpeed.cs +28 -0
- package/Runtime/Rhythm/System/TimeMachine/MTCTimeMachine.ZLaneSpeed.cs.meta +3 -0
- package/Runtime/Rhythm/System/TimeMachine/MTCTimeMachine.cs +131 -0
- package/Runtime/Rhythm/System/TimeMachine/MTCTimeMachine.cs.meta +11 -0
- package/Runtime/Rhythm/System/TimeMachine.meta +8 -0
- package/Runtime/Rhythm/System/VisualKnot/VisualKnotLogic.cs +160 -0
- package/Runtime/Rhythm/System/VisualKnot/VisualKnotLogic.cs.meta +11 -0
- package/Runtime/Rhythm/System/VisualKnot.meta +8 -0
- package/Runtime/Rhythm/System/VisualWarp/IVisualWarp.cs +10 -0
- package/Runtime/Rhythm/System/VisualWarp/IVisualWarp.cs.meta +11 -0
- package/Runtime/Rhythm/System/VisualWarp/LinearVisualWarp.cs +27 -0
- package/Runtime/Rhythm/System/VisualWarp/LinearVisualWarp.cs.meta +11 -0
- package/Runtime/Rhythm/System/VisualWarp.meta +8 -0
- package/Runtime/Rhythm/System.meta +8 -0
- package/Runtime/Rhythm.meta +8 -0
- package/Runtime.meta +8 -0
- package/package.json +12 -0
- package/package.json.meta +7 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# Knot System Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The **Knot System** provides efficient time-based lookup and interpolation by caching expensive calculations once. Used internally by MetaLogic, VisualSpeedMeta, and VisualKnotLogic.
|
|
6
|
+
|
|
7
|
+
**Key Concept**: Knot = Cached control point at a specific time
|
|
8
|
+
|
|
9
|
+
## Core Classes
|
|
10
|
+
|
|
11
|
+
### TimeKnot
|
|
12
|
+
|
|
13
|
+
```csharp
|
|
14
|
+
// From: ListTimeKnots.cs
|
|
15
|
+
public abstract class TimeKnot
|
|
16
|
+
{
|
|
17
|
+
public int knotIdx; // Index in sorted list
|
|
18
|
+
public float time; // Time in seconds
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### ListTimeKnots<T>
|
|
23
|
+
|
|
24
|
+
```csharp
|
|
25
|
+
// From: ListTimeKnots.cs
|
|
26
|
+
public class ListTimeKnots<T> where T : TimeKnot
|
|
27
|
+
{
|
|
28
|
+
public readonly List<T> _knots = new();
|
|
29
|
+
|
|
30
|
+
public (T prevKnot, T nextKnot, float percent) InterpolateKnot(float time)
|
|
31
|
+
{
|
|
32
|
+
int idx = _knots.Count > 32 ? BinarySearch(time) : LinearSearch(time);
|
|
33
|
+
// Returns: previous knot, next knot, interpolation percent (0-1)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
protected void Sort()
|
|
37
|
+
{
|
|
38
|
+
_knots.Sort((a, b) => a.time.CompareTo(b.time));
|
|
39
|
+
for (int i = 0; i < _knots.Count; i++)
|
|
40
|
+
{
|
|
41
|
+
_knots[i].knotIdx = i;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Performance**:
|
|
48
|
+
- ≤32 knots: Linear search O(n)
|
|
49
|
+
- \>32 knots: Binary search O(log n)
|
|
50
|
+
|
|
51
|
+
## MetaInfo (Meta System)
|
|
52
|
+
|
|
53
|
+
```csharp
|
|
54
|
+
// From: MetaLogic.cs
|
|
55
|
+
public class MetaInfo : TimeKnot
|
|
56
|
+
{
|
|
57
|
+
public float duration; // Duration until next meta
|
|
58
|
+
public string rawValue; // Original value
|
|
59
|
+
public string value; // Parsed value
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public class MetaLogic : ListTimeKnots<MetaInfo>
|
|
63
|
+
{
|
|
64
|
+
public string GetValueAtTime(float time)
|
|
65
|
+
{
|
|
66
|
+
var (prev, next, percent) = InterpolateKnot(time);
|
|
67
|
+
var active = prev ?? next;
|
|
68
|
+
return active?.value;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## VisualSpeedMeta (Speed System)
|
|
74
|
+
|
|
75
|
+
```csharp
|
|
76
|
+
// From: VisualSpeedMeta.cs
|
|
77
|
+
public class VisualSpeedMeta : MetaLogic
|
|
78
|
+
{
|
|
79
|
+
public class Info : MetaInfo
|
|
80
|
+
{
|
|
81
|
+
public float speed; // Speed value
|
|
82
|
+
public float distance; // Accumulated distance (cached)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public float GetSpeedAtTime(float time)
|
|
86
|
+
{
|
|
87
|
+
var (prev, next, percent) = InterpolateKnot<Info>(time);
|
|
88
|
+
return (prev ?? next).speed;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public float GetDistanceAtTime(float time)
|
|
92
|
+
{
|
|
93
|
+
var (prev, next, percent) = InterpolateKnot<Info>(time);
|
|
94
|
+
if (prev == null) return 0f;
|
|
95
|
+
if (next == null) return prev.distance + (time - prev.time) * prev.speed;
|
|
96
|
+
return Mathf.Lerp(prev.distance, next.distance, percent);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## VisualKnot (Position System)
|
|
102
|
+
|
|
103
|
+
```csharp
|
|
104
|
+
// From: VisualKnotLogic.cs
|
|
105
|
+
public class VisualKnot : TimeKnot
|
|
106
|
+
{
|
|
107
|
+
public float lane;
|
|
108
|
+
public int noteIdx;
|
|
109
|
+
public int controlIdx; // -1 for note, >=0 for control point
|
|
110
|
+
public string type; // "jump", "slide", "land", etc.
|
|
111
|
+
|
|
112
|
+
// ⭐ PRE-CALCULATED DATA (calculated once, used many times)
|
|
113
|
+
public float zPos; // From context.config.GetZ(time)
|
|
114
|
+
public Vector3 warpedPosition; // With visual speed & warp applied
|
|
115
|
+
public Quaternion warpedRotation; // With visual warp applied
|
|
116
|
+
|
|
117
|
+
public NoteBase note;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public class VisualKnotLogic : ListTimeKnots<VisualKnot>
|
|
121
|
+
{
|
|
122
|
+
// ⭐ CRITICAL: Pre-calculates ALL positions once
|
|
123
|
+
public void CalculateWarpedPositions(RhythmContext context)
|
|
124
|
+
{
|
|
125
|
+
for (var i = 0; i < _knots.Count; i++)
|
|
126
|
+
{
|
|
127
|
+
var knot = _knots[i];
|
|
128
|
+
knot.zPos = context.config.GetZ(knot.time);
|
|
129
|
+
var (warpedPos, warpedRot) = context.GetWarped(knot.time, knot.lane);
|
|
130
|
+
knot.warpedPosition = warpedPos;
|
|
131
|
+
knot.warpedRotation = warpedRot;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public Vector2 GetPositionAtTime(float time)
|
|
136
|
+
{
|
|
137
|
+
var (prevKnot, nextKnot, percent) = InterpolateKnot(time);
|
|
138
|
+
// Interpolates between cached warpedPosition
|
|
139
|
+
return Vector2.Lerp(prevPos, nextPos, percent);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Object Pooling
|
|
145
|
+
|
|
146
|
+
```csharp
|
|
147
|
+
// From: VisualKnotLogic.cs
|
|
148
|
+
private static ObjectPool<VisualKnot> _knotPool = new ObjectPool<VisualKnot>(
|
|
149
|
+
createFunc: () => new VisualKnot(),
|
|
150
|
+
defaultCapacity: 500,
|
|
151
|
+
maxSize: 2000
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
public static VisualKnot GetKnotFromPool() => _knotPool.Get();
|
|
155
|
+
public static void ReleaseKnotToPool(VisualKnot knot) => _knotPool.Release(knot);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Template Examples
|
|
159
|
+
|
|
160
|
+
### Dancing Road (DR3)
|
|
161
|
+
|
|
162
|
+
```csharp
|
|
163
|
+
// From: DRGame.Knot.cs
|
|
164
|
+
public override void InjectKnots(List<VisualKnot> knots, SongNote note, bool isVisible)
|
|
165
|
+
{
|
|
166
|
+
if (!isVisible) return;
|
|
167
|
+
|
|
168
|
+
if (IsValidLane(note.lane) && !IsFakeNote(note))
|
|
169
|
+
{
|
|
170
|
+
knots.Add(CreateKnot(note, -1)); // Note knot
|
|
171
|
+
|
|
172
|
+
for (var i = 0; i < note.controls.Count; i++)
|
|
173
|
+
{
|
|
174
|
+
knots.Add(CreateKnot(note, i)); // Control point knots
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (note.type == "push")
|
|
179
|
+
{
|
|
180
|
+
InjectKnot_TilePush(knots, note);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
private VisualKnot CreateKnot(SongNote note, int controlIdx)
|
|
185
|
+
{
|
|
186
|
+
var knot = VisualKnotLogic.GetKnotFromPool();
|
|
187
|
+
knot.time = controlIdx < 0 ? note.time : note.controls[controlIdx].time;
|
|
188
|
+
knot.lane = controlIdx < 0 ? note.lane : note.controls[controlIdx].lane;
|
|
189
|
+
knot.noteIdx = note.index;
|
|
190
|
+
knot.controlIdx = controlIdx;
|
|
191
|
+
knot.type = GetKnotType(note, controlIdx);
|
|
192
|
+
knot.note = note;
|
|
193
|
+
return knot;
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### TilesHop (TH3)
|
|
198
|
+
|
|
199
|
+
```csharp
|
|
200
|
+
// From: THGame.Knots.cs
|
|
201
|
+
private void InjectKnot_Circular(List<VisualKnot> knots, SongNote note)
|
|
202
|
+
{
|
|
203
|
+
var lane = note.lane < 3 ? 1 : 5;
|
|
204
|
+
|
|
205
|
+
// First jump
|
|
206
|
+
var knot1 = VisualKnotLogic.GetKnotFromPool();
|
|
207
|
+
knot1.time = note.time;
|
|
208
|
+
knot1.lane = lane;
|
|
209
|
+
knot1.type = "jump";
|
|
210
|
+
knot1.noteIdx = note.index;
|
|
211
|
+
knots.Add(knot1);
|
|
212
|
+
|
|
213
|
+
// Second jump
|
|
214
|
+
var knot2 = VisualKnotLogic.GetKnotFromPool();
|
|
215
|
+
knot2.time = note.time + config.circular.timeDistance;
|
|
216
|
+
knot2.lane = lane;
|
|
217
|
+
knot2.type = "jump";
|
|
218
|
+
knot2.noteIdx = note.index;
|
|
219
|
+
knots.Add(knot2);
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Performance Benefits
|
|
224
|
+
|
|
225
|
+
**Without Knot System** (every frame):
|
|
226
|
+
```csharp
|
|
227
|
+
// ❌ EXPENSIVE - 60+ times per second
|
|
228
|
+
float z = context.config.GetZ(time);
|
|
229
|
+
var (pos, rot) = context.GetWarped(time, lane);
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**With Knot System** (once at start):
|
|
233
|
+
```csharp
|
|
234
|
+
// ✅ FAST - calculate once, cache forever
|
|
235
|
+
knot.zPos = context.config.GetZ(knot.time);
|
|
236
|
+
knot.warpedPosition = context.GetWarped(knot.time, knot.lane);
|
|
237
|
+
|
|
238
|
+
// Then every frame - just interpolate
|
|
239
|
+
Vector3.Lerp(prevKnot.warpedPosition, nextKnot.warpedPosition, percent);
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## System Hierarchy
|
|
243
|
+
|
|
244
|
+
```mermaid
|
|
245
|
+
classDiagram
|
|
246
|
+
TimeKnot <|-- MetaInfo
|
|
247
|
+
TimeKnot <|-- VisualKnot
|
|
248
|
+
ListTimeKnots~T~ <|-- MetaLogic
|
|
249
|
+
ListTimeKnots~T~ <|-- VisualKnotLogic
|
|
250
|
+
MetaLogic <|-- VisualSpeedMeta
|
|
251
|
+
|
|
252
|
+
class TimeKnot {
|
|
253
|
+
+int knotIdx
|
|
254
|
+
+float time
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
class ListTimeKnots~T~ {
|
|
258
|
+
+List~T~ _knots
|
|
259
|
+
+InterpolateKnot(time)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
class MetaInfo {
|
|
263
|
+
+float duration
|
|
264
|
+
+string value
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
class VisualKnot {
|
|
268
|
+
+float lane
|
|
269
|
+
+int noteIdx
|
|
270
|
+
+float zPos
|
|
271
|
+
+Vector3 warpedPosition
|
|
272
|
+
+Quaternion warpedRotation
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
class MetaLogic {
|
|
276
|
+
+string id
|
|
277
|
+
+GetValueAtTime(time)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
class VisualSpeedMeta {
|
|
281
|
+
+GetSpeedAtTime(time)
|
|
282
|
+
+GetDistanceAtTime(time)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
class VisualKnotLogic {
|
|
286
|
+
+CalculateWarpedPositions()
|
|
287
|
+
+GetPositionAtTime(time)
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Summary
|
|
292
|
+
|
|
293
|
+
The Knot System provides:
|
|
294
|
+
|
|
295
|
+
- ✅ **Efficient lookup**: O(log n) binary search for >32 knots
|
|
296
|
+
- ✅ **Cached calculations**: Pre-compute expensive operations once
|
|
297
|
+
- ✅ **Smooth interpolation**: Linear interpolation between cached points
|
|
298
|
+
- ✅ **Memory efficient**: Object pooling for VisualKnots
|
|
299
|
+
|
|
300
|
+
**Used internally by**:
|
|
301
|
+
- `MetaLogic` - Game parameter changes
|
|
302
|
+
- `VisualSpeedMeta` - Speed and distance calculations
|
|
303
|
+
- `VisualKnotLogic` - Position and rotation caching
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
**See Also**:
|
|
308
|
+
- [Meta-System-Guide.md](Meta-System-Guide.md) - Meta system details
|
|
309
|
+
- [RhythmCore-Architecture.md](RhythmCore-Architecture.md) - Overall architecture
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# Meta System Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The **Meta System** manages game parameter changes over time using the Knot System for efficient lookup. Meta data comes from song notes and controls speed, visual effects, and gameplay mechanics.
|
|
6
|
+
|
|
7
|
+
**Key Concept**: Meta = Time-stamped game parameter (speed, color, effect, etc.)
|
|
8
|
+
|
|
9
|
+
## Core Classes
|
|
10
|
+
|
|
11
|
+
### MetaInfo
|
|
12
|
+
|
|
13
|
+
```csharp
|
|
14
|
+
// From: MetaLogic.cs
|
|
15
|
+
public class MetaInfo : TimeKnot
|
|
16
|
+
{
|
|
17
|
+
public float duration; // Duration until next meta
|
|
18
|
+
public string rawValue; // Original value from song
|
|
19
|
+
public string value; // Parsed value
|
|
20
|
+
public float endTime => time + duration;
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### MetaLogic
|
|
25
|
+
|
|
26
|
+
```csharp
|
|
27
|
+
// From: MetaLogic.cs
|
|
28
|
+
public class MetaLogic : ListTimeKnots<MetaInfo>
|
|
29
|
+
{
|
|
30
|
+
public string id { get; } // Meta ID (e.g., "speed", "color")
|
|
31
|
+
public MetaInfo currentMeta { get; protected set; } // Active meta now
|
|
32
|
+
public MetaInfo nextMeta { get; protected set; } // Next meta change
|
|
33
|
+
|
|
34
|
+
public void AddMetaInfo(float time, string value)
|
|
35
|
+
{
|
|
36
|
+
if (_knots.Count == 0 && time > 0)
|
|
37
|
+
{
|
|
38
|
+
base.AddKnot(CreateMetaInfo(0f, value)); // Add first knot at t=0
|
|
39
|
+
}
|
|
40
|
+
base.AddKnot(CreateMetaInfo(time, value));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public virtual bool Update(float time)
|
|
44
|
+
{
|
|
45
|
+
var (prev, next, percent) = InterpolateKnot(time);
|
|
46
|
+
var activeNode = prev ?? next;
|
|
47
|
+
currentMeta = activeNode;
|
|
48
|
+
nextMeta = next;
|
|
49
|
+
return hasChanged;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public string GetValueAtTime(float time)
|
|
53
|
+
{
|
|
54
|
+
var (prev, next, percent) = InterpolateKnot(time);
|
|
55
|
+
var active = prev ?? next;
|
|
56
|
+
return active?.value;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## VisualSpeedMeta
|
|
62
|
+
|
|
63
|
+
Built-in meta for controlling visual speed and calculating accumulated distance:
|
|
64
|
+
|
|
65
|
+
```csharp
|
|
66
|
+
// From: VisualSpeedMeta.cs
|
|
67
|
+
public class VisualSpeedMeta : MetaLogic
|
|
68
|
+
{
|
|
69
|
+
public class Info : MetaInfo
|
|
70
|
+
{
|
|
71
|
+
public float speed; // Speed value
|
|
72
|
+
public float distance; // Accumulated distance
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public float GetSpeedAtTime(float time)
|
|
76
|
+
{
|
|
77
|
+
var (prev, next, percent) = InterpolateKnot<Info>(time);
|
|
78
|
+
var active = prev ?? next;
|
|
79
|
+
return active.speed;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public float GetDistanceAtTime(float time)
|
|
83
|
+
{
|
|
84
|
+
var (prev, next, percent) = InterpolateKnot<Info>(time);
|
|
85
|
+
if (prev == null) return 0f;
|
|
86
|
+
if (next == null) return prev.distance + (time - prev.time) * prev.speed;
|
|
87
|
+
return Mathf.Lerp(prev.distance, next.distance, percent);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
void CalculateDistance()
|
|
91
|
+
{
|
|
92
|
+
var prev = (Info)_knots[0];
|
|
93
|
+
prev.distance = 0f;
|
|
94
|
+
for (var i = 1; i < _knots.Count; i++)
|
|
95
|
+
{
|
|
96
|
+
var cur = (Info)_knots[i];
|
|
97
|
+
cur.distance = prev.distance + prev.duration * prev.speed;
|
|
98
|
+
prev = cur;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## How It Works
|
|
105
|
+
|
|
106
|
+
### 1. Song Data Contains Meta
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"notes": [
|
|
111
|
+
{"time": 0, "lane": 1, "type": "short"},
|
|
112
|
+
{
|
|
113
|
+
"time": 4,
|
|
114
|
+
"lane": 1,
|
|
115
|
+
"type": "meta",
|
|
116
|
+
"metas": [
|
|
117
|
+
{"key": "speed", "value": "6"},
|
|
118
|
+
{"key": "bgColor", "value": "red"}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 2. RhythmContext Processes Meta
|
|
126
|
+
|
|
127
|
+
```csharp
|
|
128
|
+
// From: RhythmContext.Runtime.cs
|
|
129
|
+
private void ProcessNoteMetas(List<NoteMeta> metas, float time)
|
|
130
|
+
{
|
|
131
|
+
foreach (var meta in metas)
|
|
132
|
+
{
|
|
133
|
+
GetOrCreateMetaLogic(meta.key).AddMetaInfo(time, meta.value);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private MetaLogic GetOrCreateMetaLogic(string key)
|
|
138
|
+
{
|
|
139
|
+
if (gameMetas.TryGetValue(key, out var logic)) return logic;
|
|
140
|
+
|
|
141
|
+
// Create new MetaLogic or use custom creator
|
|
142
|
+
logic = customMetaCreators.TryGetValue(key, out var creator)
|
|
143
|
+
? creator()
|
|
144
|
+
: new MetaLogic(key);
|
|
145
|
+
|
|
146
|
+
gameMetas[key] = logic;
|
|
147
|
+
return logic;
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### 3. Update During Gameplay
|
|
152
|
+
|
|
153
|
+
```csharp
|
|
154
|
+
// Every frame, RhythmContext updates all meta:
|
|
155
|
+
foreach (var meta in gameMetas.Values)
|
|
156
|
+
{
|
|
157
|
+
bool changed = meta.Update(currentTime);
|
|
158
|
+
if (changed)
|
|
159
|
+
{
|
|
160
|
+
// Dispatch META_CHANGED event
|
|
161
|
+
Dispatch(GameEvent.META_CHANGED, meta.id, meta.currentMeta.value);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Custom Meta Types
|
|
167
|
+
|
|
168
|
+
### Creating Custom Meta
|
|
169
|
+
|
|
170
|
+
```csharp
|
|
171
|
+
public class CustomMeta : MetaLogic
|
|
172
|
+
{
|
|
173
|
+
public CustomMeta() : base("customId") { }
|
|
174
|
+
|
|
175
|
+
protected override MetaInfo CreateMetaInfo(float time, string value)
|
|
176
|
+
{
|
|
177
|
+
// Parse and validate value
|
|
178
|
+
return new MetaInfo(time, processedValue);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Registering Custom Meta
|
|
184
|
+
|
|
185
|
+
```csharp
|
|
186
|
+
// From: RhythmContext.Runtime.cs - registration
|
|
187
|
+
public void RegisterMetaCreator<T>(string key) where T: MetaLogic, new()
|
|
188
|
+
{
|
|
189
|
+
customMetaCreators[key] = () => new T();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Usage:
|
|
193
|
+
context.RegisterMetaCreator<CustomMeta>("customId");
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## System Hierarchy
|
|
197
|
+
|
|
198
|
+
```mermaid
|
|
199
|
+
classDiagram
|
|
200
|
+
TimeKnot <|-- MetaInfo
|
|
201
|
+
ListTimeKnots~MetaInfo~ <|-- MetaLogic
|
|
202
|
+
MetaLogic <|-- VisualSpeedMeta
|
|
203
|
+
MetaLogic <|-- CustomMeta
|
|
204
|
+
|
|
205
|
+
class TimeKnot {
|
|
206
|
+
+int knotIdx
|
|
207
|
+
+float time
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
class MetaInfo {
|
|
211
|
+
+float duration
|
|
212
|
+
+string rawValue
|
|
213
|
+
+string value
|
|
214
|
+
+float endTime
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
class MetaLogic {
|
|
218
|
+
+string id
|
|
219
|
+
+MetaInfo currentMeta
|
|
220
|
+
+MetaInfo nextMeta
|
|
221
|
+
+AddMetaInfo(time, value)
|
|
222
|
+
+Update(time) bool
|
|
223
|
+
+GetValueAtTime(time) string
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
class VisualSpeedMeta {
|
|
227
|
+
+GetSpeedAtTime(time) float
|
|
228
|
+
+GetDistanceAtTime(time) float
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Summary
|
|
233
|
+
|
|
234
|
+
The Meta System provides:
|
|
235
|
+
|
|
236
|
+
- ✅ **Time-based parameters**: Control game parameters at specific times
|
|
237
|
+
- ✅ **Efficient lookup**: Uses Knot System (O(log n) for >32 knots)
|
|
238
|
+
- ✅ **Automatic processing**: RhythmContext handles meta from song data
|
|
239
|
+
- ✅ **Extensible**: Create custom meta types for any game parameter
|
|
240
|
+
- ✅ **Event-driven**: META_CHANGED event when values change
|
|
241
|
+
|
|
242
|
+
**Built-in Meta**:
|
|
243
|
+
- `VisualSpeedMeta` - Controls visual speed and distance calculations
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
**See Also**:
|
|
248
|
+
- [Knot-System-Guide.md](Knot-System-Guide.md) - Knot system internals
|
|
249
|
+
- [RhythmCore-Architecture.md](RhythmCore-Architecture.md) - Overall architecture
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# RhythmCore New Game Template - Essential Steps
|
|
2
|
+
|
|
3
|
+
## 🚀 **ESSENTIAL CORE SETUP** (Must Do First)
|
|
4
|
+
|
|
5
|
+
### 1. Create Core Classes (30 minutes)
|
|
6
|
+
- [ ] **Main Game Class** extending `RhythmGameT<TConfig, TMatch>`
|
|
7
|
+
- [ ] **Game Config Class** extending `RhythmConfig` with `[CreateAssetMenu]`
|
|
8
|
+
- [ ] **Match Data Class** extending `RhythmMatch` (optional but recommended)
|
|
9
|
+
- [ ] **Base Tile Class** extending `RhythmTile`
|
|
10
|
+
|
|
11
|
+
### 2. Create Essential Assets (15 minutes)
|
|
12
|
+
- [ ] **RhythmContext ScriptableObject** - Central coordinator
|
|
13
|
+
- [ ] **GameConfig ScriptableObject** - Game settings
|
|
14
|
+
- [ ] **ListSongNote ScriptableObject** - Song data container
|
|
15
|
+
- [ ] **Link assets**: Context → Config, Context → SongNotes
|
|
16
|
+
|
|
17
|
+
### 3. Setup Scene & Pool (20 minutes)
|
|
18
|
+
- [ ] **Create main scene** with game object + your main game script
|
|
19
|
+
- [ ] **Assign RhythmContext** to game object
|
|
20
|
+
- [ ] **Configure tile pool** in GameConfig with tile prefabs
|
|
21
|
+
- [ ] **Test basic setup** - should compile and run without errors
|
|
22
|
+
|
|
23
|
+
## 🎮 **GAMEPLAY IMPLEMENTATION** (After Core Setup)
|
|
24
|
+
|
|
25
|
+
### 4. Implement Tile Behavior (45 minutes)
|
|
26
|
+
- [ ] **Override `OnAttach()`** - position tile, setup visuals
|
|
27
|
+
- [ ] **Override `RefreshTileStatus()`** - handle None/Touching/End/Missed states
|
|
28
|
+
- [ ] **Add `Update()`** - position tiles based on `context.GetDistanceAtTime()`
|
|
29
|
+
- [ ] **Add input handling** - TouchInput, HoldInput, or SwipeInput components
|
|
30
|
+
|
|
31
|
+
### 5. Configure Game Logic (30 minutes)
|
|
32
|
+
- [ ] **Override `GetMissedThreshold()`** in main game class
|
|
33
|
+
- [ ] **Override `CalculateScore()`** in match data class
|
|
34
|
+
- [ ] **Setup tile pool entries** - id matches SongNote.type, assign prefabs
|
|
35
|
+
- [ ] **Test with sample song data** - create basic notes and verify gameplay
|
|
36
|
+
|
|
37
|
+
### 6. Add Essential UI (20 minutes)
|
|
38
|
+
- [ ] **Score display** using `RhythmBehaviour` + `OnGameScoreChange` event
|
|
39
|
+
- [ ] **Basic game controls** (play/pause/restart)
|
|
40
|
+
- [ ] **Audio setup** - AudioSource component or custom IAudioPlayer
|
|
41
|
+
|
|
42
|
+
## 🔧 **ADVANCED FEATURES** (Optional)
|
|
43
|
+
|
|
44
|
+
### Visual Polish
|
|
45
|
+
- [ ] **Particle effects** for tile hits/misses
|
|
46
|
+
- [ ] **Smooth animations** for tile state changes
|
|
47
|
+
- [ ] **Background elements** and theme system
|
|
48
|
+
- [ ] **Screen size adaptation** using `ISizeListener`
|
|
49
|
+
|
|
50
|
+
### Gameplay Features
|
|
51
|
+
- [ ] **Long note support** with progress tracking
|
|
52
|
+
- [ ] **Special tile types** (swipe, drag, multi-tap)
|
|
53
|
+
- [ ] **Combo system** and accuracy calculation
|
|
54
|
+
- [ ] **Death/rewind system** with `GetDeathTiming()`
|
|
55
|
+
|
|
56
|
+
### Performance & Polish
|
|
57
|
+
- [ ] **Object pooling optimization**
|
|
58
|
+
- [ ] **Audio latency compensation**
|
|
59
|
+
- [ ] **Memory usage profiling**
|
|
60
|
+
- [ ] **Multi-platform testing**
|
|
61
|
+
|
|
62
|
+
## ⚡ **QUICK START TEMPLATE**
|
|
63
|
+
|
|
64
|
+
```csharp
|
|
65
|
+
// 1. YourGame.cs
|
|
66
|
+
public class YourGame : RhythmGameT<YourGameConfig, YourMatchData>
|
|
67
|
+
{
|
|
68
|
+
protected override void Start() { base.Start(); }
|
|
69
|
+
public override float GetMissedThreshold() => 0.5f;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 2. YourGameConfig.cs
|
|
73
|
+
[CreateAssetMenu] public class YourGameConfig : RhythmConfig
|
|
74
|
+
{
|
|
75
|
+
public float laneWidth = 2f;
|
|
76
|
+
public Vector3 GetLanePosition(int lane) => new Vector3((lane-1) * laneWidth, 0, 0);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 3. YourMatchData.cs
|
|
80
|
+
public class YourMatchData : RhythmMatch
|
|
81
|
+
{
|
|
82
|
+
public override void CalculateScore(TileContext tile)
|
|
83
|
+
{
|
|
84
|
+
if (tile.Status == TileStatus.Touching) AddScore(100);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// 4. YourTile.cs
|
|
89
|
+
public class YourTile : RhythmTile
|
|
90
|
+
{
|
|
91
|
+
public override void OnAttach() { UpdatePosition(); }
|
|
92
|
+
void Update() { if (tileContext != null) UpdatePosition(); }
|
|
93
|
+
void UpdatePosition()
|
|
94
|
+
{
|
|
95
|
+
var pos = ((YourGameConfig)context.config).GetLanePosition(tileContext.note.lane);
|
|
96
|
+
pos.z = context.GetDistanceAtTime(tileContext.note.time);
|
|
97
|
+
transform.localPosition = pos;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Total Setup Time: ~2 hours for basic working game**
|