U2C Simulation/View Binding

Fester Simulationstakt und Ansichten, die nur lesen; Nachweis, dass die Partie
bei jeder Bildrate dieselbe ist.

- LuneClock: Akkumulator, ganze Schritte zu 0,05 s, Alpha zum Interpolieren.
- LuneMatchRunner: Host-Ablauf einer Bot-Partie (Planung über die
  Befehlsschnittstelle, Kampf im festen Takt, Abrechnung, nächste Runde);
  LuneMatchDriver reicht in Update nur Bildzeit weiter.
- LuneTrace: Fingerabdruck der Partie (jeder Schritt, jede Abrechnung) und der
  reine Kernlauf zum Vergleich.
- Ansichten: LuneMatchView, LuneUnitView (interpolierte Position, Blickrichtung,
  Clips aus Kampfereignissen, Teamring, Lebensbalken), LuneBuildingView mit
  Einsturz und Ruine aus den autoritativen HP, Turmblitze, LuneCameraRig wie
  lune_camera.gd, vorläufige Debug-Anzeige (kein HUD; U3 portiert das G3-HUD).
- Einheitenbibliothek: Kohlenbeißer aus 131 Teilen zu einem Mesh, Animator-
  Controller mit den Blender-Clips, Ring- und Balkenmeshes, Markermaterialien.
- Tests: EditMode (30/60/120 fps, unbegrenzt, Ruckler, 8x Tempo; Seed 2 und
  Seed 9 ab Runde 21) und PlayMode in der Szene bei echten Bildraten 30, 60,
  120 und unbegrenzt: überall derselbe Fingerabdruck wie der Kern.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Martin Stickelbroeck 2026-10-01 17:31:18 +02:00
parent 8a72cb165a
commit 3871b3e2e6
94 changed files with 64527 additions and 59643 deletions

3
.gitignore vendored
View file

@ -21,6 +21,9 @@
.idea/
.vscode/
*.tmp
# Artefacts of Unity test runs (temporary test scenes, performance-testing run info)
/[Aa]ssets/InitTestScene*.unity*
/[Aa]ssets/[Rr]esources/PerformanceTestRun*
# Test results and captures written by tools/
/TestResults/
/tools/out/

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6c9828a677fbc402789fe847bb7dee38
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,180 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!43 &4300000
Mesh:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: MarkerQuad
serializedVersion: 12
m_SubMeshes:
- serializedVersion: 2
firstByte: 0
indexCount: 6
topology: 0
baseVertex: 0
firstVertex: 0
vertexCount: 4
localAABB:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0.5, y: 0.5, z: 0}
m_Shapes:
vertices: []
shapes: []
channels: []
fullWeights: []
m_BindPose: []
m_BoneNameHashes:
m_RootBoneNameHash: 0
m_BonesAABB: []
m_VariableBoneCountWeights:
m_Data:
m_MeshCompression: 0
m_IsReadable: 1
m_KeepVertices: 1
m_KeepIndices: 1
m_IndexFormat: 0
m_IndexBuffer: 000002000100020003000100
m_VertexData:
serializedVersion: 3
m_VertexCount: 4
m_Channels:
- stream: 0
offset: 0
format: 0
dimension: 3
- stream: 0
offset: 12
format: 0
dimension: 3
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
m_DataSize: 96
_typelessdata: 000000bf000000bf000000000000000000000000000080bf0000003f000000bf000000000000000000000000000080bf000000bf0000003f000000000000000000000000000080bf0000003f0000003f000000000000000000000000000080bf
m_CompressedMesh:
m_Vertices:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_UV:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Normals:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Tangents:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Weights:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_NormalSigns:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_TangentSigns:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_FloatColors:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_BoneIndices:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_Triangles:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_UVInfo: 0
m_LocalAABB:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0.5, y: 0.5, z: 0}
m_MeshUsageFlags: 0
m_CookingOptions: 30
m_BakedConvexCollisionMesh:
m_BakedTriangleCollisionMesh:
'm_MeshMetrics[0]': 1
'm_MeshMetrics[1]': 1
m_MeshOptimizationFlags: 1
m_StreamData:
serializedVersion: 2
offset: 0
size: 0
path:
m_MeshLodInfo:
serializedVersion: 2
m_LodSelectionCurve:
serializedVersion: 1
m_LodSlope: 0
m_LodBias: 0
m_NumLevels: 1
m_SubMeshes:
- serializedVersion: 2
m_Levels:
- serializedVersion: 1
m_IndexStart: 0
m_IndexCount: 0

View file

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

View file

@ -0,0 +1,180 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!43 &4300000
Mesh:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: RingDiamond
serializedVersion: 12
m_SubMeshes:
- serializedVersion: 2
firstByte: 0
indexCount: 24
topology: 0
baseVertex: 0
firstVertex: 0
vertexCount: 10
localAABB:
m_Center: {x: -0.000000014901161, y: 0, z: -0.000000029802322}
m_Extent: {x: 0.3676955, y: 0, z: 0.36769554}
m_Shapes:
vertices: []
shapes: []
channels: []
fullWeights: []
m_BindPose: []
m_BoneNameHashes:
m_RootBoneNameHash: 0
m_BonesAABB: []
m_VariableBoneCountWeights:
m_Data:
m_MeshCompression: 0
m_IsReadable: 1
m_KeepVertices: 1
m_KeepIndices: 1
m_IndexFormat: 0
m_IndexBuffer: 000001000300000003000200020003000500020005000400040005000700040007000600060007000900060009000800
m_VertexData:
serializedVersion: 3
m_VertexCount: 10
m_Channels:
- stream: 0
offset: 0
format: 0
dimension: 3
- stream: 0
offset: 12
format: 0
dimension: 3
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
m_DataSize: 240
_typelessdata: 650e983e00000000650e983e00000000ffff7fbf000000009642bc3e000000009642bc3e00000000000080bf00000000650e98be00000000650e983e00000000000080bf000000009642bcbe000000009642bc3e00000000000080bf00000000660e98be00000000650e98be00000000000080bf000000009742bcbe000000009542bcbe00000000000080bf00000000640e983e00000000670e98be00000000000080bf000000009442bc3e000000009842bcbe00000000000080bf00000000650e983e00000000650e983e00000000000080bf000000009642bc3e000000009642bc3e00000000000080bf00000000
m_CompressedMesh:
m_Vertices:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_UV:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Normals:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Tangents:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Weights:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_NormalSigns:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_TangentSigns:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_FloatColors:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_BoneIndices:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_Triangles:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_UVInfo: 0
m_LocalAABB:
m_Center: {x: -0.000000014901161, y: 0, z: -0.000000029802322}
m_Extent: {x: 0.3676955, y: 0, z: 0.36769554}
m_MeshUsageFlags: 0
m_CookingOptions: 30
m_BakedConvexCollisionMesh:
m_BakedTriangleCollisionMesh:
'm_MeshMetrics[0]': 1
'm_MeshMetrics[1]': 1
m_MeshOptimizationFlags: 1
m_StreamData:
serializedVersion: 2
offset: 0
size: 0
path:
m_MeshLodInfo:
serializedVersion: 2
m_LodSelectionCurve:
serializedVersion: 1
m_LodSlope: 0
m_LodBias: 0
m_NumLevels: 1
m_SubMeshes:
- serializedVersion: 2
m_Levels:
- serializedVersion: 1
m_IndexStart: 0
m_IndexCount: 0

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 31d91c2c1eb24408ea1e9697308dcdd1
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 4300000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,180 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!43 &4300000
Mesh:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: RingHexagon
serializedVersion: 12
m_SubMeshes:
- serializedVersion: 2
firstByte: 0
indexCount: 36
topology: 0
baseVertex: 0
firstVertex: 0
vertexCount: 14
localAABB:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0.52, y: 0, z: 0.4503332}
m_Shapes:
vertices: []
shapes: []
channels: []
fullWeights: []
m_BindPose: []
m_BoneNameHashes:
m_RootBoneNameHash: 0
m_BonesAABB: []
m_VariableBoneCountWeights:
m_Data:
m_MeshCompression: 0
m_IsReadable: 1
m_KeepVertices: 1
m_KeepIndices: 1
m_IndexFormat: 0
m_IndexBuffer: 000001000300000003000200020003000500020005000400040005000700040007000600060007000900060009000800080009000b0008000b000a000a000b000d000a000d000c00
m_VertexData:
serializedVersion: 3
m_VertexCount: 14
m_Channels:
- stream: 0
offset: 0
format: 0
dimension: 3
- stream: 0
offset: 12
format: 0
dimension: 3
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
m_DataSize: 336
_typelessdata: 3d0ad73e000000000000000000000000000080bf00000000b81e053f000000000000000000000000000080bf000000003c0a573e00000000e83aba3e00000000000080bf00000000b71e853e000000001392e63e00000000000080bf000000003f0a57be00000000e73aba3e00000000000080bf00000000b91e85be000000001292e63e00000000000080bf000000003d0ad7be0000000064b31db300000000000080bf00000000b81e05bf00000000a03f43b300000000000080bf000000003a0a57be00000000e83ababe00000000000080bf00000000b61e85be000000001392e6be00000000000080bf000000003a0a573e00000000e83ababe00000000000080bf00000000b61e853e000000001392e6be00000000000080bf000000003d0ad73e0000000064b39d3300000000000080bf00000000b81e053f00000000a03fc33300000000000080bf00000000
m_CompressedMesh:
m_Vertices:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_UV:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Normals:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Tangents:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Weights:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_NormalSigns:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_TangentSigns:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_FloatColors:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_BoneIndices:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_Triangles:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_UVInfo: 0
m_LocalAABB:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0.52, y: 0, z: 0.4503332}
m_MeshUsageFlags: 0
m_CookingOptions: 30
m_BakedConvexCollisionMesh:
m_BakedTriangleCollisionMesh:
'm_MeshMetrics[0]': 1
'm_MeshMetrics[1]': 1
m_MeshOptimizationFlags: 1
m_StreamData:
serializedVersion: 2
offset: 0
size: 0
path:
m_MeshLodInfo:
serializedVersion: 2
m_LodSelectionCurve:
serializedVersion: 1
m_LodSlope: 0
m_LodBias: 0
m_NumLevels: 1
m_SubMeshes:
- serializedVersion: 2
m_Levels:
- serializedVersion: 1
m_IndexStart: 0
m_IndexCount: 0

View file

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

View file

@ -0,0 +1,180 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!43 &4300000
Mesh:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: RingRound
serializedVersion: 12
m_SubMeshes:
- serializedVersion: 2
firstByte: 0
indexCount: 240
topology: 0
baseVertex: 0
firstVertex: 0
vertexCount: 82
localAABB:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0.52, y: 0, z: 0.52}
m_Shapes:
vertices: []
shapes: []
channels: []
fullWeights: []
m_BindPose: []
m_BoneNameHashes:
m_RootBoneNameHash: 0
m_BonesAABB: []
m_VariableBoneCountWeights:
m_Data:
m_MeshCompression: 0
m_IsReadable: 1
m_KeepVertices: 1
m_KeepIndices: 1
m_IndexFormat: 0
m_IndexBuffer: 000001000300000003000200020003000500020005000400040005000700040007000600060007000900060009000800080009000b0008000b000a000a000b000d000a000d000c000c000d000f000c000f000e000e000f0011000e0011001000100011001300100013001200120013001500120015001400140015001700140017001600160017001900160019001800180019001b0018001b001a001a001b001d001a001d001c001c001d001f001c001f001e001e001f0021001e0021002000200021002300200023002200220023002500220025002400240025002700240027002600260027002900260029002800280029002b0028002b002a002a002b002d002a002d002c002c002d002f002c002f002e002e002f0031002e0031003000300031003300300033003200320033003500320035003400340035003700340037003600360037003900360039003800380039003b0038003b003a003a003b003d003a003d003c003c003d003f003c003f003e003e003f0041003e0041004000400041004300400043004200420043004500420045004400440045004700440047004600460047004900460049004800480049004b0048004b004a004a004b004d004a004d004c004c004d004f004c004f004e004e004f0051004e0051005000
m_VertexData:
serializedVersion: 3
m_VertexCount: 82
m_Channels:
- stream: 0
offset: 0
format: 0
dimension: 3
- stream: 0
offset: 12
format: 0
dimension: 3
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
m_DataSize: 1968
_typelessdata: 3d0ad73e000000000000000000000000000080bf00000000b81e053f000000000000000000000000ffff7fbf000000007b64d43e00000000058f863d00000000ffff7fbf00000000277b033f00000000b198a63d00000000000080bf00000000e483cc3e00000000ebe6043e00000000000080bf000000009435fd3e000000009d8b243e00000000000080bf000000001f9abf3e000000009240433e00000000000080bf00000000b938ed3e00000000a8bd713e00000000000080bf0000000094f8ad3e000000006fcb7c3e00000000000080bf000000008764d73e00000000f07d9c3e00000000000080bf00000000650e983e00000000650e983e00000000000080bf000000009642bc3e000000009642bc3e00000000000080bf0000000071cb7c3e0000000094f8ad3e00000000000080bf00000000f17d9c3e000000008764d73e00000000000080bf000000009340433e000000001f9abf3e00000000000080bf00000000a9bd713e00000000b938ed3e00000000ffff7fbf00000000eae6043e00000000e483cc3e00000000000080bf000000009c8b243e000000009435fd3e00000000000080bf00000000068f863d000000007b64d43e00000000000080bf00000000b298a63d00000000277b033f00000000000080bf0000000064b39db2000000003d0ad73e00000000000080bf00000000a03fc3b200000000b81e053f00000000000080bf00000000048f86bd000000007b64d43e00000000000080bf00000000af98a6bd00000000277b033f00000000000080bf00000000eae604be00000000e483cc3e00000000ffff7fbf000000009b8b24be000000009435fd3e00000000000080bf000000008f4043be00000000209abf3e00000000000080bf00000000a5bd71be00000000ba38ed3e00000000000080bf000000006ecb7cbe0000000094f8ad3e00000000000080bf00000000ef7d9cbe000000008764d73e00000000000080bf00000000650e98be00000000650e983e00000000000080bf000000009642bcbe000000009642bc3e00000000000080bf0000000095f8adbe000000006ecb7c3e00000000000080bf000000008864d7be00000000ef7d9c3e00000000000080bf000000001e9abfbe000000009440433e00000000000080bf00000000b838edbe00000000abbd713e00000000000080bf00000000e383ccbe00000000ece6043e00000000000080bf000000009335fdbe000000009e8b243e00000000ffff7fbf000000007b64d4be00000000048f863d00000000000080bf00000000277b03bf00000000af98a63d00000000000080bf000000003d0ad7be0000000064b31db300000000000080bf00000000b81e05bf00000000a03f43b300000000000080bf000000007b64d4be00000000ff8e86bd00000000ffff7fbf00000000277b03bf00000000aa98a6bd00000000ffff7fbf00000000e483ccbe00000000eae604be00000000000080bf000000009435fdbe000000009c8b24be00000000ffff7fbf000000001f9abfbe00000000934043be00000000000080bf00000000b938edbe00000000aabd71be00000000000080bf0000000095f8adbe000000006ccb7cbe00000000000080bf000000008864d7be00000000ee7d9cbe00000000000080bf00000000660e98be00000000650e98be00000000000080bf000000009742bcbe000000009542bcbe00000000000080bf0000000075cb7cbe0000000092f8adbe00000000000080bf00000000f37d9cbe000000008364d7be00000000000080bf00000000974043be000000001e9abfbe00000000000080bf00000000aebd71be00000000b838edbe00000000ffff7fbf00000000eee604be00000000e383ccbe00000000000080bf00000000a08b24be000000009335fdbe00000000ffff7fbf00000000088f86bd000000007a64d4be00000000000080bf00000000b498a6bd00000000277b03bf00000000ffff7fbf00000000ca16ac31000000003d0ad7be00000000000080bf000000000610d53100000000b81e05bf00000000ffff7fbf00000000098f863d000000007a64d4be00000000000080bf00000000b598a63d00000000277b03bf00000000ffff7fbf00000000efe6043e00000000e383ccbe00000000000080bf00000000a18b243e000000009335fdbe00000000000080bf000000008b40433e00000000219abfbe00000000000080bf00000000a0bd713e00000000bb38edbe00000000000080bf000000006acb7c3e0000000096f8adbe00000000000080bf00000000ed7d9c3e000000008964d7be00000000ffff7fbf00000000640e983e00000000670e98be00000000000080bf000000009442bc3e000000009842bcbe00000000000080bf0000000093f8ad3e0000000071cb7cbe00000000000080bf000000008664d73e00000000f17d9cbe00000000000080bf000000001f9abf3e00000000934043be00000000000080bf00000000b938ed3e00000000a9bd71be00000000000080bf00000000e483cc3e00000000eae604be00000000000080bf000000009435fd3e000000009b8b24be00000000ffff7fbf000000007b64d43e00000000ff8e86bd00000000000080bf00000000277b033f00000000a998a6bd00000000000080bf000000003d0ad73e0000000064b39d3300000000000080bf00000000b81e053f00000000a03fc33300000000000080bf00000000
m_CompressedMesh:
m_Vertices:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_UV:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Normals:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Tangents:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Weights:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_NormalSigns:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_TangentSigns:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_FloatColors:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_BoneIndices:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_Triangles:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_UVInfo: 0
m_LocalAABB:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0.52, y: 0, z: 0.52}
m_MeshUsageFlags: 0
m_CookingOptions: 30
m_BakedConvexCollisionMesh:
m_BakedTriangleCollisionMesh:
'm_MeshMetrics[0]': 1
'm_MeshMetrics[1]': 1
m_MeshOptimizationFlags: 1
m_StreamData:
serializedVersion: 2
offset: 0
size: 0
path:
m_MeshLodInfo:
serializedVersion: 2
m_LodSelectionCurve:
serializedVersion: 1
m_LodSlope: 0
m_LodBias: 0
m_NumLevels: 1
m_SubMeshes:
- serializedVersion: 2
m_Levels:
- serializedVersion: 1
m_IndexStart: 0
m_IndexCount: 0

View file

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

View file

@ -0,0 +1,304 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1107 &-6764018797280473307
AnimatorStateMachine:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: -2535026887411564429}
m_Position: {x: 200, y: 0, z: 0}
- serializedVersion: 1
m_State: {fileID: -343063405845558575}
m_Position: {x: 235, y: 65, z: 0}
- serializedVersion: 1
m_State: {fileID: -342311843018734023}
m_Position: {x: 270, y: 130, z: 0}
- serializedVersion: 1
m_State: {fileID: -4669440134844499830}
m_Position: {x: 305, y: 195, z: 0}
- serializedVersion: 1
m_State: {fileID: 1088834257012490643}
m_Position: {x: 340, y: 260, z: 0}
- serializedVersion: 1
m_State: {fileID: -970221920099555238}
m_Position: {x: 375, y: 325, z: 0}
- serializedVersion: 1
m_State: {fileID: -3615956992555323955}
m_Position: {x: 410, y: 390, z: 0}
- serializedVersion: 1
m_State: {fileID: 6005959930581298553}
m_Position: {x: 445, y: 455, z: 0}
- serializedVersion: 1
m_State: {fileID: 1300998371047612755}
m_Position: {x: 480, y: 520, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 50, y: 120, z: 0}
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: -2535026887411564429}
--- !u!1102 &-4669440134844499830
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: attack_b
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -2963360793056117044, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-3615956992555323955
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: start
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 6150794267048699607, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-2535026887411564429
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: idle
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -1348917559068937310, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-970221920099555238
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: hit
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -4707179913997139171, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-343063405845558575
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: ability
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -1787258805998246360, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-342311843018734023
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: attack_a
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -6628820121952251911, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: funkenlanze
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: -6764018797280473307}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!1102 &1088834257012490643
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: death
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 9159963757730041032, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &1300998371047612755
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: walk
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7607972658950073716, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &6005959930581298553
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: stop
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 637536857275861776, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:

View file

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

View file

@ -0,0 +1,304 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1102 &-5072535758161348039
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: stop
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 637536857275861776, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-4431799369907015437
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: ability
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -1787258805998246360, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: funkenlanze
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: 6166095299861375435}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!1102 &391544143596271389
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: attack_a
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -6628820121952251911, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &3334832047352148659
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: idle
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -1348917559068937310, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &4753768985330737369
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: walk
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7607972658950073716, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1107 &6166095299861375435
AnimatorStateMachine:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: 3334832047352148659}
m_Position: {x: 200, y: 0, z: 0}
- serializedVersion: 1
m_State: {fileID: -4431799369907015437}
m_Position: {x: 235, y: 65, z: 0}
- serializedVersion: 1
m_State: {fileID: 391544143596271389}
m_Position: {x: 270, y: 130, z: 0}
- serializedVersion: 1
m_State: {fileID: 8290327798176879507}
m_Position: {x: 305, y: 195, z: 0}
- serializedVersion: 1
m_State: {fileID: 6172747248973857371}
m_Position: {x: 340, y: 260, z: 0}
- serializedVersion: 1
m_State: {fileID: 9059046945983664246}
m_Position: {x: 375, y: 325, z: 0}
- serializedVersion: 1
m_State: {fileID: 9086454302721513878}
m_Position: {x: 410, y: 390, z: 0}
- serializedVersion: 1
m_State: {fileID: -5072535758161348039}
m_Position: {x: 445, y: 455, z: 0}
- serializedVersion: 1
m_State: {fileID: 4753768985330737369}
m_Position: {x: 480, y: 520, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 50, y: 120, z: 0}
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: 3334832047352148659}
--- !u!1102 &6172747248973857371
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: death
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 9159963757730041032, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &8290327798176879507
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: attack_b
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -2963360793056117044, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &9059046945983664246
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: hit
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -4707179913997139171, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &9086454302721513878
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: start
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 6150794267048699607, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:

View file

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

File diff suppressed because one or more lines are too long

View file

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

View file

@ -0,0 +1,98 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &5437810860397098822
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 283848037006539818}
- component: {fileID: 6601225176472002464}
- component: {fileID: 4465367892794413513}
m_Layer: 0
m_Name: g01_combined
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &283848037006539818
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5437810860397098822}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &6601225176472002464
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5437810860397098822}
m_Mesh: {fileID: 4300000, guid: da6c3ddfa2d5e48bc96ee17d126ac08a, type: 2}
--- !u!23 &4465367892794413513
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5437810860397098822}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 8826486031599903766, guid: 416c29115e263420dbef5a876b74571c, type: 3}
- {fileID: -8524589278708909900, guid: 416c29115e263420dbef5a876b74571c, type: 3}
- {fileID: -500457562325487532, guid: 416c29115e263420dbef5a876b74571c, type: 3}
- {fileID: 2326369661988904523, guid: 416c29115e263420dbef5a876b74571c, type: 3}
- {fileID: 112765384125592931, guid: 416c29115e263420dbef5a876b74571c, type: 3}
- {fileID: 8240495515043335571, guid: 416c29115e263420dbef5a876b74571c, type: 3}
- {fileID: 3802194473538262930, guid: 416c29115e263420dbef5a876b74571c, type: 3}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5fd282077851b444e88f8b011542f2f3
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,362 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1102 &-8649174040998007854
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: idle
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 2159908019584541609, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-7067930944596710515
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: attack_b
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7137080732755112609, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1107 &-5556910388363311180
AnimatorStateMachine:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: -8649174040998007854}
m_Position: {x: 200, y: 0, z: 0}
- serializedVersion: 1
m_State: {fileID: -941030565808386572}
m_Position: {x: 235, y: 65, z: 0}
- serializedVersion: 1
m_State: {fileID: 8027054292600147961}
m_Position: {x: 270, y: 130, z: 0}
- serializedVersion: 1
m_State: {fileID: -7067930944596710515}
m_Position: {x: 305, y: 195, z: 0}
- serializedVersion: 1
m_State: {fileID: 7801725214768762247}
m_Position: {x: 340, y: 260, z: 0}
- serializedVersion: 1
m_State: {fileID: 3109516352655718742}
m_Position: {x: 375, y: 325, z: 0}
- serializedVersion: 1
m_State: {fileID: 4235676996855759033}
m_Position: {x: 410, y: 390, z: 0}
- serializedVersion: 1
m_State: {fileID: 137992366648403755}
m_Position: {x: 445, y: 455, z: 0}
- serializedVersion: 1
m_State: {fileID: 6076107605701060415}
m_Position: {x: 480, y: 520, z: 0}
- serializedVersion: 1
m_State: {fileID: -2494235129224698851}
m_Position: {x: 515, y: 585, z: 0}
- serializedVersion: 1
m_State: {fileID: -3267051496969522659}
m_Position: {x: 550, y: 650, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 50, y: 120, z: 0}
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: -8649174040998007854}
--- !u!1102 &-3267051496969522659
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: walk
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -395723189595340628, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-2494235129224698851
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: victory
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7279649719363434968, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-941030565808386572
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: ability
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 8816013596772264376, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: schlundkrone
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: -5556910388363311180}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!1102 &137992366648403755
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: start
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -8546801627699338383, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &3109516352655718742
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: hit
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -1153443838369333364, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &4235676996855759033
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: roar
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 1662885906025357955, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &6076107605701060415
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: stop
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 8440139490132052637, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &7801725214768762247
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: death
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 3223440528613674463, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &8027054292600147961
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: attack_a
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -3581854836903996656, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:

View file

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

View file

@ -0,0 +1,362 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1102 &-7604498211372552777
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: attack_a
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -3581854836903996656, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-7335346286295202443
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: start
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -8546801627699338383, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-6627712365168424534
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: walk
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -395723189595340628, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-5072837360098228033
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: attack_b
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7137080732755112609, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-3424720011901633727
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: hit
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -1153443838369333364, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-3367916964859850658
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: roar
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 1662885906025357955, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-2063096363206746791
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: ability
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 8816013596772264376, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: schlundkrone
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: 2076895213422903774}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!1102 &354723411150343332
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: idle
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 2159908019584541609, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1107 &2076895213422903774
AnimatorStateMachine:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: 354723411150343332}
m_Position: {x: 200, y: 0, z: 0}
- serializedVersion: 1
m_State: {fileID: -2063096363206746791}
m_Position: {x: 235, y: 65, z: 0}
- serializedVersion: 1
m_State: {fileID: -7604498211372552777}
m_Position: {x: 270, y: 130, z: 0}
- serializedVersion: 1
m_State: {fileID: -5072837360098228033}
m_Position: {x: 305, y: 195, z: 0}
- serializedVersion: 1
m_State: {fileID: 3675573970452591775}
m_Position: {x: 340, y: 260, z: 0}
- serializedVersion: 1
m_State: {fileID: -3424720011901633727}
m_Position: {x: 375, y: 325, z: 0}
- serializedVersion: 1
m_State: {fileID: -3367916964859850658}
m_Position: {x: 410, y: 390, z: 0}
- serializedVersion: 1
m_State: {fileID: -7335346286295202443}
m_Position: {x: 445, y: 455, z: 0}
- serializedVersion: 1
m_State: {fileID: 6550055648185986712}
m_Position: {x: 480, y: 520, z: 0}
- serializedVersion: 1
m_State: {fileID: 8816344095030909734}
m_Position: {x: 515, y: 585, z: 0}
- serializedVersion: 1
m_State: {fileID: -6627712365168424534}
m_Position: {x: 550, y: 650, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 50, y: 120, z: 0}
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: 354723411150343332}
--- !u!1102 &3675573970452591775
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: death
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 3223440528613674463, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &6550055648185986712
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: stop
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 8440139490132052637, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &8816344095030909734
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: victory
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7279649719363434968, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 55d11e29be0134459bf261f2dad38f33
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 9100000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,185 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Luneraria.View;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using UnityEngine.Rendering;
namespace Luneraria.EditorTools
{
/// <summary>
/// Builds what the unit views need (U2C): a one-mesh version of the rigid Kohlenbeißer (131
/// named parts combined per material, like Godot's rig groups), animator controllers with the
/// Blender clips of the rigged figures, team ring and bar meshes and their materials.
/// </summary>
public static class LuneUnitLibraryBuilder
{
public const string LibraryPath = "Assets/Luneraria/Settings/LuneUnits.asset";
const string Generated = "Assets/Luneraria/Art/Generated";
const string Art = "Assets/Luneraria/Art/";
public static LuneUnitLibrary Build(LuneMaterialSet materials, LuneGround ground)
{
Directory.CreateDirectory(Generated);
AssetDatabase.Refresh();
var library = AssetDatabase.LoadAssetAtPath<LuneUnitLibrary>(LibraryPath);
if (library == null)
{
library = ScriptableObject.CreateInstance<LuneUnitLibrary>();
AssetDatabase.CreateAsset(library, LibraryPath);
}
library.Materials = materials;
library.Ground = ground;
library.Rigid = CombinedPrefab("g01", Art + "Units/g01.fbx");
library.Hero = AssetDatabase.LoadAssetAtPath<GameObject>(Art + "Characters/funkenlanze.fbx");
library.HeroController = Controller("funkenlanze", Art + "Characters/funkenlanze.fbx");
library.Boss = AssetDatabase.LoadAssetAtPath<GameObject>(Art + "Characters/schlundkrone.fbx");
library.BossController = Controller("schlundkrone", Art + "Characters/schlundkrone.fbx");
library.RingRound = Keep(Ring("RingRound", 40, 0f));
library.RingDiamond = Keep(Ring("RingDiamond", 4, 45f));
library.RingHexagon = Keep(Ring("RingHexagon", 6, 0f));
library.Quad = Keep(Quad());
for (int team = 0; team < 3; team++)
{
library.TeamRing[team] = Marker("Ring_" + team, LuneMaterialFactory.TeamColor[team], team == 2 ? .6f : 1.4f, false);
library.BarFill[team] = Marker("BarFill_" + team, Color.Lerp(LuneMaterialFactory.TeamColor[team], Color.white, .15f), 1f, true);
library.Bolt[team] = Marker("Bolt_" + team, LuneMaterialFactory.TeamLight[team], 3f, false);
}
library.HeroRing = Marker("Ring_Hero", LuneMaterialFactory.Hex("f2c96b"), 2.2f, false);
library.BarBack = Marker("BarBack", new Color(0f, 0f, 0f, .7f), 1f, true);
EditorUtility.SetDirty(library);
AssetDatabase.SaveAssets();
return library;
}
/// <summary>All parts of a rigid figure in one mesh, one submesh per material.</summary>
static GameObject CombinedPrefab(string id, string fbx)
{
var source = AssetDatabase.LoadAssetAtPath<GameObject>(fbx);
var groups = new Dictionary<Material, List<CombineInstance>>();
foreach (MeshFilter filter in source.GetComponentsInChildren<MeshFilter>(true))
{
Material[] slots = filter.GetComponent<MeshRenderer>().sharedMaterials;
Matrix4x4 toRoot = source.transform.worldToLocalMatrix * filter.transform.localToWorldMatrix;
for (int sub = 0; sub < filter.sharedMesh.subMeshCount; sub++)
{
if (!groups.TryGetValue(slots[sub], out List<CombineInstance> list))
groups[slots[sub]] = list = new List<CombineInstance>();
list.Add(new CombineInstance { mesh = filter.sharedMesh, subMeshIndex = sub, transform = toRoot });
}
}
var parts = new List<CombineInstance>();
var materials = new List<Material>();
foreach (KeyValuePair<Material, List<CombineInstance>> group in groups.OrderBy(g => g.Key.name))
{
var merged = new Mesh { indexFormat = IndexFormat.UInt32 };
merged.CombineMeshes(group.Value.ToArray(), true, true);
parts.Add(new CombineInstance { mesh = merged, transform = Matrix4x4.identity });
materials.Add(group.Key);
}
var mesh = new Mesh { name = id + "_combined", indexFormat = IndexFormat.UInt32 };
mesh.CombineMeshes(parts.ToArray(), false, false);
mesh.RecalculateBounds();
mesh = Keep(mesh);
string prefabPath = Generated + "/" + id + "_combined.prefab";
var go = new GameObject(id + "_combined");
go.AddComponent<MeshFilter>().sharedMesh = mesh;
go.AddComponent<MeshRenderer>().sharedMaterials = materials.ToArray();
GameObject prefab = PrefabUtility.SaveAsPrefabAsset(go, prefabPath);
Object.DestroyImmediate(go);
return prefab;
}
/// <summary>One state per clip of the model (named like the Blender action), idle first.</summary>
static RuntimeAnimatorController Controller(string id, string fbx)
{
string path = Generated + "/" + id + ".controller";
AssetDatabase.DeleteAsset(path);
AnimatorController controller = AnimatorController.CreateAnimatorControllerAtPath(path);
AnimationClip[] clips = AssetDatabase.LoadAllAssetsAtPath(fbx).OfType<AnimationClip>().Where(c => !c.name.StartsWith("__preview__"))
.OrderBy(c => c.name == "idle" ? 0 : 1).ThenBy(c => c.name).ToArray();
AnimatorStateMachine machine = controller.layers[0].stateMachine;
foreach (AnimationClip clip in clips)
{
AnimatorState state = machine.AddState(clip.name);
state.motion = clip;
if (clip.name == "idle")
machine.defaultState = state;
}
EditorUtility.SetDirty(controller);
return controller;
}
/// <summary>Flat ring on the ground (Godot: TorusMesh inner .42, outer .52, flattened).</summary>
static Mesh Ring(string name, int sides, float offsetDegrees)
{
var vertices = new List<Vector3>();
var triangles = new List<int>();
for (int i = 0; i <= sides; i++)
{
float angle = (offsetDegrees + 360f * i / sides) * Mathf.Deg2Rad;
var direction = new Vector3(Mathf.Cos(angle), 0f, Mathf.Sin(angle));
vertices.Add(direction * .42f);
vertices.Add(direction * .52f);
if (i < sides)
{
int a = i * 2;
triangles.AddRange(new[] { a, a + 1, a + 3, a, a + 3, a + 2 });
}
}
var mesh = new Mesh { name = name };
mesh.SetVertices(vertices);
mesh.SetTriangles(triangles, 0);
mesh.RecalculateNormals();
mesh.RecalculateBounds();
return mesh;
}
static Mesh Quad()
{
var mesh = new Mesh { name = "MarkerQuad" };
mesh.SetVertices(new List<Vector3> { new Vector3(-.5f, -.5f, 0f), new Vector3(.5f, -.5f, 0f), new Vector3(-.5f, .5f, 0f), new Vector3(.5f, .5f, 0f) });
mesh.SetTriangles(new[] { 0, 2, 1, 2, 3, 1 }, 0);
mesh.RecalculateNormals();
mesh.RecalculateBounds();
return mesh;
}
static Mesh Keep(Mesh mesh)
{
string path = Generated + "/" + mesh.name + ".asset";
var existing = AssetDatabase.LoadAssetAtPath<Mesh>(path);
if (existing == null)
{
AssetDatabase.CreateAsset(mesh, path);
return mesh;
}
EditorUtility.CopySerialized(mesh, existing);
EditorUtility.SetDirty(existing);
return existing;
}
/// <summary>Unshaded marker colour (Godot _flat with emission energy); bars draw on top.</summary>
static Material Marker(string name, Color srgb, float energy, bool onTop)
{
string path = LuneMaterialFactory.Folder + "/Markers/" + name + ".mat";
Directory.CreateDirectory(Path.GetDirectoryName(path));
Shader shader = Shader.Find("Luneraria/Unlit");
var material = AssetDatabase.LoadAssetAtPath<Material>(path);
if (material == null)
{
material = new Material(shader);
AssetDatabase.CreateAsset(material, path);
}
material.shader = shader;
Color linear = srgb.linear * energy;
material.SetColor("_Color", new Color(linear.r, linear.g, linear.b, srgb.a));
material.SetFloat("_ZTest", onTop ? (float)CompareFunction.Always : (float)CompareFunction.LessEqual);
material.enableInstancing = true;
EditorUtility.SetDirty(material);
return material;
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f11c6afb699e94a3f99758842b770883

View file

@ -62,6 +62,7 @@ namespace Luneraria.EditorTools
Terrain(bake, world, worldMaterials);
int meshes = Nodes(bake, world, worldMaterials, materials);
var buildings = Buildings(materials, ground);
LuneUnitLibrary library = LuneUnitLibraryBuilder.Build(materials, ground);
var camera = new GameObject("Main Camera");
camera.tag = "MainCamera";
var unityCamera = camera.AddComponent<Camera>();
@ -71,6 +72,21 @@ namespace Luneraria.EditorTools
camera.AddComponent<UniversalAdditionalCameraData>().renderPostProcessing = true;
LuneCameraMath.Pose(new Vector3(0f, ground.StandHeight(new Vec2(0f, 0f)), 0f), LuneCameraMath.OverviewZoom, 0f, out Vector3 position, out Quaternion rotation);
camera.transform.SetPositionAndRotation(position, rotation);
var rig = camera.AddComponent<LuneCameraRig>();
rig.Ground = ground;
rig.Zoom = LuneCameraMath.OverviewZoom;
// The match: a bot match on the host, its views and the temporary U2 readout.
var matchObject = new GameObject("Match");
var driver = matchObject.AddComponent<LuneMatchDriver>();
var view = matchObject.AddComponent<LuneMatchView>();
view.Driver = driver;
view.Library = library;
view.ViewCamera = unityCamera;
matchObject.AddComponent<LuneDebugOverlay>().Driver = driver;
var benchmark = matchObject.AddComponent<LuneBenchmark>();
benchmark.Driver = driver;
benchmark.View = view;
benchmark.Rig = rig;
// Meshes of an earlier build that this build no longer produces.
foreach (string stale in AssetDatabase.FindAssets("t:Mesh", new[] { GeneratedFolder }).Select(AssetDatabase.GUIDToAssetPath).Where(p => !_written.Contains(p)).ToList())
AssetDatabase.DeleteAsset(stale);

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b74c9f2e24c4b47f4bc089873100cc2e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,33 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: BarBack
m_Shader: {fileID: 4800000, guid: 5674755340f3b446aad7884cd0870a4f, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints: []
m_Floats:
- _Cull: 0
- _ZTest: 8
m_Colors:
- _Color: {r: 0, g: 0, b: 0, a: 0.7}
m_BuildTextureStacks: []
m_AllowLocking: 1

View file

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

View file

@ -0,0 +1,33 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: BarFill_0
m_Shader: {fileID: 4800000, guid: 5674755340f3b446aad7884cd0870a4f, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints: []
m_Floats:
- _Cull: 0
- _ZTest: 8
m_Colors:
- _Color: {r: 0.17064494, g: 0.46236148, b: 1, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View file

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

View file

@ -0,0 +1,33 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: BarFill_1
m_Shader: {fileID: 4800000, guid: 5674755340f3b446aad7884cd0870a4f, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints: []
m_Floats:
- _Cull: 0
- _ZTest: 8
m_Colors:
- _Color: {r: 1, g: 0.21713942, b: 0.1574394, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View file

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

View file

@ -0,0 +1,33 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: BarFill_2
m_Shader: {fileID: 4800000, guid: 5674755340f3b446aad7884cd0870a4f, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints: []
m_Floats:
- _Cull: 0
- _ZTest: 8
m_Colors:
- _Color: {r: 0.51734394, g: 0.27741405, b: 1, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View file

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

View file

@ -0,0 +1,33 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Bolt_0
m_Shader: {fileID: 4800000, guid: 5674755340f3b446aad7884cd0870a4f, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints: []
m_Floats:
- _Cull: 0
- _ZTest: 4
m_Colors:
- _Color: {r: 0.78675216, g: 1.7327416, b: 3, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View file

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

View file

@ -0,0 +1,33 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Bolt_1
m_Shader: {fileID: 4800000, guid: 5674755340f3b446aad7884cd0870a4f, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints: []
m_Floats:
- _Cull: 0
- _ZTest: 4
m_Colors:
- _Color: {r: 3, g: 1.2698033, b: 0.5048082, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View file

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

View file

@ -0,0 +1,33 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Bolt_2
m_Shader: {fileID: 4800000, guid: 5674755340f3b446aad7884cd0870a4f, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints: []
m_Floats:
- _Cull: 0
- _ZTest: 4
m_Colors:
- _Color: {r: 1.3523575, g: 0.60466874, b: 3, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View file

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

View file

@ -0,0 +1,33 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Ring_0
m_Shader: {fileID: 4800000, guid: 5674755340f3b446aad7884cd0870a4f, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints: []
m_Floats:
- _Cull: 0
- _ZTest: 4
m_Colors:
- _Color: {r: 0.14313844, g: 0.54820156, b: 1.4, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View file

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

View file

@ -0,0 +1,33 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Ring_1
m_Shader: {fileID: 4800000, guid: 5674755340f3b446aad7884cd0870a4f, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints: []
m_Floats:
- _Cull: 0
- _ZTest: 4
m_Colors:
- _Color: {r: 1.4, g: 0.20177987, b: 0.12717843, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View file

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

View file

@ -0,0 +1,33 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Ring_2
m_Shader: {fileID: 4800000, guid: 5674755340f3b446aad7884cd0870a4f, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints: []
m_Floats:
- _Cull: 0
- _ZTest: 4
m_Colors:
- _Color: {r: 0.2704715, g: 0.12093375, b: 0.6, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View file

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

View file

@ -0,0 +1,33 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Ring_Hero
m_Shader: {fileID: 4800000, guid: 5674755340f3b446aad7884cd0870a4f, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints: []
m_Floats:
- _Cull: 0
- _ZTest: 4
m_Colors:
- _Color: {r: 1.953431, g: 1.2849727, b: 0.32346004, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View file

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

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,39 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !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: cc54af12d81bc4f6a89d31026a2cd83e, type: 3}
m_Name: LuneUnits
m_EditorClassIdentifier: Luneraria.View::Luneraria.View.LuneUnitLibrary
Rigid: {fileID: 5437810860397098822, guid: 5fd282077851b444e88f8b011542f2f3, type: 3}
Hero: {fileID: 919132149155446097, guid: 652ee682a82c34ff99c2eb11cd218f5e, type: 3}
HeroController: {fileID: 9100000, guid: b0e33b10cf38a4aca9b6a03585a5ef2d, type: 2}
Boss: {fileID: 919132149155446097, guid: b2dd57798499c4b7b8698ee56e676c45, type: 3}
BossController: {fileID: 9100000, guid: 55d11e29be0134459bf261f2dad38f33, type: 2}
Materials: {fileID: 11400000, guid: cb9b2e3ea8c3149538d92ca4d679092f, type: 2}
Ground: {fileID: 11400000, guid: 9db83b0785ebd456884ea69675e50c88, type: 2}
RingRound: {fileID: 4300000, guid: e9200d94ebe5d43af953b5bed0e427f0, type: 2}
RingDiamond: {fileID: 4300000, guid: 31d91c2c1eb24408ea1e9697308dcdd1, type: 2}
RingHexagon: {fileID: 4300000, guid: b6a53eb15d8c54935979c79596f54af1, type: 2}
Quad: {fileID: 4300000, guid: d867dec5bb7fd4328aecf98bf7838726, type: 2}
TeamRing:
- {fileID: 2100000, guid: d605511d227854255ab8c4aa887074e1, type: 2}
- {fileID: 2100000, guid: 42de21345916440af8d534f7a015a490, type: 2}
- {fileID: 2100000, guid: 77d940cdf3d6043cb93c647607c3e35e, type: 2}
HeroRing: {fileID: 2100000, guid: 862d58435f9824d969aecf8551257a64, type: 2}
BarBack: {fileID: 2100000, guid: 8efe289a463614fee8dcb19e789f2bf8, type: 2}
BarFill:
- {fileID: 2100000, guid: 778bc4f74208340e38dc099b897f3db3, type: 2}
- {fileID: 2100000, guid: b9031e71d3e8142149c6bb40b1386265, type: 2}
- {fileID: 2100000, guid: c156a92a89cae43fd94a66a1bab97ea8, type: 2}
Bolt:
- {fileID: 2100000, guid: 57679ea845a534e0cb625512321e1f12, type: 2}
- {fileID: 2100000, guid: ff98f0c178d214560b42be7959bfa214, type: 2}
- {fileID: 2100000, guid: 325b6aa4f2372452a93a1e400cafec61, type: 2}

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 553ae73ef2b6241769bb43e7ff8fd821
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,56 +1,6 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-5978695530690538826
MonoBehaviour:
m_ObjectHideFlags: 3
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: 0b2db86121404754db890f4c8dfe81b2, type: 3}
m_Name: Bloom
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.Bloom
active: 1
skipIterations:
m_OverrideState: 1
m_Value: 1
threshold:
m_OverrideState: 1
m_Value: 1.2
intensity:
m_OverrideState: 1
m_Value: 0.55
scatter:
m_OverrideState: 1
m_Value: 0.6
clamp:
m_OverrideState: 1
m_Value: 65472
tint:
m_OverrideState: 1
m_Value: {r: 1, g: 1, b: 1, a: 1}
highQualityFiltering:
m_OverrideState: 1
m_Value: 0
filter:
m_OverrideState: 1
m_Value: 0
downscale:
m_OverrideState: 1
m_Value: 0
maxIterations:
m_OverrideState: 1
m_Value: 6
dirtTexture:
m_OverrideState: 1
m_Value: {fileID: 0}
dimension: 1
dirtIntensity:
m_OverrideState: 1
m_Value: 0
--- !u!114 &-5036015673192800570
--- !u!114 &-6758026943016807199
MonoBehaviour:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
@ -78,7 +28,7 @@ MonoBehaviour:
saturation:
m_OverrideState: 1
m_Value: 18
--- !u!114 &-4947812577690109050
--- !u!114 &-1566529294735705150
MonoBehaviour:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
@ -131,6 +81,56 @@ MonoBehaviour:
m_Name: LuneVolume
m_EditorClassIdentifier: Unity.RenderPipelines.Core.Runtime::UnityEngine.Rendering.VolumeProfile
components:
- {fileID: -4947812577690109050}
- {fileID: -5978695530690538826}
- {fileID: -5036015673192800570}
- {fileID: -1566529294735705150}
- {fileID: 4907748662702703089}
- {fileID: -6758026943016807199}
--- !u!114 &4907748662702703089
MonoBehaviour:
m_ObjectHideFlags: 3
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: 0b2db86121404754db890f4c8dfe81b2, type: 3}
m_Name: Bloom
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.Bloom
active: 1
skipIterations:
m_OverrideState: 1
m_Value: 1
threshold:
m_OverrideState: 1
m_Value: 1.2
intensity:
m_OverrideState: 1
m_Value: 0.55
scatter:
m_OverrideState: 1
m_Value: 0.6
clamp:
m_OverrideState: 1
m_Value: 65472
tint:
m_OverrideState: 1
m_Value: {r: 1, g: 1, b: 1, a: 1}
highQualityFiltering:
m_OverrideState: 1
m_Value: 0
filter:
m_OverrideState: 1
m_Value: 0
downscale:
m_OverrideState: 1
m_Value: 0
maxIterations:
m_OverrideState: 1
m_Value: 6
dirtTexture:
m_OverrideState: 1
m_Value: {fileID: 0}
dimension: 1
dirtIntensity:
m_OverrideState: 1
m_Value: 0

View file

@ -0,0 +1,45 @@
// Flat colour for markers (team rings, health bars, tower bolts): Godot's unshaded materials.
// _ZTest 8 (Always) draws on top like Godot's no_depth_test health bars.
Shader "Luneraria/Unlit"
{
Properties
{
[HDR] _Color("Colour", Color) = (1, 1, 1, 1)
[Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("Z Test", Float) = 4
[Enum(UnityEngine.Rendering.CullMode)] _Cull("Cull", Float) = 0
}
SubShader
{
Tags { "RenderType" = "Transparent" "RenderPipeline" = "UniversalPipeline" "Queue" = "Transparent+10" }
Pass
{
Name "Unlit"
Tags { "LightMode" = "UniversalForward" }
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
ZTest [_ZTest]
Cull [_Cull]
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#pragma multi_compile_instancing
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
CBUFFER_START(UnityPerMaterial)
half4 _Color;
float _ZTest;
float _Cull;
CBUFFER_END
struct Attributes { float4 positionOS : POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID };
struct Varyings { float4 positionCS : SV_POSITION; };
Varyings Vert(Attributes input)
{
UNITY_SETUP_INSTANCE_ID(input);
Varyings output;
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
return output;
}
half4 Frag(Varyings input) : SV_Target { return _Color; }
ENDHLSL
}
}
}

View file

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 5674755340f3b446aad7884cd0870a4f
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2f0678eee8e93471b93b5ef561491e6b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 10b1783f6b79646dd8911a4b672fe7ae
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using Luneraria.Core;
using NUnit.Framework;
using UnityEngine;
namespace Luneraria.View.Tests
{
/// <summary>
/// U2C: the host loop gives the same match at every frame rate. The runner is fed frame
/// times of 30, 60 and 120 FPS, of an unlimited frame rate (tiny, jittering frames), and of a
/// stuttering machine (long stalls between short frames); every run must end with the state
/// fingerprint of the plain core run (LuneTrace.RunCore), step for step and round for round.
/// </summary>
public sealed class FrameRateIndependenceTests
{
static readonly Dictionary<string, Func<int, double>> Rates = new Dictionary<string, Func<int, double>>
{
{ "30 fps", frame => 1.0 / 30.0 },
{ "60 fps", frame => 1.0 / 60.0 },
{ "120 fps", frame => 1.0 / 120.0 },
{ "unlimited (0.4-3.9 ms jitter)", frame => 0.0004 + ((frame * 7919) % 97) / 97.0 * 0.0035 },
{ "stutter (stalls up to 0.4 s)", frame => frame % 23 == 0 ? 0.4 : 1.0 / 144.0 },
};
static void Compare(int seed, int startRound, int extraGold, double speed)
{
var options = new MatchOptions { Seed = seed, HumanSlot = -1 };
LuneTrace core = LuneTrace.RunCore(options, startRound, extraGold, "");
foreach (KeyValuePair<string, Func<int, double>> rate in Rates)
{
var runner = new LuneMatchRunner(options, startRound, extraGold) { Trace = new LuneTrace(), PlanningSeconds = .5, SettledSeconds = .5 };
int frames = 0;
while (runner.Current != LuneMatchRunner.Stage.Over && frames < 20000000)
runner.Advance(rate.Value(frames++) * speed);
Debug.Log(string.Format("LUNE_FPS seed {0} {1}: {2} frames, {3} steps, hash {4:X16} (core {5:X16})", seed, rate.Key, frames, runner.Trace.Steps, runner.Trace.Hash, core.Hash));
Assert.AreEqual(core.Steps, runner.Trace.Steps, rate.Key + ": steps");
CollectionAssert.AreEqual(core.RoundHashes, runner.Trace.RoundHashes, rate.Key + ": round fingerprints");
Assert.AreEqual(core.Hash, runner.Trace.Hash, rate.Key + ": match fingerprint");
Assert.AreEqual(core.Rounds, runner.Trace.Rounds, rate.Key + ": rounds");
}
}
[Test]
public void FullBotMatchSeed2IsTheSameAtEveryFrameRate()
{
Compare(2, 1, 0, 1.0);
}
[Test]
public void HighWaveMatchFromRound21IsTheSameAtEveryFrameRate()
{
Compare(9, 21, 4000, 1.0);
}
[Test]
public void MatchSpeedDoesNotChangeTheMatch()
{
Compare(2, 1, 0, 8.0);
}
[Test]
public void ClockRunsWholeStepsOnly()
{
var clock = new LuneClock(0.05);
int steps = 0;
steps += clock.Advance(0.049, () => true);
Assert.AreEqual(0, steps);
Assert.That(clock.Alpha, Is.InRange(0.97, 0.99));
steps += clock.Advance(0.052, () => true);
Assert.AreEqual(2, steps);
Assert.That(clock.Alpha, Is.InRange(0.01, 0.03));
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 64c89a430970948199eb76a6b4f8b6b1

View file

@ -0,0 +1,25 @@
{
"name": "Luneraria.View.Tests.EditMode",
"rootNamespace": "Luneraria.View.Tests",
"references": [
"Luneraria.Core",
"Luneraria.View",
"UnityEngine.TestRunner",
"UnityEditor.TestRunner"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: abb5a5ea036c74db08891297b848b69d
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0ceacf850cd4748819af013c3a6a90d1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,22 @@
{
"name": "Luneraria.View.Tests.PlayMode",
"rootNamespace": "Luneraria.View.Tests",
"references": [
"Luneraria.Core",
"Luneraria.View",
"UnityEngine.TestRunner"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 45c757dea029044fc9940c36292b4316
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,28 @@
using System.Collections;
using System.Globalization;
using System.IO;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Luneraria.View.Tests
{
static class PlayModeSupport
{
public const string Scene = "G1_Map";
public static string Root { get { return Path.GetDirectoryName(Application.dataPath); } }
public static IEnumerator Load()
{
AsyncOperation loading = SceneManager.LoadSceneAsync(Scene, LoadSceneMode.Single);
while (!loading.isDone)
yield return null;
yield return null;
}
public static string Number(double value)
{
return value.ToString("0.###", CultureInfo.InvariantCulture);
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 57f0808b8f2a344d582e1285f7050ae9

View file

@ -0,0 +1,73 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Luneraria.Core;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Luneraria.View.Tests
{
/// <summary>
/// U2C in the real scene: the bot match of seed 2 runs with every view attached while the
/// player loop runs at 30, 60, 120 FPS and unlimited (Application.targetFrameRate, VSync off).
/// Each run must reproduce the core's fingerprint. The measured frame rates show that the
/// frame timing really differed. Writes docs/port/logs/u2c/scene-frame-rates.json.
/// </summary>
public sealed class SceneFrameRateTests
{
const float Speed = 24f;
[UnityTest]
public IEnumerator SceneMatchIsTheSameAtRealFrameRates()
{
var options = new MatchOptions { Seed = 2, HumanSlot = -1 };
LuneTrace core = LuneTrace.RunCore(options, 1, 0, "");
var report = new StringBuilder("{\n \"match\": \"seed 2, bots, speed " + Speed + "x\",\n \"core_hash\": \"" + core.Hash.ToString("X16") + "\",\n \"core_steps\": " + core.Steps + ",\n \"runs\": [\n");
var failures = new List<string>();
int[] rates = { 30, 60, 120, -1 };
for (int index = 0; index < rates.Length; index++)
{
QualitySettings.vSyncCount = 0;
Application.targetFrameRate = rates[index];
yield return PlayModeSupport.Load();
var driver = Object.FindAnyObjectByType<LuneMatchDriver>();
driver.Seed = 2;
driver.StartRound = 1;
driver.ExtraGold = 0;
driver.Speed = Speed;
driver.Restart();
driver.Runner.PlanningSeconds = .5;
driver.Runner.SettledSeconds = .5;
var rig = Object.FindAnyObjectByType<LuneCameraRig>();
rig.Interactive = false;
rig.LookAt(new Vec2(0, 0), 60f, true);
float start = Time.realtimeSinceStartup;
int frames = 0;
int maxSteps = 0;
while (driver.Runner.Current != LuneMatchRunner.Stage.Over && Time.realtimeSinceStartup - start < 600f)
{
yield return null;
frames++;
maxSteps = Mathf.Max(maxSteps, driver.Runner.StepsThisFrame);
}
float seconds = Time.realtimeSinceStartup - start;
LuneTrace trace = driver.Runner.Trace;
string label = rates[index] > 0 ? rates[index] + " fps" : "unlimited";
bool same = trace.Hash == core.Hash && trace.Steps == core.Steps;
if (!same)
failures.Add(label + ": " + trace.Hash.ToString("X16") + " / " + trace.Steps + " steps");
Debug.Log(string.Format("LUNE_SCENE_FPS {0}: {1} frames in {2:0.0} s = {3:0.0} fps, up to {4} steps per frame, hash {5:X16}, same={6}", label, frames, seconds, frames / seconds, maxSteps, trace.Hash, same));
report.AppendFormat(" {{\"target\": \"{0}\", \"frames\": {1}, \"seconds\": {2}, \"measured_fps\": {3}, \"max_steps_per_frame\": {4}, \"steps\": {5}, \"hash\": \"{6:X16}\", \"winner\": {7}, \"same_as_core\": {8}}}{9}\n",
label, frames, PlayModeSupport.Number(seconds), PlayModeSupport.Number(frames / seconds), maxSteps, trace.Steps, trace.Hash, driver.Runner.Match.Winner, same ? "true" : "false", index < rates.Length - 1 ? "," : "");
}
Application.targetFrameRate = -1;
report.Append(" ]\n}\n");
string logs = Path.Combine(PlayModeSupport.Root, "docs/port/logs/u2c");
Directory.CreateDirectory(logs);
File.WriteAllText(Path.Combine(logs, "scene-frame-rates.json"), report.ToString());
Assert.IsEmpty(failures, string.Join("\n", failures));
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: df37372a1cb354cbc8cb638f55016610

View file

@ -0,0 +1,177 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using Luneraria.Core;
using UnityEngine;
namespace Luneraria.View
{
/// <summary>
/// Frame-time benchmark of a player build (U2D). Active only with the command-line argument
/// "-luneBenchmark &lt;out.json&gt;": runs the match of seed 9 from round 21 (the golden fixture
/// high_wave_21, the most units) at normal speed, VSync off, and measures two windows once the
/// armies meet: the whole map (20 s) and a close view of the Mid lane (10 s). Then it quits.
/// </summary>
[DefaultExecutionOrder(-100)]
public sealed class LuneBenchmark : MonoBehaviour
{
public LuneMatchDriver Driver;
public LuneMatchView View;
public LuneCameraRig Rig;
sealed class Window
{
public string Label;
public float Seconds;
public float Zoom;
public Vec2 Focus;
public readonly List<double> FrameMs = new List<double>();
public double Simulation;
public double Views;
public int Units;
public int GcStart;
public int GcEnd;
public int SlowFrames;
public int SlowWithStep;
public readonly List<double> MainThreadMs = new List<double>();
public readonly List<double> RenderThreadMs = new List<double>();
public readonly List<double> GpuMs = new List<double>();
public readonly List<double> PresentWaitMs = new List<double>();
}
readonly FrameTiming[] _timings = new FrameTiming[1];
string _out;
readonly List<Window> _windows = new List<Window>();
int _index = -1;
float _elapsed;
void Awake()
{
string[] args = Environment.GetCommandLineArgs();
int at = Array.IndexOf(args, "-luneBenchmark");
if (at < 0 || at + 1 >= args.Length)
{
enabled = false;
return;
}
_out = args[at + 1];
// The benchmark runs unattended; it must not pause when its window loses focus.
Application.runInBackground = true;
QualitySettings.vSyncCount = 0;
Application.targetFrameRate = -1;
_windows.Add(new Window { Label = "overview (zoom 64)", Seconds = 20f, Zoom = 64f, Focus = new Vec2(0, 0) });
_windows.Add(new Window { Label = "mid lane close (zoom 22)", Seconds = 10f, Zoom = 22f, Focus = new Vec2(0, 0) });
}
void Start()
{
Driver.Seed = 9;
Driver.StartRound = 21;
Driver.ExtraGold = 4000;
Driver.Speed = 1f;
Driver.Restart();
Rig.Interactive = false;
Rig.Overview(true);
}
void Update()
{
LuneMatch match = Driver.Runner.Match;
if (_index < 0)
{
if (Driver.Runner.Current == LuneMatchRunner.Stage.Combat && match.Combat.Elapsed >= 10.0)
Begin(0);
return;
}
if (_index >= _windows.Count)
return;
Window window = _windows[_index];
double ms = Time.unscaledDeltaTime * 1000.0;
window.FrameMs.Add(ms);
// Where the time goes (needs "Frame Timing Stats" in the player settings).
FrameTimingManager.CaptureFrameTimings();
if (FrameTimingManager.GetLatestTimings(1, _timings) > 0)
{
window.MainThreadMs.Add(_timings[0].cpuMainThreadFrameTime);
window.RenderThreadMs.Add(_timings[0].cpuRenderThreadFrameTime);
window.GpuMs.Add(_timings[0].gpuFrameTime);
window.PresentWaitMs.Add(_timings[0].cpuMainThreadPresentWaitTime);
}
// Frames above 1/60 s, and how many of them also ran a simulation step.
if (ms > 1000.0 / 60.0)
{
window.SlowFrames++;
if (Driver.Runner.StepsThisFrame > 0)
window.SlowWithStep++;
}
window.Simulation += Driver.LastAdvanceMs;
window.Views += View.LastSyncMs;
if (match.Combat != null && window.FrameMs.Count % 30 == 1)
window.Units = Math.Max(window.Units, CountAlive(match.Combat));
_elapsed += Time.unscaledDeltaTime;
if (_elapsed >= window.Seconds)
{
window.GcEnd = GC.CollectionCount(0);
if (_index + 1 < _windows.Count)
Begin(_index + 1);
else
Finish();
}
}
static string Describe(List<double> values)
{
if (values.Count == 0)
return "n/a";
double[] sorted = values.OrderBy(v => v).ToArray();
return string.Format(CultureInfo.InvariantCulture, "avg {0:0.00} / median {1:0.00} / p95 {2:0.00} ms", sorted.Average(), sorted[sorted.Length / 2], sorted[(int)(sorted.Length * .95)]);
}
static int CountAlive(LuneCombat combat)
{
int count = 0;
foreach (LuneUnit unit in combat.Units)
if (unit.Alive && unit.IsMobile())
count++;
return count;
}
void Begin(int index)
{
_index = index;
_elapsed = 0f;
Window window = _windows[index];
window.GcStart = GC.CollectionCount(0);
Rig.LookAt(window.Focus, window.Zoom, true);
}
void Finish()
{
_index = _windows.Count;
var text = new System.Text.StringBuilder("{\n");
text.AppendFormat(" \"build\": \"{0} player, {1}, {2}\",\n", Application.platform, Application.unityVersion, Debug.isDebugBuild ? "development" : "release");
text.AppendFormat(" \"device\": \"{0}; {1}; {2}\",\n", SystemInfo.deviceModel, SystemInfo.processorType, SystemInfo.graphicsDeviceName);
text.AppendFormat(" \"graphics_api\": \"{0}\",\n \"resolution\": \"{1}x{2}\",\n \"vsync\": {3},\n", SystemInfo.graphicsDeviceType, Screen.width, Screen.height, QualitySettings.vSyncCount);
text.Append(" \"match\": \"seed 9 from round 21 (fixture high_wave_21), speed 1x, measured after 10 s of combat\",\n \"windows\": [\n");
for (int i = 0; i < _windows.Count; i++)
{
Window window = _windows[i];
double[] sorted = window.FrameMs.OrderBy(v => v).ToArray();
double total = window.FrameMs.Sum();
text.AppendFormat(CultureInfo.InvariantCulture,
" {{\"view\": \"{0}\", \"frames\": {1}, \"fps\": {2:0.0}, \"frame_ms_avg\": {3:0.00}, \"frame_ms_median\": {4:0.00}, \"frame_ms_p95\": {5:0.00}, \"frame_ms_p99\": {6:0.00}, \"frame_ms_max\": {7:0.00}, \"frames_over_16_7_ms\": {8}, \"of_them_with_simulation_step\": {9}, \"gc_collections\": {10}, \"simulation_ms_per_frame\": {11:0.000}, \"views_ms_per_frame\": {12:0.000}, \"units_alive_max\": {13}}}{14}\n",
window.Label, sorted.Length, sorted.Length / (total / 1000.0), total / sorted.Length, sorted[sorted.Length / 2], sorted[(int)(sorted.Length * .95)], sorted[(int)(sorted.Length * .99)], sorted[sorted.Length - 1],
window.SlowFrames, window.SlowWithStep, window.GcEnd - window.GcStart, window.Simulation / sorted.Length, window.Views / sorted.Length, window.Units, i < _windows.Count - 1 ? "," : "");
text.AppendFormat(CultureInfo.InvariantCulture, " // timings {0}: main thread {1}, render thread {2}, gpu {3}, present wait {4}\n", window.Label,
Describe(window.MainThreadMs), Describe(window.RenderThreadMs), Describe(window.GpuMs), Describe(window.PresentWaitMs));
}
text.Append(" ]\n}\n");
Directory.CreateDirectory(Path.GetDirectoryName(_out));
File.WriteAllText(_out, text.ToString());
Application.Quit();
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ab1ea9c0f58c943ccb61b914a38989b9

View file

@ -23,7 +23,72 @@ namespace Luneraria.View
public string Tier = "";
public Look Current = Look.Intact;
/// <summary>Length of the collapse before the ruin shows (Godot DESTROY_SECONDS).</summary>
public const float DestroySeconds = 1.7f;
readonly Dictionary<string, Transform> _parts = new Dictionary<string, Transform>();
readonly Dictionary<string, Pose> _rest = new Dictionary<string, Pose>();
float _destroyTime = -1f;
bool _destroyFromHeavy;
/// <summary>Crystal tip (where tower bolts leave).</summary>
public Vector3 Muzzle
{
get
{
Collect();
if (_parts.TryGetValue("Crystal", out Transform crystal))
return crystal.position + Vector3.up * .35f;
return transform.position + Vector3.up * 5f;
}
}
/// <summary>
/// Authoritative HP to a look. A building that falls while the view watches collapses first;
/// one that is already down when the view is built appears as a ruin at once.
/// </summary>
public void SetHealth(float hp, float maxHp, bool animate)
{
Look next = LookFor(hp, maxHp);
if (Current == Look.Destroying)
return;
if (next == Look.Ruin && Current != Look.Ruin && animate)
{
_destroyFromHeavy = Current == Look.Heavy;
Show(Look.Destroying);
_destroyTime = 0f;
return;
}
if (next != Current)
Show(next);
}
void Update()
{
if (Current != Look.Destroying)
return;
_destroyTime += Time.deltaTime;
float k = Mathf.Clamp01(_destroyTime / DestroySeconds);
// The upper part tips over and sinks; the Ancient's structure sinks into its dais.
foreach (KeyValuePair<string, Transform> part in _parts)
{
if (!_rest.TryGetValue(part.Key, out Pose rest))
continue;
bool falls = IsAncient ? !part.Key.StartsWith("Ruin") && part.Key != "Dais" && part.Key != "Pedestal"
: part.Key == "Upper" || part.Key == "Upper_Damaged" || part.Key == "Crystal" || part.Key == "Ring" || part.Key.StartsWith("Shard") || part.Key.StartsWith("Pennant") || part.Key.StartsWith("Banner");
if (!falls)
continue;
part.Value.localRotation = rest.rotation * Quaternion.Euler(0f, 0f, 70f * k * k);
part.Value.localPosition = rest.position + Vector3.down * 3f * k * k;
}
if (k >= 1f)
{
foreach (KeyValuePair<string, Transform> part in _parts)
if (_rest.TryGetValue(part.Key, out Pose rest))
part.Value.SetLocalPositionAndRotation(rest.position, rest.rotation);
Show(Look.Ruin);
}
}
public bool IsAncient { get { return Tier == "core"; } }
@ -33,7 +98,10 @@ namespace Luneraria.View
return;
Transform model = transform.childCount > 0 ? transform.GetChild(0) : transform;
foreach (Transform part in model)
{
_parts[part.name] = part;
_rest[part.name] = new Pose(part.localPosition, part.localRotation);
}
}
/// <summary>Look for an HP fraction; a destroyed building shows its ruin.</summary>
@ -75,7 +143,7 @@ namespace Luneraria.View
}
return;
}
bool damagedTop = look == Look.Heavy || look == Look.Destroying;
bool damagedTop = look == Look.Heavy || (look == Look.Destroying && _destroyFromHeavy);
Set("Upper", standing && !damagedTop);
Set("Upper_Damaged", standing && damagedTop);
Set("Debris", look == Look.Heavy || look == Look.Destroying);

View file

@ -0,0 +1,130 @@
using Luneraria.Core;
using UnityEngine;
namespace Luneraria.View
{
/// <summary>
/// The MOBA camera of the reference (lune_camera.gd): WASD or arrows pan, mouse wheel zooms,
/// Q/E turn in 45 degree steps, R resets, O shows the whole map, middle mouse drags. The focus
/// follows the ground. Uses the classic input manager until the HUD port (U3) moves input over.
/// </summary>
public sealed class LuneCameraRig : MonoBehaviour
{
public LuneGround Ground;
public bool Interactive = true;
public float Zoom = LuneCameraMath.DefaultZoom;
public float Yaw;
Vec2 _focus;
Vec2 _goalFocus;
float _goalZoom = LuneCameraMath.DefaultZoom;
float _goalYaw;
Vector3 _dragAnchor;
public void LookAt(Vec2 point, float zoom = -1f, bool instant = false)
{
_goalFocus = new Vec2(Mathf.Clamp((float)point.X, -LuneCameraMath.FocusLimit, LuneCameraMath.FocusLimit),
Mathf.Clamp((float)point.Y, -LuneCameraMath.FocusLimit, LuneCameraMath.FocusLimit));
if (zoom > 0f)
_goalZoom = Mathf.Clamp(zoom, LuneCameraMath.MinZoom, LuneCameraMath.MaxZoom);
if (instant)
{
_focus = _goalFocus;
Zoom = _goalZoom;
Yaw = _goalYaw;
Apply();
}
}
public void SetYawSteps(int steps, bool instant = false)
{
_goalYaw = steps * Mathf.PI * .25f;
if (instant)
{
Yaw = _goalYaw;
Apply();
}
}
/// <summary>Camera heading in radians (Godot yaw: 0 looks from the map's +y side).</summary>
public void SetYaw(float radians, bool instant = false)
{
_goalYaw = radians;
if (instant)
{
Yaw = _goalYaw;
Apply();
}
}
/// <summary>Yaw that puts the camera on the side of `from` that faces `towards`.</summary>
public static float YawTowards(Vec2 from, Vec2 towards)
{
Vec2 d = towards - from;
return Mathf.Atan2((float)d.X, (float)d.Y);
}
public void Overview(bool instant = false)
{
LookAt(new Vec2(0, 0), LuneCameraMath.OverviewZoom, instant);
}
void Apply()
{
float height = Ground != null ? Ground.StandHeight(_focus) : 0f;
LuneCameraMath.Pose(LuneSpace.World(_focus, height), Zoom, Yaw, out Vector3 position, out Quaternion rotation);
transform.SetPositionAndRotation(position, rotation);
}
void LateUpdate()
{
float dt = Time.unscaledDeltaTime;
if (Interactive)
HandleInput(dt);
float t = Mathf.Min(1f, dt * 7f);
_focus = _focus.Lerp(_goalFocus, t);
Zoom = Mathf.Lerp(Zoom, _goalZoom, t);
Yaw = Mathf.LerpAngle(Yaw * Mathf.Rad2Deg, _goalYaw * Mathf.Rad2Deg, t) * Mathf.Deg2Rad;
Apply();
}
void HandleInput(float dt)
{
var pan = new Vector2(Input.GetAxisRaw("Horizontal"), -Input.GetAxisRaw("Vertical"));
if (pan != Vector2.zero)
{
// Godot: right = (cos yaw, 0, -sin yaw), forward = (-sin yaw, 0, -cos yaw), map frame.
var right = new Vec2(Mathf.Cos(Yaw), -Mathf.Sin(Yaw));
var forward = new Vec2(-Mathf.Sin(Yaw), -Mathf.Cos(Yaw));
Vec2 move = right * (pan.x * Zoom * .9f * dt) - forward * (pan.y * Zoom * .9f * dt);
LookAt(_goalFocus + move);
}
float wheel = Input.mouseScrollDelta.y;
if (wheel > 0f)
_goalZoom = Mathf.Max(LuneCameraMath.MinZoom, _goalZoom - Mathf.Max(2.5f, _goalZoom * .09f));
else if (wheel < 0f)
_goalZoom = Mathf.Min(LuneCameraMath.MaxZoom, _goalZoom + Mathf.Max(2.5f, _goalZoom * .09f));
if (Input.GetKeyDown(KeyCode.Q))
_goalYaw -= Mathf.PI * .25f;
if (Input.GetKeyDown(KeyCode.E))
_goalYaw += Mathf.PI * .25f;
if (Input.GetKeyDown(KeyCode.R))
{
_goalYaw = 0f;
LookAt(_goalFocus, LuneCameraMath.DefaultZoom);
}
if (Input.GetKeyDown(KeyCode.O))
Overview();
if (Input.GetMouseButtonDown(2))
_dragAnchor = Input.mousePosition;
if (Input.GetMouseButton(2))
{
Vector3 delta = Input.mousePosition - _dragAnchor;
_dragAnchor = Input.mousePosition;
var right = new Vec2(Mathf.Cos(Yaw), -Mathf.Sin(Yaw));
var forward = new Vec2(-Mathf.Sin(Yaw), -Mathf.Cos(Yaw));
// Screen y grows upwards in Unity (downwards in Godot).
LookAt(_goalFocus - (right * delta.x + forward * delta.y) * (Zoom / 700f));
}
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e6c3e3f0a9e754c01ab57a6296535e17

View file

@ -0,0 +1,30 @@
using System.IO;
using UnityEngine;
namespace Luneraria.View
{
/// <summary>Renders a camera into a PNG (screenshots of tests and tools, also in batch mode).</summary>
public static class LuneCapture
{
public static void Render(Camera camera, string file, int width = 1920, int height = 1080)
{
var target = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32) { antiAliasing = 4 };
RenderTexture previous = camera.targetTexture;
float aspect = camera.aspect;
camera.aspect = (float)width / height;
camera.targetTexture = target;
camera.Render();
RenderTexture.active = target;
var image = new Texture2D(width, height, TextureFormat.RGB24, false);
image.ReadPixels(new Rect(0, 0, width, height), 0, 0);
image.Apply();
Directory.CreateDirectory(Path.GetDirectoryName(file));
File.WriteAllBytes(file, image.EncodeToPNG());
RenderTexture.active = null;
camera.targetTexture = previous;
camera.aspect = aspect;
Object.Destroy(target);
Object.Destroy(image);
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: bf2671b51c98c4f8693435167bed25e6

View file

@ -0,0 +1,49 @@
using System;
namespace Luneraria.View
{
/// <summary>
/// Fixed simulation tick (U2C): frame time goes into an accumulator, and whole steps of
/// LuneBalance.SimStep (0.05 s) come out. The frame rate only decides how many steps run in a
/// frame, never what a step does, so every frame rate produces the same sequence of steps.
/// Alpha is the fraction of the next step already elapsed; views interpolate with it.
/// </summary>
public sealed class LuneClock
{
public readonly double Step;
/// <summary>Upper bound per frame; a stalled frame is caught up over the next frames.</summary>
public int MaxStepsPerFrame = 200;
double _accumulator;
public LuneClock(double step)
{
Step = step;
}
public double Alpha { get { return Math.Min(1.0, _accumulator / Step); } }
public void Reset()
{
_accumulator = 0.0;
}
/// <summary>Adds frame time and runs whole steps; step returns false when it has to stop.</summary>
public int Advance(double seconds, Func<bool> step)
{
if (seconds > 0.0)
_accumulator += seconds;
int count = 0;
while (_accumulator >= Step && count < MaxStepsPerFrame)
{
_accumulator -= Step;
count++;
if (!step())
{
_accumulator = 0.0;
break;
}
}
return count;
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 28ec5b6f44acc4721b30783873c76b47

View file

@ -0,0 +1,19 @@
using UnityEngine;
namespace Luneraria.View
{
/// <summary>
/// Receives the contact event of attack and ability clips (added by the FBX import rules at
/// the Blender action's contact time). Presentation only: the rules applied the hit already.
/// Counts contacts so effects and sounds can hook in later.
/// </summary>
public sealed class LuneContactReceiver : MonoBehaviour
{
public int Contacts { get; private set; }
public void OnLuneContact()
{
Contacts++;
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c3e1f2bd3d0974d289d193d32785ee83

View file

@ -0,0 +1,56 @@
using System.Linq;
using System.Text;
using Luneraria.Core;
using UnityEngine;
namespace Luneraria.View
{
/// <summary>
/// Temporary match readout for U2 (round, phase, buildings, heroes, boss, winner). Not a HUD:
/// the G3 HUD is ported in U3 and replaces this overlay.
/// </summary>
public sealed class LuneDebugOverlay : MonoBehaviour
{
public LuneMatchDriver Driver;
GUIStyle _style;
GUIContent _content = new GUIContent();
float _next;
void OnGUI()
{
if (Driver == null || Driver.Runner == null)
return;
if (_style == null)
_style = new GUIStyle(GUI.skin.box) { alignment = TextAnchor.UpperLeft, fontSize = 15, wordWrap = true, padding = new RectOffset(10, 10, 8, 8) };
// Four refreshes a second: building the text every GUI pass produced garbage each frame.
if (Time.unscaledTime >= _next)
{
_content.text = Text(Driver.Runner);
_next = Time.unscaledTime + .25f;
}
GUI.Box(new Rect(12, 12, 430, 150), _content, _style);
}
public static string Text(LuneMatchRunner runner)
{
LuneMatch match = runner.Match;
var text = new StringBuilder();
text.AppendFormat("U2 Debug (kein HUD) · Runde {0} · {1}\n", match.RoundNumber, runner.Current);
for (int team = 0; team < 2; team++)
{
int towers = match.Map.Buildings.Count(b => b.Team == team && b.Tier != "core" && match.BuildingHp[b.Id] > 0.0);
double core = match.BuildingHp[team == 0 ? "blau_ancient" : "rot_ancient"];
text.AppendFormat("{0}: Türme {1}/8 · Ancient {2:0}\n", team == 0 ? "Blau" : "Rot", towers, core);
}
if (match.Combat != null)
{
int heroes = match.Combat.Units.Count(u => u.Kind == "hero" && u.Alive);
int boss = match.Combat.Units.Count(u => u.Kind == "boss" && u.Alive);
text.AppendFormat("Kampf {0:0.0} s · Einheiten {1} · Helden {2} · Boss {3}\n", match.Combat.Elapsed, match.Combat.Units.Count(u => u.IsMobile() && u.Alive), heroes, boss);
}
if (match.Phase == Phase.Over)
text.AppendFormat("Sieger: {0} · {1}", match.Winner == 0 ? "Blau" : match.Winner == 1 ? "Rot" : "Unentschieden", match.EndNote);
return text.ToString();
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: dd301446233234cbe8a983e51f0aa25e

View file

@ -0,0 +1,48 @@
using Luneraria.Core;
using UnityEngine;
namespace Luneraria.View
{
/// <summary>
/// Hosts a bot match in the scene (U2C/U2D). Update only hands frame time (times Speed) to the
/// runner's fixed clock; it never decides anything in combat. Seed, start round and extra gold
/// are the public fixtures of the golden scenarios.
/// </summary>
public sealed class LuneMatchDriver : MonoBehaviour
{
public int Seed = 2;
public int StartRound = 1;
public int ExtraGold;
public string Profile = "";
/// <summary>Match speed: simulated seconds per real second.</summary>
public float Speed = 1f;
public bool Paused;
public bool RecordTrace = true;
public LuneMatchRunner Runner { get; private set; }
/// <summary>Main-thread cost of the last frame's simulation (milliseconds).</summary>
public double LastAdvanceMs { get; private set; }
readonly System.Diagnostics.Stopwatch _clock = new System.Diagnostics.Stopwatch();
public void Restart()
{
Runner = new LuneMatchRunner(new MatchOptions { Seed = Seed, HumanSlot = -1 }, StartRound, ExtraGold, Profile);
if (RecordTrace)
Runner.Trace = new LuneTrace();
}
void Awake()
{
if (Runner == null)
Restart();
}
void Update()
{
_clock.Restart();
if (!Paused)
Runner.Advance(Time.deltaTime * Speed);
LastAdvanceMs = _clock.Elapsed.TotalMilliseconds;
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8de509cb5a54f42f0a0e02b19c6648ab

View file

@ -0,0 +1,113 @@
using System;
using Luneraria.Core;
namespace Luneraria.View
{
/// <summary>
/// Runs a bot match on the host (U2C/U2D) against wall-clock time: planning (the six bots plan
/// through the command interface), combat in fixed steps, a pause after the settlement, the
/// next round, until an Ancient falls. Only the core decides; time only paces the calls, so
/// the sequence of core calls is the one of LuneTrace.RunCore at every frame rate.
/// </summary>
public sealed class LuneMatchRunner
{
public enum Stage { Planning, Combat, Settled, Over }
public readonly LuneMatch Match;
public readonly LuneClock Clock;
public readonly string Profile;
public LuneTrace Trace;
public double PlanningSeconds = 1.0;
public double SettledSeconds = 2.0;
public int MaxRound = 60;
public Stage Current { get; private set; }
public int StepsThisFrame { get; private set; }
public event Action<LuneCombat> CombatStarted;
public event Action<Settlement> Settled;
public event Action<int> Finished;
double _stageTime;
public LuneMatchRunner(MatchOptions options, int startRound = 1, int extraGold = 0, string profile = "")
{
Match = NewMatch(options, startRound, extraGold);
Clock = new LuneClock(Match.Balance.SimStep);
Profile = profile;
EnterPlanning();
}
/// <summary>A match with the public fixtures the golden scenarios use (start round, gold).</summary>
public static LuneMatch NewMatch(MatchOptions options, int startRound, int extraGold)
{
var match = new LuneMatch();
match.Setup(options);
if (startRound > 1)
match.RoundNumber = startRound;
if (extraGold != 0)
foreach (Player player in match.Players)
player.Draft.Gold += extraGold;
return match;
}
void EnterPlanning()
{
Current = Stage.Planning;
_stageTime = 0.0;
for (int slot = 0; slot < 6; slot++)
LuneBot.Plan(Match, slot, Profile);
}
/// <summary>Advances by simulated seconds (frame time times match speed).</summary>
public void Advance(double seconds)
{
StepsThisFrame = 0;
switch (Current)
{
case Stage.Planning:
_stageTime += seconds;
if (_stageTime >= PlanningSeconds)
{
Match.BeginCombat();
Clock.Reset();
Current = Stage.Combat;
CombatStarted?.Invoke(Match.Combat);
}
break;
case Stage.Combat:
StepsThisFrame = Clock.Advance(seconds, StepOnce);
if (Match.Phase != Phase.Combat)
EndCombat();
break;
case Stage.Settled:
_stageTime += seconds;
if (_stageTime >= SettledSeconds)
EnterPlanning();
break;
}
}
bool StepOnce()
{
Match.StepCombat();
Trace?.RecordStep(Match.Combat);
return Match.Phase == Phase.Combat;
}
void EndCombat()
{
Trace?.RecordSettlement(Match);
Settled?.Invoke(Match.LastSettlement);
_stageTime = 0.0;
if (Match.Phase == Phase.Over || Match.RoundNumber > MaxRound)
{
Current = Stage.Over;
Finished?.Invoke(Match.Winner);
}
else
{
Current = Stage.Settled;
}
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5b861e38c3c9346738bfa107fd126637

View file

@ -0,0 +1,145 @@
using System.Collections.Generic;
using Luneraria.Core;
using UnityEngine;
namespace Luneraria.View
{
/// <summary>
/// Shows the driver's match (U2C): unit views per combat, building looks from the authoritative
/// HP, tower bolts from the towers' attack events. Runs after the driver in the same frame and
/// only reads the core.
/// </summary>
[DefaultExecutionOrder(100)]
public sealed class LuneMatchView : MonoBehaviour
{
public LuneMatchDriver Driver;
public LuneUnitLibrary Library;
public Camera ViewCamera;
readonly Dictionary<int, LuneUnitView> _units = new Dictionary<int, LuneUnitView>();
readonly Dictionary<string, LuneBuildingView> _buildings = new Dictionary<string, LuneBuildingView>();
readonly Dictionary<string, int> _towerSerials = new Dictionary<string, int>();
readonly List<Bolt> _bolts = new List<Bolt>();
LuneCombat _combat;
Transform _unitRoot;
bool _synced;
sealed class Bolt
{
public LineRenderer Line;
public float Age;
public LuneUnitView Target;
public Vector3 From;
}
public IEnumerable<LuneUnitView> Units { get { return _units.Values; } }
/// <summary>Main-thread cost of the last frame's view update (milliseconds).</summary>
public double LastSyncMs { get; private set; }
readonly System.Diagnostics.Stopwatch _clock = new System.Diagnostics.Stopwatch();
public LuneBuildingView Building(string id)
{
_buildings.TryGetValue(id, out LuneBuildingView view);
return view;
}
void Start()
{
foreach (LuneBuildingView building in FindObjectsByType<LuneBuildingView>(FindObjectsSortMode.None))
_buildings[building.BuildingId] = building;
_unitRoot = new GameObject("Units").transform;
if (ViewCamera == null)
ViewCamera = Camera.main;
}
void LateUpdate()
{
if (Driver == null || Driver.Runner == null)
return;
_clock.Restart();
LuneMatch match = Driver.Runner.Match;
float dt = Time.deltaTime;
if (match.Combat != _combat)
{
foreach (LuneUnitView view in _units.Values)
Destroy(view.gameObject);
_units.Clear();
_towerSerials.Clear();
_combat = match.Combat;
}
bool showUnits = _combat != null && Driver.Runner.Current != LuneMatchRunner.Stage.Planning;
float alpha = Driver.Runner.Current == LuneMatchRunner.Stage.Combat ? (float)Driver.Runner.Clock.Alpha : 1f;
if (showUnits)
{
foreach (LuneUnit unit in _combat.Units)
{
if (!unit.IsMobile())
continue;
if (!_units.TryGetValue(unit.Id, out LuneUnitView view))
{
view = new GameObject().AddComponent<LuneUnitView>();
view.transform.SetParent(_unitRoot, false);
view.Bind(unit, Library);
_units[unit.Id] = view;
}
view.Sync(alpha, dt, ViewCamera != null ? ViewCamera.transform : null);
}
}
SyncBuildings(match);
SyncBolts(dt);
_synced = true;
LastSyncMs = _clock.Elapsed.TotalMilliseconds;
}
void SyncBuildings(LuneMatch match)
{
bool fighting = _combat != null && match.Phase == Phase.Combat;
foreach (BuildingDef definition in match.Map.Buildings)
{
if (!_buildings.TryGetValue(definition.Id, out LuneBuildingView view))
continue;
double hp = match.BuildingHp[definition.Id];
LuneUnit unit = null;
if (_combat != null && _combat.Buildings.TryGetValue(definition.Id, out unit) && fighting)
hp = unit.Hp;
view.SetHealth((float)hp, (float)definition.MaxHp, _synced);
if (unit != null && unit.Kind == "tower" && _combat != null)
TowerAttack(view, unit);
}
}
void TowerAttack(LuneBuildingView view, LuneUnit tower)
{
_towerSerials.TryGetValue(tower.BuildingId, out int last);
_towerSerials[tower.BuildingId] = tower.AttackSerial;
if (tower.AttackSerial == last || last == 0 && tower.AttackSerial == 0)
return;
if (tower.Target == null || !_units.TryGetValue(tower.Target.Id, out LuneUnitView target))
return;
var line = new GameObject("Bolt").AddComponent<LineRenderer>();
line.transform.SetParent(_unitRoot, false);
line.sharedMaterial = Library.Bolt[Mathf.Clamp(view.Team, 0, 2)];
line.widthMultiplier = view.Tier == "base" ? .22f : .16f;
line.positionCount = 2;
line.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
_bolts.Add(new Bolt { Line = line, Target = target, From = view.Muzzle });
}
void SyncBolts(float dt)
{
for (int i = _bolts.Count - 1; i >= 0; i--)
{
Bolt bolt = _bolts[i];
bolt.Age += dt;
if (bolt.Age > .25f || bolt.Target == null)
{
Destroy(bolt.Line.gameObject);
_bolts.RemoveAt(i);
continue;
}
bolt.Line.SetPosition(0, bolt.From);
bolt.Line.SetPosition(1, bolt.Target.AimPoint);
}
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 43a34f60268384d4ba97d4f66e3b9210

View file

@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using Luneraria.Core;
namespace Luneraria.View
{
/// <summary>
/// Fingerprint of a match (U2C): FNV-1a over every combat step (step, time, and per unit id,
/// alive, hit points, position, target) and every settlement (gains, lost buildings, winner).
/// Two runs are the same match exactly when their fingerprints are equal; the Unity match and
/// the plain core run are compared this way at any frame rate.
/// </summary>
public sealed class LuneTrace
{
const ulong Offset = 14695981039346656037UL;
const ulong Prime = 1099511628211UL;
ulong _hash = Offset;
public int Steps;
public readonly List<ulong> RoundHashes = new List<ulong>();
public readonly List<string> Rounds = new List<string>();
public ulong Hash { get { return _hash; } }
void Mix(ulong value)
{
for (int i = 0; i < 8; i++)
{
_hash ^= (value >> (i * 8)) & 0xFF;
_hash *= Prime;
}
}
void Mix(double value) { Mix((ulong)BitConverter.DoubleToInt64Bits(value)); }
void Mix(float value) { Mix((ulong)(uint)BitConverter.ToInt32(BitConverter.GetBytes(value), 0)); }
public void RecordStep(LuneCombat combat)
{
Steps++;
Mix((ulong)combat.Steps);
Mix(combat.Elapsed);
foreach (LuneUnit unit in combat.Units)
{
Mix((ulong)unit.Id);
Mix(unit.Alive ? 1UL : 0UL);
Mix(unit.Hp);
Mix(unit.Position.X);
Mix(unit.Position.Y);
Mix((ulong)(unit.Target != null ? unit.Target.Id : 0));
}
}
public void RecordSettlement(LuneMatch match)
{
Settlement settlement = match.LastSettlement;
foreach (int gain in settlement.Gains)
Mix((ulong)(uint)gain);
foreach (string building in settlement.BuildingsLost)
foreach (char c in building)
Mix((ulong)c);
Mix((ulong)(uint)match.Winner);
RoundHashes.Add(_hash);
Rounds.Add(string.Format("round {0}: {1} steps, lost [{2}], winner {3}", settlement.Round, match.Combat != null ? match.Combat.Steps : 0,
string.Join(",", settlement.BuildingsLost), match.Winner));
}
/// <summary>The same match without Unity: plan, begin, step to the end, round after round.</summary>
public static LuneTrace RunCore(MatchOptions options, int startRound, int extraGold, string profile, int maxRound = 60)
{
var match = LuneMatchRunner.NewMatch(options, startRound, extraGold);
var trace = new LuneTrace();
while (match.Phase != Phase.Over && match.RoundNumber <= maxRound)
{
for (int slot = 0; slot < 6; slot++)
LuneBot.Plan(match, slot, profile);
match.BeginCombat();
while (match.Phase == Phase.Combat)
{
match.StepCombat();
trace.RecordStep(match.Combat);
}
trace.RecordSettlement(match);
}
return trace;
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2964fe36e99af492fa56cf50edd68c60

View file

@ -0,0 +1,46 @@
using Luneraria.Core;
using UnityEngine;
namespace Luneraria.View
{
/// <summary>
/// What a unit looks like in U2 (only the six representative assets are imported): the boss
/// is the Schlundkrone, heroes use the rigged Funkenlanze, every other unit the Kohlenbeißer
/// (g01, parts combined into one mesh). Team rings and bars tell the sides apart, as in Godot.
/// </summary>
public sealed class LuneUnitLibrary : ScriptableObject
{
public GameObject Rigid;
public GameObject Hero;
public RuntimeAnimatorController HeroController;
public GameObject Boss;
public RuntimeAnimatorController BossController;
public LuneMaterialSet Materials;
public LuneGround Ground;
public Mesh RingRound;
public Mesh RingDiamond;
public Mesh RingHexagon;
public Mesh Quad;
public Material[] TeamRing = new Material[3];
public Material HeroRing;
public Material BarBack;
public Material[] BarFill = new Material[3];
public Material[] Bolt = new Material[3];
public GameObject PrefabFor(LuneUnit unit, out RuntimeAnimatorController controller)
{
controller = null;
if (unit.Kind == "boss")
{
controller = BossController;
return Boss;
}
if (unit.Kind == "hero")
{
controller = HeroController;
return Hero;
}
return Rigid;
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: cc54af12d81bc4f6a89d31026a2cd83e

View file

@ -0,0 +1,175 @@
using System;
using Luneraria.Core;
using UnityEngine;
namespace Luneraria.View
{
/// <summary>
/// Visual twin of one LuneUnit (port of scripts/luneraria/view/lune_unit_view.gd). Reads the
/// authoritative state and never writes back: position between the last two fixed steps,
/// facing, clips from real combat events (attack and ability serials), team ring, health bar.
/// </summary>
public sealed class LuneUnitView : MonoBehaviour
{
public LuneUnit Unit { get; private set; }
LuneGround _ground;
Transform _model;
Animator _animator;
bool _skeletal;
float _height = 1.6f;
Transform _ring;
Transform _bars;
Transform _fill;
int _lastAttack;
int _lastAbility;
float _attackFlash;
float _time;
Vector3 _lastVisual;
string _clip = "";
bool _attackB;
bool _deathShown;
public void Bind(LuneUnit unit, LuneUnitLibrary library)
{
Unit = unit;
_ground = library.Ground;
name = "Unit_" + unit.Id + "_" + unit.Kind;
GameObject prefab = library.PrefabFor(unit, out RuntimeAnimatorController controller);
_model = Instantiate(prefab, transform, false).transform;
_model.name = "Model";
float scale = (float)Math.Max(.1, unit.Def.ViewScale);
_model.localScale = Vector3.one * scale;
library.Materials.Dress(_model.gameObject, unit.Team);
_animator = _model.GetComponentInChildren<Animator>();
_skeletal = controller != null && _animator != null;
if (_skeletal)
{
_animator.runtimeAnimatorController = controller;
_animator.applyRootMotion = false;
_animator.gameObject.AddComponent<LuneContactReceiver>();
}
var bounds = new Bounds(transform.position, Vector3.zero);
foreach (Renderer renderer in _model.GetComponentsInChildren<Renderer>())
bounds.Encapsulate(renderer.bounds);
_height = Mathf.Max(1f, bounds.max.y - transform.position.y);
int team = Mathf.Clamp(unit.Team, 0, 2);
_ring = Marker("Ring", team == 0 ? library.RingRound : team == 1 ? library.RingDiamond : library.RingHexagon,
unit.Kind == "hero" ? library.HeroRing : library.TeamRing[team]);
_ring.localScale = new Vector3(scale, 1f, scale);
_ring.localPosition = new Vector3(0f, .05f, 0f);
_bars = new GameObject("Bars").transform;
_bars.SetParent(transform, false);
_bars.localPosition = new Vector3(0f, _height + .25f, 0f);
Transform back = Marker("Back", library.Quad, library.BarBack);
back.SetParent(_bars, false);
back.localScale = new Vector3(.9f, .1f, 1f);
_fill = Marker("Fill", library.Quad, library.BarFill[team]);
_fill.SetParent(_bars, false);
_fill.localScale = new Vector3(.86f, .07f, 1f);
_fill.localPosition = new Vector3(0f, 0f, -.001f);
_lastAttack = unit.AttackSerial;
_lastAbility = unit.AbilitySerial;
transform.position = Ground(unit.Position);
transform.rotation = LuneSpace.Facing(unit.Facing);
_lastVisual = transform.position;
Play("idle");
}
Transform Marker(string label, Mesh mesh, Material material)
{
var go = new GameObject(label);
go.transform.SetParent(transform, false);
go.AddComponent<MeshFilter>().sharedMesh = mesh;
var renderer = go.AddComponent<MeshRenderer>();
renderer.sharedMaterial = material;
renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
renderer.receiveShadows = false;
return go.transform;
}
Vector3 Ground(Vec2 at)
{
return LuneSpace.World(at, (_ground != null ? _ground.StandHeight(at) : 0f) + .03f);
}
/// <summary>Where tower bolts hit this figure (upper body).</summary>
public Vector3 AimPoint { get { return transform.position + Vector3.up * _height * .55f; } }
public void Sync(float alpha, float dt, Transform camera)
{
_time += dt;
Vec2 at = Unit.PreviousPosition.Lerp(Unit.Position, Mathf.Clamp01(alpha));
transform.position = Ground(at);
transform.rotation = Quaternion.Slerp(transform.rotation, LuneSpace.Facing(Unit.Facing), Mathf.Min(1f, dt * 12f));
float moved = Vector2.Distance(new Vector2(transform.position.x, transform.position.z), new Vector2(_lastVisual.x, _lastVisual.z));
_lastVisual = transform.position;
bool attacked = Unit.AttackSerial != _lastAttack;
bool ability = Unit.AbilitySerial != _lastAbility;
_lastAttack = Unit.AttackSerial;
_lastAbility = Unit.AbilitySerial;
if (attacked || ability)
_attackFlash = .28f;
_attackFlash = Mathf.Max(0f, _attackFlash - dt);
if (_skeletal)
AnimateSkeletal(moved, attacked, ability);
else
AnimateRigid(moved);
float fraction = Mathf.Clamp01((float)(Unit.Hp / Math.Max(1.0, Unit.MaxHp)));
_fill.localScale = new Vector3(.86f * Mathf.Max(.001f, fraction), .07f, 1f);
_fill.localPosition = new Vector3(-.43f * (1f - fraction), 0f, -.001f);
_bars.gameObject.SetActive(Unit.Alive && fraction < .999f);
if (camera != null)
_bars.rotation = camera.rotation;
_ring.gameObject.SetActive(Unit.Alive);
// Rigid figures have no death clip; skeletal ones stay down in their death pose.
if (!_skeletal)
_model.gameObject.SetActive(Unit.Alive);
}
void AnimateSkeletal(float moved, bool attacked, bool ability)
{
if (!Unit.Alive)
{
if (!_deathShown)
Play("death");
_deathShown = true;
return;
}
if (ability)
Play("ability", true);
else if (attacked)
{
Play(_attackB ? "attack_b" : "attack_a", true);
_attackB = !_attackB;
}
else if (IsPlaying("attack_a") || IsPlaying("attack_b") || IsPlaying("ability"))
return;
else
Play(moved > .002f ? "walk" : "idle");
}
bool IsPlaying(string state)
{
AnimatorStateInfo info = _animator.GetCurrentAnimatorStateInfo(0);
return info.IsName(state) && info.normalizedTime < .95f;
}
void Play(string state, bool restart = false)
{
if (!_skeletal || (_clip == state && !restart))
return;
_clip = state;
_animator.CrossFadeInFixedTime(state, .12f, 0, 0f);
}
/// <summary>Rigid figures: a stride bob while walking and a short lunge on attacks.</summary>
void AnimateRigid(float moved)
{
float bob = moved > .002f ? Mathf.Abs(Mathf.Sin((_time + Unit.Id * .23f) * 9f)) * .08f : 0f;
float lunge = Mathf.Sin(Mathf.Clamp01(_attackFlash / .28f) * Mathf.PI) * .25f;
_model.localPosition = new Vector3(0f, bob, lunge);
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7cad021503f5547fa9e5ff9933799bda

View file

@ -1,12 +1,12 @@
# U2 · Unity-Spielwelt
Stand: 30. September 2026.
Stand: 1. Oktober 2026.
| Teil | Inhalt | Zustand |
| --- | --- | --- |
| U2A | Blender→FBX-Pipeline, sechs repräsentative Assets vollständig geprüft | **fertig** |
| U2B | Weltgeometrie (G1-Karte, Türme, Ancients, Grotte, Aufstellungsbereiche), Materialsystem | **fertig** |
| U2C | Simulation/Darstellung: fester Takt, Interpolation, Bildraten-Unabhängigkeit | offen |
| U2C | Simulation/Darstellung: fester Takt, Interpolation, Bildraten-Unabhängigkeit | **fertig** |
| U2D | spielbare Unity-Partie, Vertical Function Test | offen |
Voraussetzung U1.5 ist erfüllt ([U1.5-UNITY.md](U1.5-UNITY.md)).
@ -216,9 +216,61 @@ Unterschiede:
- Die Materialien sind vereinfacht (siehe oben).
- Die Beleuchtung ist ähnlich, aber nicht identisch abgestimmt.
## U2C bis U2D
## U2C · Simulation und Darstellung
Folgen in diesem Dokument.
### Aufbau
| Teil | Aufgabe |
| --- | --- |
| `LuneClock` | fester Takt: Bildzeit geht in einen Akkumulator, heraus kommen ganze Schritte zu 0,05 s (`LuneBalance.SimStep`); `Alpha` ist der Bruchteil des nächsten Schritts |
| `LuneMatchRunner` | Host-Ablauf einer Bot-Partie: Planung (die sechs Bots planen über die Befehlsschnittstelle), Kampf in festen Schritten, Pause nach der Abrechnung, nächste Runde, bis ein Ancient fällt; reine Logik ohne Unity |
| `LuneMatchDriver` | MonoBehaviour: `Update` reicht nur Bildzeit × Spieltempo an den Takt weiter |
| `LuneMatchView` | liest den Kern (nach dem Driver): eine Einheitenansicht je Einheit und Kampf, Gebäudezustände aus den autoritativen HP, Turmblitze aus den Angriffsereignissen der Türme |
| `LuneUnitView` | Position zwischen den letzten beiden Schritten interpoliert, Blickrichtung, Clips aus echten Kampfereignissen, Teamring, Lebensbalken |
| `LuneBuildingView` | fünf Zustände wie in Godot (intakt, leicht, schwer beschädigt, Einsturz, Ruine); fällt ein Gebäude unter den Augen des Betrachters, stürzt es 1,7 s lang ein |
| `LuneTrace` | Fingerabdruck einer Partie (FNV-1a über jeden Schritt und jede Abrechnung) zum Vergleich mit dem reinen Kernlauf |
Regeln bleiben im Kern:
- Die Szene besitzt keine. `Update()` entscheidet nie über den Kampf; die Bildrate bestimmt nur, wie viele Schritte in ein Bild fallen, nie, was ein Schritt tut.
- Ansichten schreiben nichts zurück; eine Animation löst keine Regelwirkung aus.
- Umgekehrt führen Kernzustände zu Darstellung: Gebäude-HP 0 → Einsturz und Ruine; Angriffszähler → Clip und Turmblitz.
### Nachweis Bildraten-Unabhängigkeit
**Logisch** (EditMode, `FrameRateIndependenceTests`): Der Runner bekommt verschiedene Bildzeitfolgen. Jede muss Schritt für Schritt und Runde für Runde den Fingerabdruck des Kernlaufs ergeben (`LuneTrace.RunCore`).
| Bildfolge | Seed 2 (volle Partie) | Seed 9 ab Runde 21 |
| --- | --- | --- |
| 30 fps | 19.315 Bilder, gleich | 6.342 Bilder, gleich |
| 60 fps | 38.597 Bilder, gleich | 12.678 Bilder, gleich |
| 120 fps | 77.169 Bilder, gleich | 25.352 Bilder, gleich |
| unbegrenzt (0,4–3,9 ms, schwankend) | 569.627 Bilder, gleich | 99.090 Bilder, gleich |
| Ruckler (Stillstände bis 0,4 s) | 26.845 Bilder, gleich | 8.796 Bilder, gleich |
| Spieltempo 8× | gleich | – |
Seed 2 ergibt jedes Mal 12.690 Schritte mit Fingerabdruck `DCE95C96556F3A1A`, Seed 9 jedes Mal 4.195 Schritte mit `7B8E43AEFC0D60C5`.
**In der echten Szene** (PlayMode, `SceneFrameRateTests`): Die Partie mit Seed 2 läuft mit allen Ansichten bei `Application.targetFrameRate` 30, 60, 120 und unbegrenzt (VSync aus), bei Spieltempo 24×.
| Ziel | gemessen | Bilder | Schritte je Bild höchstens | Ergebnis |
| --- | ---: | ---: | ---: | --- |
| 30 fps | 30,0 fps | 816 | 17 | gleich dem Kern |
| 60 fps | 60,0 fps | 1.626 | 9 | gleich dem Kern |
| 120 fps | 120,0 fps | 3.227 | 6 | gleich dem Kern |
| unbegrenzt | 4.696 fps | 125.732 | 3 | gleich dem Kern |
Im Batchmodus zeichnet Unity kein Bild auf einen Bildschirm; daher die sehr hohe Rate bei „unbegrenzt“. Die Bildzeiten mit Grafik stehen bei U2D (Player). Protokoll: `logs/u2c/scene-frame-rates.json`.
### Bekannte Grenzen
- **Einheitenmodelle:** Bis zum Batch-Import zeigen Einheiten die repräsentativen Modelle. Truppen, Monster und Champions sind der Kohlenbeißer (131 Teile zu einem Mesh zusammengefasst), Helden die Funkenlanze, Bosse die Schlundkrone. Teamringe (rund, Raute, Sechseck) und Balken unterscheiden die Seiten wie in Godot.
- **Animation:** Die starren Figuren haben nur Schrittwippen und Angriffsausfall; Godots prozedurale Gliederbewegung folgt mit dem Batch-Import. Figuren mit Skelett spielen die Blender-Clips (idle, walk, attack_a/b, ability, death).
- **Weitere Vereinfachungen:** Turmblitze sind kurze Linien. Die Einsturzsequenz ist vereinfacht (Kippen und Absinken). Der schlafende Boss zwischen den Kämpfen und die Planungsflächen fehlen noch.
- **Kamera:** wie `lune_camera.gd` (WASD, Mausrad, Q/E, R, O, mittlere Maustaste), vorerst mit dem klassischen Input Manager.
## U2D
Folgt in diesem Dokument.
## Abnahme (gesamt)

View file

@ -0,0 +1,11 @@
{
"match": "seed 2, bots, speed 24x",
"core_hash": "DCE95C96556F3A1A",
"core_steps": 12690,
"runs": [
{"target": "30 fps", "frames": 816, "seconds": 27.195, "measured_fps": 30.006, "max_steps_per_frame": 17, "steps": 12690, "hash": "DCE95C96556F3A1A", "winner": 1, "same_as_core": true},
{"target": "60 fps", "frames": 1626, "seconds": 27.092, "measured_fps": 60.017, "max_steps_per_frame": 9, "steps": 12690, "hash": "DCE95C96556F3A1A", "winner": 1, "same_as_core": true},
{"target": "120 fps", "frames": 3227, "seconds": 26.885, "measured_fps": 120.031, "max_steps_per_frame": 6, "steps": 12690, "hash": "DCE95C96556F3A1A", "winner": 1, "same_as_core": true},
{"target": "unlimited", "frames": 126621, "seconds": 26.775, "measured_fps": 4729.108, "max_steps_per_frame": 3, "steps": 12690, "hash": "DCE95C96556F3A1A", "winner": 1, "same_as_core": true}
]
}