Compare commits

..

30 Commits

Author SHA1 Message Date
26625f6b6f Attempt to improve time 2026-01-01 21:49:12 +01:00
69a0a752be Successful sync test 2026-01-01 20:44:34 +01:00
97fe8cd69f Trying to get stuff to work 2025-12-29 21:02:05 +01:00
8d5362eff6 Fixed stuff 2025-12-28 19:55:54 +01:00
e3f93c69c5 Removing more networking things 2025-12-28 19:40:10 +01:00
74223c8139 Added NetworkManager 2025-12-28 19:35:18 +01:00
129ef16714 PrepareForCutscene 2025-12-26 18:28:17 +01:00
a15f977107 No SetMazeActive 2025-12-26 18:15:51 +01:00
f53a41f70c Cleaning up 2025-12-26 18:14:48 +01:00
16b0a348e4 Removed queue 2025-12-26 16:48:39 +01:00
8dec85e9f2 Added time sequence buttons 2025-12-26 16:05:03 +01:00
a251763158 Fixed stuff 2025-12-24 21:09:26 +01:00
8e9936274f Separated time sequence finish 2025-12-24 19:09:49 +01:00
43ee68dc44 Removed RECORDING_DEMO from ghost 2025-12-22 22:40:44 +01:00
39fb76d469 Fixed demo being borked 2025-12-22 21:53:24 +01:00
a3cd69a12f Annoying log 2025-12-22 20:11:07 +01:00
e0f3c39997 Put in all the sequences 2025-12-22 19:55:59 +01:00
51206b96f4 Intermission 3 2025-12-21 18:50:57 +01:00
0dd0d87e32 Clean 2025-12-21 18:04:43 +01:00
15267f90e9 Fixed Intermission 1 2025-12-21 17:58:38 +01:00
346ae7884e Intermission 2 2025-12-21 17:40:26 +01:00
fb539bfdf5 Added intermission1 2025-12-20 18:28:50 +01:00
8cf3f95af9 Separated time sequences 2025-12-14 17:05:24 +01:00
a2a576a0c9 Fixes 2025-12-14 16:50:25 +01:00
5355effc23 Renamed GameController 2025-12-14 15:52:34 +01:00
1fd5eb1f44 Etc 2025-12-13 20:36:36 +01:00
a2779ab31b More sound stuff 2025-12-13 20:30:54 +01:00
42a32f5fe4 Sound updates 2025-12-13 17:27:04 +01:00
3bc8db347d Progress 2025-12-11 22:43:40 +01:00
75b9459157 More sounds 2025-12-10 23:37:36 +01:00
146 changed files with 18631 additions and 4511 deletions

6
.vsconfig Normal file
View File

@@ -0,0 +1,6 @@
{
"version": "1.0",
"components": [
"Microsoft.VisualStudio.Workload.ManagedGame"
]
}

View File

@@ -47,6 +47,61 @@ BlendTree:
m_UseAutomaticThresholds: 1
m_NormalizedBlendValues: 0
m_BlendType: 1
--- !u!206 &-8944447067464121002
BlendTree:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Special
m_Childs:
- serializedVersion: 2
m_Motion: {fileID: 7400000, guid: 7285e9dfd47eeb64f8a359c3d14be984, type: 2}
m_Threshold: 0
m_Position: {x: 1, y: 0}
m_TimeScale: 1
m_CycleOffset: 0
m_DirectBlendParameter: DirX
m_Mirror: 0
- serializedVersion: 2
m_Motion: {fileID: 7400000, guid: aaf4617f2ca36da40883d1c0fa350dbc, type: 2}
m_Threshold: 0.25
m_Position: {x: -1, y: 0}
m_TimeScale: 1
m_CycleOffset: 0
m_DirectBlendParameter: DirX
m_Mirror: 0
- serializedVersion: 2
m_Motion: {fileID: 7400000, guid: 85bb4d19537fb1d429f9b123bc9d9c00, type: 2}
m_Threshold: 0.5
m_Position: {x: 0, y: 1}
m_TimeScale: 1
m_CycleOffset: 0
m_DirectBlendParameter: DirX
m_Mirror: 0
- serializedVersion: 2
m_Motion: {fileID: 7400000, guid: 454d1764e1b7a1946808d4221d71c6c5, type: 2}
m_Threshold: 0.75
m_Position: {x: 0, y: -1}
m_TimeScale: 1
m_CycleOffset: 0
m_DirectBlendParameter: DirX
m_Mirror: 0
- serializedVersion: 2
m_Motion: {fileID: 7400000, guid: 2e01a9fa01711c949a6922e3ebaece0f, type: 2}
m_Threshold: 1
m_Position: {x: 0, y: 0}
m_TimeScale: 1
m_CycleOffset: 0
m_DirectBlendParameter: DirX
m_Mirror: 0
m_BlendParameter: DirX
m_BlendParameterY: DirY
m_MinThreshold: 0
m_MaxThreshold: 1
m_UseAutomaticThresholds: 1
m_NormalizedBlendValues: 0
m_BlendType: 1
--- !u!206 &-6725170829935541210
BlendTree:
m_ObjectHideFlags: 1
@@ -228,19 +283,19 @@ AnimatorController:
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 0}
m_Controller: {fileID: 9100000}
- m_Name: DirY
m_Type: 1
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 0}
m_Controller: {fileID: 9100000}
- m_Name: GhostType
m_Type: 1
m_DefaultFloat: 1
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 0}
m_Controller: {fileID: 9100000}
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
@@ -417,10 +472,18 @@ BlendTree:
m_CycleOffset: 0
m_DirectBlendParameter: GhostState
m_Mirror: 0
- serializedVersion: 2
m_Motion: {fileID: -8944447067464121002}
m_Threshold: 7
m_Position: {x: 0, y: 0}
m_TimeScale: 1
m_CycleOffset: 0
m_DirectBlendParameter: DirX
m_Mirror: 0
m_BlendParameter: GhostType
m_BlendParameterY: Blend
m_MinThreshold: 0
m_MaxThreshold: 6
m_MaxThreshold: 7
m_UseAutomaticThresholds: 0
m_NormalizedBlendValues: 0
m_BlendType: 0

View File

@@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: SpecialDown Leg cover torn
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: -1398607546, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 15
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: -1398607546, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.06666667
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

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

View File

@@ -0,0 +1,75 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: SpecialLeft Stiched up
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 1662480253, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
- time: 0.06666667
value: {fileID: 1425082029, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 15
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 1662480253, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
- {fileID: 1425082029, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.13333334
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

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

View File

@@ -0,0 +1,75 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: SpecialRight dragging cover
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 938106153, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
- time: 0.06666667
value: {fileID: -824318244, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 15
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 938106153, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
- {fileID: -824318244, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.13333334
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

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

View File

@@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: SpecialUp Leg cover torn
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 222565271, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 15
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 222565271, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.06666667
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

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

View File

@@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: SpecialZero
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: -1398607546, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 15
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: -1398607546, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.06666667
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

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

View File

@@ -126,11 +126,19 @@ BlendTree:
m_CycleOffset: 0
m_DirectBlendParameter: Blend
m_Mirror: 0
- serializedVersion: 2
m_Motion: {fileID: 7400000, guid: a28e7bee3098d0a4996a108a60ccf4c0, type: 2}
m_Threshold: 1.25
m_Position: {x: 0, y: 0}
m_TimeScale: 1
m_CycleOffset: 0
m_DirectBlendParameter: Direction
m_Mirror: 0
m_BlendParameter: Direction
m_BlendParameterY: Blend
m_MinThreshold: 0
m_MaxThreshold: 1
m_UseAutomaticThresholds: 1
m_MaxThreshold: 1.25
m_UseAutomaticThresholds: 0
m_NormalizedBlendValues: 0
m_BlendType: 0
--- !u!91 &9100000
@@ -147,25 +155,25 @@ AnimatorController:
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 0}
m_Controller: {fileID: 9100000}
- m_Name: Eating
m_Type: 4
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 0}
m_Controller: {fileID: 9100000}
- m_Name: Direction
m_Type: 1
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 0}
m_Controller: {fileID: 9100000}
- m_Name: Reset
m_Type: 9
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 0}
m_Controller: {fileID: 9100000}
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer

View File

@@ -0,0 +1,81 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: PacManEatRightBig
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: -1729128937, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
- time: 0.055555556
value: {fileID: -63752043, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
- time: 0.11111111
value: {fileID: 1288529213, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
- time: 0.16666667
value: {fileID: -63752043, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 18
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: -1729128937, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
- {fileID: -63752043, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
- {fileID: 1288529213, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
- {fileID: -63752043, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.22222222
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

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

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 3d8e24cfdcd973f4ba3f87214ddd6896
guid: 712dee4d10687b8419e7ddcf1dfa728f
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Pole Base
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 1420031444, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 1420031444, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.016666668
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 0
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

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

View File

@@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Pole Separated
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 1473020388, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 1473020388, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.016666668
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 0
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

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

View File

@@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Pole Strech 1
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 1836525864, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 1836525864, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.016666668
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 0
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

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

View File

@@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Pole Strech 2
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: -1045593724, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: -1045593724, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.016666668
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 0
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

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

View File

@@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Pole Strech 3
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: -1340953024, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: -1340953024, guid: 7c9882097c3869842a9cfc7730a9a2dc, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.016666668
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 0
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

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

View File

@@ -0,0 +1,133 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!206 &-6499750159121831549
BlendTree:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Blend Tree
m_Childs:
- serializedVersion: 2
m_Motion: {fileID: 7400000, guid: e8a3071f9082e9248b263f38d82bbbc8, type: 2}
m_Threshold: 0
m_Position: {x: 0, y: 0}
m_TimeScale: 1
m_CycleOffset: 0
m_DirectBlendParameter: Blend
m_Mirror: 0
- serializedVersion: 2
m_Motion: {fileID: 7400000, guid: ac67a04acec0d9546b21851869fda2d4, type: 2}
m_Threshold: 1
m_Position: {x: 0, y: 0}
m_TimeScale: 1
m_CycleOffset: 0
m_DirectBlendParameter: Blend
m_Mirror: 0
- serializedVersion: 2
m_Motion: {fileID: 7400000, guid: 4a1a2d9f0f85bb14cbd4733341241ca3, type: 2}
m_Threshold: 2
m_Position: {x: 0, y: 0}
m_TimeScale: 1
m_CycleOffset: 0
m_DirectBlendParameter: Blend
m_Mirror: 0
- serializedVersion: 2
m_Motion: {fileID: 7400000, guid: a9c77b2807eb9a6408d84c525c9dba13, type: 2}
m_Threshold: 3
m_Position: {x: 0, y: 0}
m_TimeScale: 1
m_CycleOffset: 0
m_DirectBlendParameter: Blend
m_Mirror: 0
- serializedVersion: 2
m_Motion: {fileID: 7400000, guid: 83b261ac8c2e7f04ca0d8da11e8fc14f, type: 2}
m_Threshold: 4
m_Position: {x: 0, y: 0}
m_TimeScale: 1
m_CycleOffset: 0
m_DirectBlendParameter: Blend
m_Mirror: 0
m_BlendParameter: Strech
m_BlendParameterY: Blend
m_MinThreshold: 0
m_MaxThreshold: 4
m_UseAutomaticThresholds: 0
m_NormalizedBlendValues: 0
m_BlendType: 0
--- !u!1102 &-237968760341279601
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Blend Tree
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: -6499750159121831549}
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: Pole
serializedVersion: 5
m_AnimatorParameters:
- m_Name: Strech
m_Type: 1
m_DefaultFloat: 1
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 0}
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: 1520295354504132550}
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!1107 &1520295354504132550
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: -237968760341279601}
m_Position: {x: 381.44016, y: 123.90466, 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: -237968760341279601}

View File

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

View File

@@ -5,7 +5,7 @@ TextureImporter:
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
mipMapMode: 1
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0

View File

@@ -5,7 +5,7 @@ TextureImporter:
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
mipMapMode: 1
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0

View File

@@ -5,7 +5,7 @@ TextureImporter:
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
mipMapMode: 1
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0

View File

@@ -5,7 +5,7 @@ TextureImporter:
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
mipMapMode: 1
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0

View File

@@ -5,7 +5,7 @@ TextureImporter:
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
mipMapMode: 1
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0

File diff suppressed because it is too large Load Diff

View File

@@ -44,14 +44,14 @@
public void Spawn()
{
Debug.Log($"{gameObject} Spawned");
// Debug.Log($"{gameObject} Spawned");
SetActive(true);
activeCountdown = Random.Range(9, 10);
}
public void Despawn()
{
Debug.Log($"{gameObject} Despawned");
// Debug.Log($"{gameObject} Despawned");
SetActive(false);
}

View File

@@ -1,120 +1,120 @@
namespace Marro.PacManUdon
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.Animations;
using UnityEditor;
public class AnimationRecorder : MonoBehaviour
{
[SerializeField] AnimationClip clip;
[SerializeField] GameObject root;
[SerializeField] GameObject[] gameObjectsToAnimate;
private GameObjectRecorder recorder;
void Start()
{
recorder = new GameObjectRecorder(root);
foreach (GameObject gameObject in gameObjectsToAnimate)
{
// if(gameObject.GetComponent<PacMan>() || gameObject.GetComponent<Ghost>())
//namespace Marro.PacManUdon
//{
// recorder.BindComponentsOfType<Transform>(gameObject, true);
// using System.Collections;
// using System.Collections.Generic;
// using UnityEngine;
// using UnityEditor.Animations;
// using UnityEditor;
// public class AnimationRecorder : MonoBehaviour
// {
// [SerializeField] AnimationClip clip;
// [SerializeField] GameObject root;
// [SerializeField] GameObject[] gameObjectsToAnimate;
// private GameObjectRecorder recorder;
// void Start()
// {
// recorder = new GameObjectRecorder(root);
// foreach (GameObject gameObject in gameObjectsToAnimate)
// {
// // if(gameObject.GetComponent<PacMan>() || gameObject.GetComponent<Ghost>())
// // {
// // recorder.BindComponentsOfType<Transform>(gameObject, true);
// // }
// // recorder.BindComponentsOfType<Renderer>(gameObject, true);
// string path = AnimationUtility.CalculateTransformPath(gameObject.transform, root.transform);
// recorder.Bind(EditorCurveBinding.FloatCurve(path, typeof(GameObject), "m_IsActive"));
// Pellet pellet = gameObject.GetComponent<Pellet>();
// if (pellet)
// {
// recorder.Bind(EditorCurveBinding.FloatCurve(path, typeof(SpriteRenderer), "m_Enabled"));
// if (pellet.isPowerPellet)
// {
// recorder.Bind(EditorCurveBinding.PPtrCurve(path, typeof(SpriteRenderer), "m_Sprite"));
// }
// continue;
// }
// recorder.BindComponentsOfType<Renderer>(gameObject, true);
string path = AnimationUtility.CalculateTransformPath(gameObject.transform, root.transform);
// if (gameObject.GetComponent<SpriteRenderer>())
// {
// recorder.Bind(EditorCurveBinding.FloatCurve(path, typeof(SpriteRenderer), "m_Enabled"));
// recorder.Bind(EditorCurveBinding.PPtrCurve(path, typeof(SpriteRenderer), "m_Sprite"));
// }
// else if (gameObject.GetComponent<MeshRenderer>())
// {
// recorder.Bind(EditorCurveBinding.DiscreteCurve(path, typeof(MeshRenderer), "m_Enabled"));
// }
// recorder.Bind(EditorCurveBinding.FloatCurve(path, typeof(Transform), "m_LocalPosition.x"));
// recorder.Bind(EditorCurveBinding.FloatCurve(path, typeof(Transform), "m_LocalPosition.y"));
// recorder.Bind(EditorCurveBinding.FloatCurve(path, typeof(Transform), "m_LocalPosition.z"));
// }
recorder.Bind(EditorCurveBinding.FloatCurve(path, typeof(GameObject), "m_IsActive"));
// EditorCurveBinding[] bindings = recorder.GetBindings();
// foreach (EditorCurveBinding binding in bindings)
// {
// Debug.Log($"{binding.path}, {binding.propertyName}, {binding.type}");
// }
// }
Pellet pellet = gameObject.GetComponent<Pellet>();
if (pellet)
{
recorder.Bind(EditorCurveBinding.FloatCurve(path, typeof(SpriteRenderer), "m_Enabled"));
if (pellet.isPowerPellet)
{
recorder.Bind(EditorCurveBinding.PPtrCurve(path, typeof(SpriteRenderer), "m_Sprite"));
}
continue;
}
// private static string GetGameObjectPathToObject(GameObject obj, Transform target)
// {
// string path = "/" + obj.name;
// while (!obj.transform.parent.Equals(target))
// {
// obj = obj.transform.parent.gameObject;
// path = "/" + obj.name + path;
// }
// Debug.Log($"GetGameObjectPathToTransform from {obj} to {target.gameObject} gives {path}");
// return path;
// }
if (gameObject.GetComponent<SpriteRenderer>())
{
recorder.Bind(EditorCurveBinding.FloatCurve(path, typeof(SpriteRenderer), "m_Enabled"));
recorder.Bind(EditorCurveBinding.PPtrCurve(path, typeof(SpriteRenderer), "m_Sprite"));
}
else if (gameObject.GetComponent<MeshRenderer>())
{
recorder.Bind(EditorCurveBinding.DiscreteCurve(path, typeof(MeshRenderer), "m_Enabled"));
}
recorder.Bind(EditorCurveBinding.FloatCurve(path, typeof(Transform), "m_LocalPosition.x"));
recorder.Bind(EditorCurveBinding.FloatCurve(path, typeof(Transform), "m_LocalPosition.y"));
recorder.Bind(EditorCurveBinding.FloatCurve(path, typeof(Transform), "m_LocalPosition.z"));
}
// void LateUpdate()
// {
// if (clip == null)
// return;
EditorCurveBinding[] bindings = recorder.GetBindings();
foreach (EditorCurveBinding binding in bindings)
{
Debug.Log($"{binding.path}, {binding.propertyName}, {binding.type}");
}
}
// recorder.TakeSnapshot(Time.deltaTime);
// }
private static string GetGameObjectPathToObject(GameObject obj, Transform target)
{
string path = "/" + obj.name;
while (!obj.transform.parent.Equals(target))
{
obj = obj.transform.parent.gameObject;
path = "/" + obj.name + path;
}
Debug.Log($"GetGameObjectPathToTransform from {obj} to {target.gameObject} gives {path}");
return path;
}
// void OnDisable()
// {
// if (clip == null)
// return;
void LateUpdate()
{
if (clip == null)
return;
// if (recorder.isRecording)
// {
// recorder.SaveToClip(clip);
// RemoveUnneededCurves(clip);
// }
// }
recorder.TakeSnapshot(Time.deltaTime);
}
// private static void RemoveUnneededCurves(AnimationClip clip)
// {
// // Collect curves to process
// EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(clip);
// List<EditorCurveBinding> unneededCurves = new List<EditorCurveBinding>();
void OnDisable()
{
if (clip == null)
return;
// foreach (var binding in bindings)
// {
// AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, binding);
if (recorder.isRecording)
{
recorder.SaveToClip(clip);
RemoveUnneededCurves(clip);
}
}
// if (curve == null || curve.keys.Length <= 2)
// {
// unneededCurves.Add(binding);
// }
// }
private static void RemoveUnneededCurves(AnimationClip clip)
{
// Collect curves to process
EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(clip);
List<EditorCurveBinding> unneededCurves = new List<EditorCurveBinding>();
foreach (var binding in bindings)
{
AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, binding);
if (curve == null || curve.keys.Length <= 2)
{
unneededCurves.Add(binding);
}
}
// Remove unchanged curves
foreach (var binding in unneededCurves)
{
AnimationUtility.SetEditorCurve(clip, binding, null);
Debug.Log($"Removed unchanged curve for property: {binding.propertyName}");
}
}
}
}
// // Remove unchanged curves
// foreach (var binding in unneededCurves)
// {
// AnimationUtility.SetEditorCurve(clip, binding, null);
// Debug.Log($"Removed unchanged curve for property: {binding.propertyName}");
// }
// }
// }
//}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,504 @@
#define RECORDING_DEMO
namespace Marro.PacManUdon
{
using System;
using UdonSharp;
using UnityEngine;
using VRC.SDK3.Components;
using VRC.SDKBase;
public partial class GameManager : SyncedObject
{
[Header("Static game components")]
[SerializeField] private Maze[] mazes;
[SerializeField] private PacMan pacMan;
[SerializeField] private GhostManager ghostManager;
[SerializeField] private BonusFruit bonusFruit;
[SerializeField] private PelletManager pelletManager;
[SerializeField] public StatusDisplay statusDisplay; // This one is public so other scripts can write to the debug display
[SerializeField] private PelletManager attractScreen;
[SerializeField] private GameObject intermissionScreen;
[SerializeField] private GameObject pressStartButtonScreen;
[SerializeField] private PlayerInput playerInput;
[SerializeField] private Animator demo;
[SerializeField] private SoundManager soundManager;
[SerializeField] private NetworkManager networkManager;
[SerializeField] private GameObject recorder;
[Header("Game settings")]
[SerializeField] private int startingExtraLives = 3;
[SerializeField] private int scoreToExtraLife = 10000;
[Tooltip("Override amount of pellets needed to clear stage, set to -1 to disable.")]
[SerializeField] private int pelletCountOverride = -1;
private Maze maze;
private VRCObjectPool pelletPool;
private Intermission2Pole intermission2Pole;
private Animator mazeSpriteAnimator;
private int pelletCountTotal;
private int pelletCountRemaining;
private GameObject[] attractScreenElements;
private GameObject[] intermissionScreenElements;
private PacManGameState gameState;
[UdonSynced, FieldChangeCallback(nameof(Score))] private int score;
[UdonSynced, FieldChangeCallback(nameof(Level))] private int level;
[UdonSynced, FieldChangeCallback(nameof(HighScore))] private int highScore;
[UdonSynced, FieldChangeCallback(nameof(ExtraLives))] private int extraLives;
public void Start()
{
attractScreenElements = new GameObject[attractScreen.transform.childCount];
for (int i = 0; i < attractScreenElements.Length; i++)
{
attractScreenElements[i] = attractScreen.transform.GetChild(i).gameObject;
}
intermissionScreenElements = new GameObject[intermissionScreen.transform.childCount];
for (int i = 0; i < intermissionScreenElements.Length; i++)
{
intermissionScreenElements[i] = intermissionScreen.transform.GetChild(i).gameObject;
}
maze = mazes[0];
pelletPool = maze.pelletContainer.GetComponent<VRCObjectPool>();
mazeSpriteAnimator = maze.mazeSprite.GetComponent<Animator>();
intermission2Pole = intermissionScreenElements[4].GetComponent<Intermission2Pole>();
ghostManager.Initialize(maze.ghostTargets, pacMan, this);
pacMan.Initialize(playerInput, pelletPool, this);
bonusFruit.Initialize();
pelletManager.Initialize(pelletPool);
statusDisplay.Initialize();
playerInput.Initialize(this);
soundManager.Initialize();
intermission2Pole.Initialize(this, ghostManager.Ghosts[0]);
networkManager.Initialize();
HideEverything();
SetScore(0);
SetHighScore(0);
SetLevel(0);
StartAttractMode();
}
public override void FixedUpdate()
{
TimeSequenceUpdate(Time.deltaTime);
}
public void JoystickGrabbed()
{
if (gameState == PacManGameState.AttractMode || gameState == PacManGameState.AttractModeDemo)
StartTimeSequence(PacManTimeSequence.WaitForStart);
}
public void JoystickReleased()
{
if (gameState == PacManGameState.WaitForStart)
StartTimeSequence(PacManTimeSequence.WaitForStartTimeout);
}
public void ResetButtonPressed()
{
Debug.Log($"{gameObject} Reset button was pressed!");
Start();
}
public void StartGameButtonPressed()
{
Debug.Log($"{gameObject} Start Game Button was pressed!");
TakeOwnership();
StartTimeSequence(PacManTimeSequence.StartNewGame);
}
private void StartAttractMode()
{
// #if RECORDING_DEMO
// recorder.gameObject.SetActive(true);
StartTimeSequence(PacManTimeSequence.AttractScreenIntroduction);
// #else
// SetGameState(PacManGameState.AttractMode);
// HideEverything();
// demo.gameObject.SetActive(true);
// #endif
}
private void InitializeNewGame()
{
Debug.Log($"{gameObject} Started new game!");
SetScore(0);
SetExtraLives(startingExtraLives);
SetLevel(1);
}
private void InitializeLevel()
{
Debug.Log($"{gameObject} New level started!");
pelletCountTotal = pelletPool.Pool.Length;
pelletCountRemaining = pelletCountTotal;
ghostManager.SetPelletsRemaining(pelletCountRemaining);
ghostManager.NewLevel();
pelletManager.RestoreAllPellets();
if (pelletCountOverride > 0)
{
pelletCountRemaining = pelletCountOverride;
}
mazeSpriteAnimator.SetBool("Blinking", false);
}
private void RestartLevel()
{
Debug.Log($"{gameObject} (Re)started level!");
// SetInGameComponentVisibility(true);
ghostManager.Reset();
pacMan.Reset();
bonusFruit.Despawn();
soundManager.Reset();
pelletManager.SetPowerPelletsBlink(false);
}
private void PrepareForCutscene()
{
HideEverything();
RestartLevel();
SetFrozen(true);
}
public void GotPellet(bool addScore = true)
{
pelletCountRemaining--;
if (addScore) AddScore(10);
ghostManager.PelletConsumed();
soundManager.PlayPelletSound();
soundManager.UpdatePelletCount(pelletCountRemaining);
int pelletsConsumed = pelletCountTotal - pelletCountRemaining;
if (pelletCountRemaining <= 0)
{
StartTimeSequence(PacManTimeSequence.BoardClear);
}
else if (pelletsConsumed == 70 || pelletsConsumed == 170)
{
bonusFruit.Spawn();
}
}
public void GotPowerPellet()
{
if (gameState == PacManGameState.AttractMode)
{
TimeSequenceSkipToNextStep();
return;
}
GotPellet(addScore: false);
AddScore(50);
ghostManager.SetPowerPellet(true);
pacMan.SetPowerPellet(true);
soundManager.SetGhostBlue(true);
}
public void EndPowerPellet()
{
ghostManager.SetPowerPellet(false);
pacMan.SetPowerPellet(false);
soundManager.SetGhostBlue(false);
}
public void GotFruit()
{
AddScore(bonusFruit.Collected());
soundManager.PlayFruitSound();
}
public void GhostCaught(int scoreBonus)
{
if (gameState == PacManGameState.AttractMode)
{
TimeSequenceSkipToNextStep();
return;
}
AddScore(scoreBonus);
StartTimeSequence(PacManTimeSequence.GhostCaught);
pacMan.HideUntilUnfrozen();
}
public void PacManCaught()
{
StartTimeSequence(PacManTimeSequence.PacManCaught);
}
public void NoGhostsScared()
{
soundManager.SetGhostBlue(false);
}
public void NoGhostsRetreating()
{
soundManager.SetGhostRetreat(false);
}
public void Intermission2PoleUpdate()
{
TimeSequenceSkipToNextStep();
}
void BoardClearAnimation()
{
ghostManager.gameObject.SetActive(false);
mazeSpriteAnimator.SetBool("Blinking", true);
}
private void HideEverything()
{
SetPelletsActive(false);
SetMazeVisible(false);
SetGhostsActive(false);
SetPacManActive(false);
SetPressStartButtonScreenVisible(false);
SetIntermissionScreenVisible(false);
statusDisplay.SetGameOverTextVisible(false);
statusDisplay.SetExtraLivesDisplayVisible(false);
statusDisplay.SetLevelDisplayVisible(false);
statusDisplay.SetPlayer1TextVisible(false);
statusDisplay.SetReadyTextVisible(false);
demo.gameObject.SetActive(false);
}
void SetPelletsActive(bool active)
{
pelletPool.gameObject.SetActive(active);
}
void SetMazeVisible(bool visible)
{
mazeSpriteAnimator.SetBool("Hidden", !visible);
}
void SetGhostsActive(bool active)
{
ghostManager.SetActive(active);
}
void SetPacManActive(bool active)
{
pacMan.SetActive(active);
}
void SetPressStartButtonScreenVisible(bool visible)
{
pressStartButtonScreen.SetActive(visible);
}
void SetIntermissionScreenVisible(bool visible)
{
intermissionScreen.SetActive(visible);
}
void SetGameState(PacManGameState newGameState)
{
// Debug.Log($"{gameObject} State transitioning from {gameState} to {newGameState}");
gameState = newGameState;
if (Networking.IsOwner(gameObject))
{
RequestSerialization();
}
}
private void IncrementLevel()
{
SetLevel(level + 1);
}
private void SetLevel(int level)
{
this.level = level;
pacMan.SetLevel(level);
ghostManager.SetLevel(level);
statusDisplay.SetLevel(level);
bonusFruit.SetFruitType(PacManConstants.GetFruitTypeForLevel(level));
}
void AddScore(int score)
{
if (gameState == PacManGameState.AttractMode || gameState == PacManGameState.AttractModeDemo)
{
return;
}
if (this.score < scoreToExtraLife && this.score + score >= scoreToExtraLife)
{
BonusLifeReached();
}
SetScore(this.score + score);
RequestSerialization();
}
void SetScore(int score)
{
this.score = score;
statusDisplay.Set1UPScore(score);
if (score > highScore)
{
highScore = score;
statusDisplay.SetHighScore(score);
}
}
void SetHighScore(int highScore)
{
this.highScore = highScore;
statusDisplay.SetHighScore(score);
}
public void DecrementLives()
{
if (!Networking.IsOwner(gameObject))
{
return;
}
// Debug.Log($"{gameObject} Decremented lives from {extraLives} to {extraLives - 1}");
SetExtraLives(extraLives - 1);
}
void IncrementLives()
{
if (!Networking.IsOwner(gameObject))
{
return;
}
// Debug.Log($"{gameObject} Incremented lives from {extraLives} to {extraLives + 1}");
SetExtraLives(extraLives + 1);
}
void SetExtraLives(int extraLives)
{
// Debug.Log($"{gameObject} Set lives from {this.extraLives} to {extraLives}");
this.extraLives = extraLives;
statusDisplay.SetExtraLives(extraLives);
}
void BonusLifeReached()
{
IncrementLives();
soundManager.PlayExtraLifeSound();
}
public void SetFrozen(bool frozen, bool ghostIgnoreIfCaught = false, bool ghostKeepAnimating = false)
{
// Debug.Log($"{gameObject} Set Frozen: {frozen}");
pacMan.SetFrozen(frozen);
bonusFruit.SetFrozen(frozen);
ghostManager.SetFrozen(frozen, ignoreIfCaught: ghostIgnoreIfCaught);
if (!frozen)
{
pelletManager.SetPowerPelletsBlink(true);
}
}
void TakeOwnership()
{
Networking.SetOwner(Networking.LocalPlayer, gameObject);
Networking.SetOwner(Networking.LocalPlayer, pacMan.gameObject);
Networking.SetOwner(Networking.LocalPlayer, pelletPool.gameObject);
ghostManager.SetOwner(Networking.LocalPlayer);
}
public override void AppendSyncedData(byte[][] data, ref int offset, NetworkEventType eventType)
{
data[offset++] = new byte[] { Int32ToByte((int)gameState) };
data[offset++] = BitConverter.GetBytes(currentlyInTimeSequence);
data[offset++] = new byte[] { Int32ToByte((int)currentTimeSequence) };
data[offset++] = BitConverter.GetBytes(timeSequenceProgress);
}
public override bool SetSyncedData(byte[] data, ref int offset, NetworkEventType eventType)
{
SetGameState((PacManGameState)data[offset++]);
var currentlyInTimeSequence = BitConverter.ToBoolean(data, offset++);
var currentTimeSequence = (PacManTimeSequence)data[offset++];
var timeSequenceProgress = BitConverter.ToSingle(data, offset);
offset += 4;
TimeSequenceSyncWithRemote(currentlyInTimeSequence, currentTimeSequence, timeSequenceProgress);
return true;
}
public int ExtraLives
{
set
{
SetExtraLives(value);
}
get => extraLives;
}
public PacManGameState GameState
{
set
{
SetGameState(value);
}
get => gameState;
}
public bool GhostsScared
{
set
{
}
get => GhostsScared;
}
public int Score
{
set
{
SetScore(value);
}
get => score;
}
public int HighScore
{
set
{
SetHighScore(value);
}
get => score;
}
public int Level
{
set
{
SetLevel(value);
}
get => level;
}
public static byte Int32ToByte(int value) =>
(byte)value;
//byte.Parse(value.ToString()); // This is the only way I could find to cast an int to byte in Udon, a regular cast crashes in runtime...
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 6e99011c9b7c5824fa22a5dc4b5bb735
guid: 501bd6c4adad10344a5e5dc0598e0b24
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,69 +0,0 @@
// // Silly me for wanting to make the code neat, forgot this was Udon :)
// using System.Collections;
// using System.Collections.Generic;
// using UdonSharp;
// using UnityEngine;
// public class GameStartSequence : TimeSequence
// {
// GameStateManager gameStateManager;
// StatusDisplay statusDisplay;
// public GameStartSequence(GameStateManager gameStateManager, StatusDisplay statusDisplay) : base(DeltaToAbsolute(new float[]
// {0, 0.016f, 2.2f, 0.032f, 0.032f, 1.92f, 0.032f}
// ))
// {
// this.gameStateManager = gameStateManager;
// this.statusDisplay = statusDisplay;
// }
// protected override void SequenceStep(int sequneceProgress)
// {
// switch (SequenceProgress)
// {
// case 0:
// // Prepare new game, hide everything except score bar
// gameStateManager.SetFrozen(true);
// gameStateManager.StartNewGame();
// gameStateManager.SetPelletsVisible(false);
// gameStateManager.SetMazeVisible(false);
// gameStateManager.SetGhostsVisible(false);
// gameStateManager.SetPacManVisible(false);
// statusDisplay.SetExtraLivesDisplayVisible(false);
// statusDisplay.SetLevelDisplayVisible(false);
// break;
// case 1:
// // Show maze, lives indicator, level indicator, player 1 and ready text
// gameStateManager.SetPelletsVisible(true);
// gameStateManager.SetMazeVisible(true);
// statusDisplay.SetExtraLivesDisplayVisible(true);
// statusDisplay.SetLevelDisplayVisible(true);
// statusDisplay.SetPlayer1TextVisible(true);
// statusDisplay.SetReadyTextVisible(true);
// break;
// case 2:
// // Subtract a life
// gameStateManager.DecrementLives();
// break;
// case 3:
// // Remove Player 1 text
// statusDisplay.SetPlayer1TextVisible(false);
// break;
// case 4:
// // Show ghosts and pacman
// gameStateManager.SetGhostsVisible(true);
// gameStateManager.SetPacManVisible(true);
// break;
// case 5:
// // Remove ready text
// statusDisplay.SetReadyTextVisible(true);
// break;
// case 6:
// // Start game, end sequence
// gameStateManager.SetFrozen(false);
// break;
// }
// }
// }

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,8 @@ namespace Marro.PacManUdon
Blinky,
Pinky,
Inky,
Clyde
Clyde,
Special,
}
public enum PacManGhostState
@@ -65,26 +66,26 @@ namespace Marro.PacManUdon
private int housePelletCounterLimit;
private bool faceInStartingDirectionUntilUnfrozen;
private bool specialLook;
private bool followingPredefinedPath;
private Vector2[] predefinedPath;
private int predefinedPathIndex;
[UdonSynced] int rngState;
[UdonSynced] private Vector2 syncedPosition;
[UdonSynced] private float speed;
[UdonSynced] private Vector2 direction;
[UdonSynced] private Vector2 target;
[UdonSynced] private bool offGrid;
[UdonSynced] private bool inTunnel;
[UdonSynced] private PacManGhostState ghostState;
[UdonSynced] private bool isScared;
[UdonSynced] private bool scattering;
[UdonSynced] private PacManGhostFrozenState frozenState;
[UdonSynced] private bool hideUntilUnfrozen;
[UdonSynced] private int housePelletCounter;
[UdonSynced] private bool housePelletCounterActive;
[UdonSynced] private bool turnAroundSoon;
int rngState;
private Vector2 syncedPosition;
private float speed;
private Vector2 target;
private bool offGrid;
private bool inTunnel;
private PacManGhostState ghostState;
private bool isScared;
private bool scattering;
private PacManGhostFrozenState frozenState;
private bool hideUntilUnfrozen;
private int housePelletCounter;
private bool housePelletCounterActive;
private bool turnAroundSoon;
public void Initialize(PacMan pacMan, Ghost blinky, Vector2 homePosition, Vector2 idlePosition1, Vector2 idlePosition2, Vector2 cornerPosition)
{
@@ -137,18 +138,19 @@ namespace Marro.PacManUdon
kinematic = false;
followingPredefinedPath = false;
turnAroundSoon = false;
// scattering = true;
specialLook = false;
rngState = 1;
UpdateSpeed();
faceInStartingDirectionUntilUnfrozen = true;
UpdateAnimator();
// animator.Play(0, -1, 0);
RequestSerialization();
// Debug.Log($"{gameObject} reset with state: {state}, target: {target}, offGrid: {offGrid}");
}
void FixedUpdate()
public override void FixedUpdate()
{
if (ghostType == PacManGhostType.Blinky)
{
@@ -362,6 +364,7 @@ namespace Marro.PacManUdon
case PacManGhostState.Entering:
offGrid = true;
SetState(PacManGhostState.Home);
ghostManager.GhostReturned();
if (!target.Equals(idlePosition1))
{ // This is idlePosition1 if PacManGhostStartState == TargetingIdlePosition1
SetOffGridTarget(idlePosition2, false);
@@ -474,13 +477,17 @@ namespace Marro.PacManUdon
}
}
private void UpdateAnimator()
protected override void UpdateAnimator()
{
if (!gameObject.activeInHierarchy)
return;
// Debug.Log($"{gameObject} UpdateAnimator with state: {ghostState}, isScared: {isScared}, direction: {direction}");
if (isScared)
if (specialLook)
{
animator.SetFloat("GhostType", GhostTypeToAnimationValue(PacManGhostType.Special));
}
else if (isScared)
{
float currentGhostType = animator.GetFloat("GhostType");
if (currentGhostType > 0.5f && currentGhostType < 2.5f)
@@ -517,7 +524,7 @@ namespace Marro.PacManUdon
animator.SetFloat("DirX", 0);
animator.SetFloat("DirY", -1);
}
else if (!direction.Equals(Vector2.zero))
else if (specialLook || !direction.Equals(Vector2.zero))
{
animator.SetFloat("DirX", direction.x);
animator.SetFloat("DirY", direction.y);
@@ -529,6 +536,8 @@ namespace Marro.PacManUdon
switch (ghostType)
{
default:
Debug.LogError("Invalid ghost animation value!");
return 0;
case PacManGhostType.Caught:
return 0;
case PacManGhostType.Scared:
@@ -543,12 +552,15 @@ namespace Marro.PacManUdon
return 5;
case PacManGhostType.Clyde:
return 6;
case PacManGhostType.Special:
return 7;
}
}
void UpdateSpeed()
public void UpdateSpeed()
{
speed = ghostManager.GetTargetSpeed(this, ghostState, isScared, inTunnel);
// Debug.Log($"Ghost with type {ghostType} updated speed to {speed}, ghostState: {ghostState}, isScared: {isScared}, inTunnel: {inTunnel}, elroyLevel: {ghostManager.elroyLevel}");
}
public void ResetHousePelletCounter()
@@ -626,13 +638,9 @@ namespace Marro.PacManUdon
ghostState = state;
UpdateAnimator();
UpdateSpeed();
if (Networking.IsOwner(gameObject))
{
RequestSerialization();
}
}
public void SetScared(bool scared)
private void SetScared(bool scared)
{
isScared = scared;
UpdateAnimator();
@@ -642,11 +650,6 @@ namespace Marro.PacManUdon
{
SetWhite(false);
}
if (Networking.IsOwner(gameObject))
{
RequestSerialization();
}
}
public void SetScattering(bool scattering, bool reverseDirection = true)
@@ -654,9 +657,8 @@ namespace Marro.PacManUdon
if (reverseDirection && this.scattering != scattering)
{
if (ghostState == PacManGhostState.Normal || ghostState == PacManGhostState.Home || ghostState == PacManGhostState.Exiting
#if RECORDING_DEMO
|| ghostState == PacManGhostState.Entering // This is afaik not normal PacMan behaviour, but is needed to accomidate slight timing differences
#endif
// This is afaik not normal PacMan behaviour, but is needed to accomidate slight timing differences
|| ghostState == PacManGhostState.Entering && ghostManager.gameController.GameState == PacManGameState.AttractModeDemo
)
{
turnAroundSoon = true;
@@ -683,16 +685,12 @@ namespace Marro.PacManUdon
}
animator.speed = frozen && !keepAnimating ? 0 : 1; // This would cause issues if the returning sprite was animated, luckily it isn't :)
if (frozen == false)
{
if (faceInStartingDirectionUntilUnfrozen)
if (frozen == false && faceInStartingDirectionUntilUnfrozen)
{
faceInStartingDirectionUntilUnfrozen = false;
UpdateAnimator();
}
}
}
public void SetHousePelletCounterActive(bool active)
{
@@ -751,12 +749,18 @@ namespace Marro.PacManUdon
predefinedPathIndex = 0;
}
void SetInTunnel(bool inTunnel)
public void SetInTunnel(bool inTunnel)
{
this.inTunnel = inTunnel;
UpdateSpeed();
}
public void SetSpecialLook(bool enabled)
{
specialLook = enabled;
UpdateAnimator();
}
void SetVisibility(bool visible)
{
renderer.enabled = visible;
@@ -767,36 +771,11 @@ namespace Marro.PacManUdon
return ghostState;
}
public override Vector2 GetPosition()
{
return (Vector2)transform.localPosition;
}
public bool IsScared => isScared;
public override void SetPosition(Vector2 position)
public void SetSpeed(float speed)
{
GridMoverTools.SetPosition(position, transform);
}
public override Vector2 GetDirection()
{
return direction;
}
public void SetDirection(Vector2 direction)
{
this.direction = direction;
UpdateAnimator();
RequestSerialization();
}
public override void OnPreSerialization()
{
syncedPosition = GetPosition();
}
public override void OnDeserialization()
{
SetPosition(syncedPosition);
this.speed = speed;
UpdateAnimator();
}

View File

@@ -43,7 +43,7 @@ MonoBehaviour:
Data:
- Name:
Entry: 12
Data: 32
Data: 33
- Name:
Entry: 7
Data:
@@ -61,7 +61,7 @@ MonoBehaviour:
Data: 3|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: Marro.PacManUdon.GameController, Assembly-CSharp
Data: Marro.PacManUdon.GameManager, Assembly-CSharp
- Name:
Entry: 8
Data:
@@ -1291,7 +1291,7 @@ MonoBehaviour:
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
Data: true
- Name: _fieldAttributes
Entry: 7
Data: 62|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
@@ -1652,6 +1652,54 @@ MonoBehaviour:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: kinematic
- Name: $v
Entry: 7
Data: 78|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: kinematic
- Name: <UserType>k__BackingField
Entry: 9
Data: 35
- Name: <SystemType>k__BackingField
Entry: 9
Data: 35
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 79|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 13
Data:

View File

@@ -9,7 +9,7 @@
public class GhostManager : UdonSharpBehaviour
{
[NonSerialized] public GameController gameController;
[NonSerialized] public GameManager gameController;
private Ghost[] ghosts;
private Ghost blinky;
@@ -44,7 +44,7 @@
private int scatterPatternIndex;
// Elroy logic
private int elroyLevel;
public int elroyLevel;
private int pelletsRemaining;
// Ghost house logic
@@ -55,9 +55,10 @@
private float pelletTimeoutLimit;
private bool frozen;
private bool kinematic;
// This should be called once when the game is initialized
public void Initialize(GameObject[] ghostTargets, PacMan pacMan, GameController gameController)
public void Initialize(GameObject[] ghostTargets, PacMan pacMan, GameManager gameController)
{
this.gameController = gameController;
ghosts = transform.GetComponentsInChildren<Ghost>(true);
@@ -80,9 +81,10 @@
powerPelletActive = false;
scatterCounter = 0;
scatterPatternIndex = 0;
SetScattering(false, reverseDirection: false);
sharedPelletCounter = 0;
pelletTimeout = 0;
elroyLevel = 0;
kinematic = false;
foreach (Ghost ghost in ghosts)
{
@@ -90,6 +92,7 @@
}
SetScattering(true, reverseDirection: false);
RequestSerialization();
}
public void NewLevel()
@@ -109,7 +112,7 @@
public void FixedUpdate()
{
// gameStateManager.statusDisplay.SetDebugText(1, this.blinkCountdown.ToString());
if (frozen)
if (frozen || kinematic)
{
return;
}
@@ -139,7 +142,6 @@
void UpdatePowerPellet()
{
powerPelletCountdown -= Time.deltaTime;
if (powerPelletCountdown <= 0)
{
@@ -188,14 +190,14 @@
gameController.GhostCaught(0);
return;
}
Debug.Log($"{gameObject} GhostCaughtQueue with ghost {ghost}");
// Debug.Log($"{gameObject} GhostCaughtQueue with ghost {ghost}");
ghostScaredQueue.Add(ghost);
GhostCaughtExecute(ghost);
}
public void GhostCaughtContinue()
{
Debug.Log($"{gameObject} GhostCaughtContinue with ghost queue length {ghostScaredQueue.Count}");
// Debug.Log($"{gameObject} GhostCaughtContinue with ghost queue length {ghostScaredQueue.Count}");
if (!ghostScaredQueue.TryGetValue(0, out DataToken currentGhost))
{
Debug.LogError("Called GhostCaughtContinue without a ghost in the queue!");
@@ -224,6 +226,37 @@
gameController.PacManCaught();
}
public void GhostReturned()
{
bool noGhostsScared = true;
bool noGhostsRetreating = true;
foreach (var ghost in ghosts)
{
var state = ghost.GetGhostState();
if (ghost.IsScared)
{
noGhostsScared = false;
}
if (state == PacManGhostState.CaughtScore || state == PacManGhostState.Returning || state == PacManGhostState.Entering)
{
noGhostsRetreating = false;
}
}
if (noGhostsScared)
{
gameController.NoGhostsScared();
}
if (noGhostsRetreating)
{
gameController.NoGhostsRetreating();
}
}
void SetGhostBlinking(bool blinking)
{
blinkingActivated = blinking;
@@ -278,6 +311,7 @@
public void SetLevel(int level)
{
Debug.Log($"GhostManager: SetLevel {level}");
speedDefault = PacManConstants.GetGhostDefaultSpeedForLevel(level);
speedScared = PacManConstants.GetGhostScaredSpeedForLevel(level);
speedReturn = 15f;
@@ -292,9 +326,10 @@
pelletTimeoutLimit = PacManConstants.GetGhostHousePelletTimeoutLimitForLevel(level);
int[] privatePelletCounterReleaseValues = PacManConstants.GetGhostHousePrivatePelletCounterLimitForLevel(level);
for (int i = 0; i < Math.Min(sharedPelletCounterReleaseValues.Length, ghosts.Length); i++)
for (int i = 0; i < ghosts.Length; i++)
{
ghosts[i].SetHousePelletCounterLimit(privatePelletCounterReleaseValues[i]);
Reset(); // Reset needed to properly apply level
}
}
@@ -439,6 +474,7 @@
public void SetKinematic(bool kinematic)
{
this.kinematic = kinematic;
foreach (Ghost ghost in ghosts)
{
ghost.SetKinematic(kinematic);

View File

@@ -3,24 +3,53 @@ namespace Marro.PacManUdon
using System;
using UdonSharp;
using UnityEngine;
using VRC.Udon.Serialization.OdinSerializer;
public abstract class GridMover : UdonSharpBehaviour
public abstract class GridMover : SyncedObject
{
protected Vector2 direction;
public virtual Vector2 GetPosition()
{
Debug.LogWarning($"{gameObject} does not implement GetPosition");
return Vector2.zero;
return (Vector2)transform.localPosition;
}
public virtual void SetPosition(Vector2 position)
{
Debug.LogWarning($"{gameObject} does not implement SetPosition");
transform.localPosition = new Vector3(position.x, position.y, transform.localPosition.z);
}
public virtual Vector2 GetDirection()
{
Debug.LogWarning($"{gameObject} does not implement GetDirection");
return Vector2.zero;
return direction;
}
public void SetDirection(Vector2 direction)
{
this.direction = direction;
UpdateAnimator();
}
protected abstract void UpdateAnimator();
public override void AppendSyncedData(byte[][] data, ref int offset, NetworkEventType eventType)
{
var position = GetPosition();
data[offset++] = BitConverter.GetBytes(position.x);
data[offset++] = BitConverter.GetBytes(position.y);
var direction = GetDirection();
data[offset++] = BitConverter.GetBytes(direction.x);
data[offset++] = BitConverter.GetBytes(direction.y);
}
public override bool SetSyncedData(byte[] data, ref int offset, NetworkEventType eventType)
{
SetPosition(new Vector2(BitConverter.ToSingle(data, offset), BitConverter.ToSingle(data, offset + 2)));
SetDirection(new Vector2(BitConverter.ToSingle(data, offset + 4), BitConverter.ToSingle(data, offset + 6)));
offset += 8;
return true;
}
}
}

View File

@@ -10,12 +10,6 @@ namespace Marro.PacManUdon
return currentPosition + direction * speed * Time.deltaTime;
}
public static void SetPosition(Vector2 position, Transform transform)
{
transform.localPosition = new Vector3(position.x, position.y, transform.localPosition.z);
}
public static Vector2 PositionToGrid(Vector2 position)
{
return new Vector2((float)Math.Round(position.x), (float)Math.Round(position.y));

View File

@@ -0,0 +1,280 @@
%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: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3}
m_Name: Intermission2Pole
m_EditorClassIdentifier:
serializedUdonProgramAsset: {fileID: 11400000, guid: 33352f027da089a48a08445f114d9370, type: 2}
udonAssembly:
assemblyError:
sourceCsScript: {fileID: 11500000, guid: 5561162f0532eab4ea6c388cb2d33504, type: 3}
scriptVersion: 2
compiledVersion: 2
behaviourSyncMode: 0
hasInteractEvent: 0
scriptID: 288864006765975011
serializationData:
SerializedFormat: 2
SerializedBytes:
ReferencedUnityObjects: []
SerializedBytesString:
Prefab: {fileID: 0}
PrefabModificationsReferencedUnityObjects: []
PrefabModifications: []
SerializationNodes:
- Name: fieldDefinitions
Entry: 7
Data: 0|System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[UdonSharp.Compiler.FieldDefinition,
UdonSharp.Editor]], mscorlib
- Name: comparer
Entry: 7
Data: 1|System.Collections.Generic.GenericEqualityComparer`1[[System.String,
mscorlib]], mscorlib
- Name:
Entry: 8
Data:
- Name:
Entry: 12
Data: 4
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: _animator
- Name: $v
Entry: 7
Data: 2|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: _animator
- Name: <UserType>k__BackingField
Entry: 7
Data: 3|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: UnityEngine.Animator, UnityEngine.AnimationModule
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 3
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 4|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: _gameManager
- Name: $v
Entry: 7
Data: 5|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: _gameManager
- Name: <UserType>k__BackingField
Entry: 7
Data: 6|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: Marro.PacManUdon.GameManager, Assembly-CSharp
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 7
Data: 7|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: VRC.Udon.UdonBehaviour, VRC.Udon
- Name:
Entry: 8
Data:
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 8|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: _ghost
- Name: $v
Entry: 7
Data: 9|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: _ghost
- Name: <UserType>k__BackingField
Entry: 7
Data: 10|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: Marro.PacManUdon.Ghost, Assembly-CSharp
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 7
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 11|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: _lastUpdate
- Name: $v
Entry: 7
Data: 12|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: _lastUpdate
- Name: <UserType>k__BackingField
Entry: 7
Data: 13|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: Marro.PacManUdon.PoleStrechLevels, Assembly-CSharp
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 7
Data: 14|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: System.Int32, mscorlib
- Name:
Entry: 8
Data:
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 15|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:

View File

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

View File

@@ -0,0 +1,138 @@
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
namespace Marro.PacManUdon
{
public enum PoleStrechLevels
{
None = 0,
Strech1 = 1,
Strech2 = 2,
Strech3 = 3,
Separated = 4,
}
[RequireComponent(typeof(Animator))]
public class Intermission2Pole : UdonSharpBehaviour
{
Animator _animator;
GameManager _gameManager;
Ghost _ghost;
PoleStrechLevels _lastUpdate;
const float Strech1Distance = 0f;
const float Strech2Distance = 0.250f;
const float Strech3Distance = 0.625f;
const float SeparatedDistance = 1f;
public void Initialize(GameManager gameManager, Ghost ghost)
{
_ghost = ghost;
_gameManager = gameManager;
_animator = GetComponent<Animator>();
Reset();
}
public void Reset()
{
_lastUpdate = PoleStrechLevels.None;
SetStrechLevel(PoleStrechLevels.None);
}
public void FixedUpdate()
{
if (!_ghost.gameObject.activeInHierarchy)
{
return;
}
var ghostDistance = -(_ghost.GetPosition().x - GetPosition().x);
// Debug.Log(ghostDistance);
if (ghostDistance < 0)
{
return;
}
var level = PoleStrechLevels.None;
if (ghostDistance >= SeparatedDistance)
{
level = PoleStrechLevels.Separated;
}
else if (ghostDistance >= Strech3Distance)
{
level = PoleStrechLevels.Strech3;
}
else if (ghostDistance >= Strech2Distance)
{
level = PoleStrechLevels.Strech2;
}
else if (ghostDistance >= Strech1Distance)
{
level = PoleStrechLevels.Strech1;
}
ProcessDistanceUpdate(level);
}
private void ProcessDistanceUpdate(PoleStrechLevels level)
{
if ((int)_lastUpdate >= (int)level)
{
return;
}
_lastUpdate = level;
if (level != PoleStrechLevels.Separated) // This one is done later via the timed procedure
{
SetStrechLevel(level);
}
else
{
// Align ghost nicely with pole :)
_ghost.SetPosition(new Vector2(GetPosition().x - SeparatedDistance, _ghost.GetPosition().y));
}
if (level == PoleStrechLevels.Strech1 || level == PoleStrechLevels.Separated) // Step forward timed procedure
{
_gameManager.Intermission2PoleUpdate();
}
}
public void SetStrechLevel(PoleStrechLevels level)
{
_animator.SetFloat("Strech", GetAnimatorValueForStrechLevel(level));
}
private float GetAnimatorValueForStrechLevel(PoleStrechLevels level)
{
switch (level)
{
case PoleStrechLevels.None:
return 0f;
case PoleStrechLevels.Strech1:
return 1f;
case PoleStrechLevels.Strech2:
return 2f;
case PoleStrechLevels.Strech3:
return 3f;
case PoleStrechLevels.Separated:
return 4f;
default:
Debug.LogError("Invalid pole strech level!");
return 0f;
}
}
public Vector2 GetPosition()
{
return (Vector2)transform.localPosition;
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 88e88d9bfa304c8448489e53fc031f74
guid: 5561162f0532eab4ea6c388cb2d33504
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,640 @@
%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: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3}
m_Name: NetworkManager
m_EditorClassIdentifier:
serializedUdonProgramAsset: {fileID: 11400000, guid: 37b60ab207700554ba5c119f63c3c7bd, type: 2}
udonAssembly:
assemblyError:
sourceCsScript: {fileID: 11500000, guid: ac984c07ae3e9674a850c3916be56ca3, type: 3}
scriptVersion: 2
compiledVersion: 2
behaviourSyncMode: 0
hasInteractEvent: 0
scriptID: -3442137929426346155
serializationData:
SerializedFormat: 2
SerializedBytes:
ReferencedUnityObjects: []
SerializedBytesString:
Prefab: {fileID: 0}
PrefabModificationsReferencedUnityObjects: []
PrefabModifications: []
SerializationNodes:
- Name: fieldDefinitions
Entry: 7
Data: 0|System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[UdonSharp.Compiler.FieldDefinition,
UdonSharp.Editor]], mscorlib
- Name: comparer
Entry: 7
Data: 1|System.Collections.Generic.GenericEqualityComparer`1[[System.String,
mscorlib]], mscorlib
- Name:
Entry: 8
Data:
- Name:
Entry: 12
Data: 11
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: syncedObjects
- Name: $v
Entry: 7
Data: 2|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: syncedObjects
- Name: <UserType>k__BackingField
Entry: 7
Data: 3|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: Marro.PacManUdon.SyncedObject[], Assembly-CSharp
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 7
Data: 4|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: UnityEngine.Component[], UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: true
- Name: _fieldAttributes
Entry: 7
Data: 5|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 6|UnityEngine.SerializeField, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: DebugImageToIndicateOwner
- Name: $v
Entry: 7
Data: 7|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: DebugImageToIndicateOwner
- Name: <UserType>k__BackingField
Entry: 7
Data: 8|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: UnityEngine.Animator, UnityEngine.AnimationModule
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 8
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: true
- Name: _fieldAttributes
Entry: 7
Data: 9|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 10|UnityEngine.SerializeField, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: isOwner
- Name: $v
Entry: 7
Data: 11|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: isOwner
- Name: <UserType>k__BackingField
Entry: 7
Data: 12|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: System.Boolean, mscorlib
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 12
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 13|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: isSynced
- Name: $v
Entry: 7
Data: 14|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: isSynced
- Name: <UserType>k__BackingField
Entry: 9
Data: 12
- Name: <SystemType>k__BackingField
Entry: 9
Data: 12
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 15|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: startTimeTicks
- Name: $v
Entry: 7
Data: 16|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: startTimeTicks
- Name: <UserType>k__BackingField
Entry: 7
Data: 17|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: System.Int64, mscorlib
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 17
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 18|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: nextEventTimeTicks
- Name: $v
Entry: 7
Data: 19|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: nextEventTimeTicks
- Name: <UserType>k__BackingField
Entry: 9
Data: 17
- Name: <SystemType>k__BackingField
Entry: 9
Data: 17
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 20|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: retriesWithoutSuccess
- Name: $v
Entry: 7
Data: 21|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: retriesWithoutSuccess
- Name: <UserType>k__BackingField
Entry: 7
Data: 22|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: System.Int32, mscorlib
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 22
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 23|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: buffer
- Name: $v
Entry: 7
Data: 24|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: buffer
- Name: <UserType>k__BackingField
Entry: 7
Data: 25|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: System.Byte[], mscorlib
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 25
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 26|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: index
- Name: $v
Entry: 7
Data: 27|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: index
- Name: <UserType>k__BackingField
Entry: 9
Data: 22
- Name: <SystemType>k__BackingField
Entry: 9
Data: 22
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 28|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: networkedData
- Name: $v
Entry: 7
Data: 29|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: networkedData
- Name: <UserType>k__BackingField
Entry: 9
Data: 25
- Name: <SystemType>k__BackingField
Entry: 9
Data: 25
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 3
Data: 1
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 30|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 31|UdonSharp.UdonSyncedAttribute, UdonSharp.Runtime
- Name:
Entry: 8
Data:
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: <CurrentTimeTicks>k__BackingField
- Name: $v
Entry: 7
Data: 32|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: <CurrentTimeTicks>k__BackingField
- Name: <UserType>k__BackingField
Entry: 9
Data: 17
- Name: <SystemType>k__BackingField
Entry: 9
Data: 17
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 33|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:

View File

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

View File

@@ -0,0 +1,525 @@
using Cysharp.Threading.Tasks.Triggers;
using JetBrains.Annotations;
using System;
using System.Drawing;
using System.Text;
using UdonSharp;
using UnityEngine;
using VRC.SDK3.UdonNetworkCalling;
using VRC.SDKBase;
using VRC.Udon.ClientBindings.Interfaces;
using VRC.Udon.Common;
namespace Marro.PacManUdon
{
public enum NetworkEventType
{
FullSync = 0,
PacManTurn = 1,
}
public class NetworkManager : UdonSharpBehaviour
{
// The network manager works by serializing event and state data into a byte array, including a timestamp for each event.
// If user is owner, this data is created and stored in a buffer which is cleared upon transmission.
// If user is not owner, this data is read into the same buffer and replayed based on the included timestamp.
// Data replay is delayed with an offset on the timestamp to hide inconsistency in latency.
// The timestamp is transferred in ms as a 32 bit uint, which gives a maximum time of about 49 days.
// The maximum allowed age of a VRChat instance is 7 days, so this should not cause issues.
// A byte array is used as a DataList or DataDictionary can only be transmitted as JSON which is much less efficient.
// As Udon does not support instantiating objects, I have not created classes to represent the data being sent.
// Correct parsing is dependend upon everything being read out identially to how it was created.
// An event has the following structure:
// [0-1]: (ushort) Size of event.
// [2-5]: (uint) Time in seconds at which event occured.
// [6]: (byte) Type of event. 0 = Full Sync, which is used to sync up from an undefinted state.
// [7+]: Event-specific data
private const int BufferMaxSizeBytes = 10000;
private const int BufferIncrementSizeBytes = 1000;
[SerializeField] private SyncedObject[] syncedObjects;
[SerializeField] private Animator DebugImageToIndicateOwner;
private bool isOwner;
private bool isSynced;
private long startTimeTicks = DateTime.UtcNow.Ticks; // Initialize to prevent errors
private long nextEventTimeTicks;
private int retriesWithoutSuccess;
// Main buffer of events
private byte[] buffer;
private int index;
private const ushort HeaderEventSizeIndex = 0;
private const ushort HeaderTimestampIndex = 2;
private const ushort HeaderEventTypeIndex = 6;
private const ushort HeaderLength = 7;
private const int Delay = 250;
[UdonSynced] private byte[] networkedData = new byte[0];
public long CurrentTimeTicks { get; private set; }
public void Initialize()
{
if (!BitConverter.IsLittleEndian)
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Fatal: NetworkManager only supports little endian! Network sync will not be possible.");
var zero = 0;
Debug.Log(1 / zero); // Intentionally crash
return;
}
buffer = new byte[BufferIncrementSizeBytes];
index = 0;
startTimeTicks = DateTime.UtcNow.Ticks;
isSynced = false;
retriesWithoutSuccess = 0;
SetOwner(Networking.IsOwner(gameObject));
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Initialized, startTimeTicks: {startTimeTicks}");
}
public void Update()
{
if (!isOwner)
{
ProgressReplayTime();
}
UpdateTime(DateTime.UtcNow.Ticks);
}
public void SendEvent(NetworkEventType eventType)
{
if (!isOwner)
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Attempted {nameof(SendEvent)} while not the owner!");
return;
}
var eventTime = GetTimestamp(CurrentTimeTicks);
InitializeEvent(eventType, eventTime, BufferMaxSizeBytes, out byte[][] data, out var index);
foreach (var obj in syncedObjects)
{
obj.AppendSyncedData(data, ref index, eventType);
}
// Get event size, skipping over the event size which is not yet included
ushort eventSize = 0;
for (int i = 0; i < index; i++)
{
eventSize += (ushort)data[i].Length;
}
if (!EnsureSpaceToStoreEvent(eventSize))
{
return;
}
data[0] = BitConverter.GetBytes(eventSize);
var oldIndex = this.index;
FlattenAndCopy(data, index, buffer, ref this.index);
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Prepared event with {eventSize} bytes and timestamp {eventTime} for serialization, index went from {oldIndex} to {this.index}");
RequestSerialization();
retriesWithoutSuccess = 0; // We had success!
}
public void RequestEvent(NetworkEventType eventType)
{
if (isOwner)
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Attempted {nameof(RequestEvent)} while we are the owner!");
return;
}
SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.Owner, "RequestEventReceived", eventType);
}
[NetworkCallable]
public void RequestEventReceived(NetworkEventType eventType)
{
if (!isOwner)
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Attempted {nameof(RequestEventReceived)} while we are not the owner!");
return;
}
SendEvent(eventType);
}
private void ProcessIncomingData()
{
if (networkedData.Length == 0)
{
return; // Nothing to process
}
var length = networkedData.Length;
int index = 0;
while (index < length)
{
if (length - index < HeaderLength)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) {nameof(ProcessIncomingData)}: Remaining data in networkedData is not long enough to form a complete event!");
HandleError();
return;
}
var eventSize = networkedData[index + HeaderEventSizeIndex];
var eventType = (NetworkEventType)networkedData[index + HeaderEventTypeIndex];
if (eventType == NetworkEventType.FullSync)
{
ProcessIncomingFullSync(index, eventSize); // Immediately process full sync
index += eventSize;
continue;
}
if (!isSynced)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Received event of type {eventType} while we are not yet synced to the remote time, ignoring event.");
index += eventSize;
continue;
}
AppendEventToBuffer(index, eventSize);
index += eventSize;
}
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Received {networkedData.Length} bytes!\nBytes received:\n{BytesToString(networkedData)}");
}
private void ProcessIncomingFullSync(int index, int size)
{
// Intentionally not doing a buffer size check here, since this is not appending to the buffer
// (and there is no good way to continue if event is too large)
// Clear buffer and copy the full sync into it
buffer = new byte[size];
Array.Copy(networkedData, index, buffer, 0, size);
this.index = size;
// Sync up to the time in the full sync
var timestamp = BitConverter.ToUInt32(networkedData, index + HeaderTimestampIndex);
SyncToTimestamp(timestamp);
// Immediately apply the full sync
nextEventTimeTicks = GetTimeTicks(timestamp);
isSynced = true;
}
private void AppendEventToBuffer(int index, int size)
{
if (!EnsureSpaceToStoreEvent(size))
{
return;
}
Array.Copy(networkedData, index, buffer, this.index, size);
this.index += size;
UpdateNextEventTime();
}
private void ProgressReplayTime()
{
while (index != 0 && nextEventTimeTicks <= CurrentTimeTicks)
{
ProcessIncomingEvent();
UpdateNextEventTime();
}
}
private void UpdateNextEventTime()
{
if (index == 0)
{
return;
}
var nextEventTimeTicks = GetTimeTicks(BitConverter.ToUInt32(buffer, HeaderTimestampIndex));
if (nextEventTimeTicks >= this.nextEventTimeTicks)
{
this.nextEventTimeTicks = nextEventTimeTicks;
}
else
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) New event is earlier than previous event!");
HandleError();
return;
}
}
private void ProcessIncomingEvent()
{
var eventTimeTicks = GetTimeTicks(BitConverter.ToUInt32(buffer, HeaderTimestampIndex));
var eventType = (NetworkEventType)buffer[HeaderEventTypeIndex];
var index = (int)HeaderLength; // Skip header
UpdateTime(eventTimeTicks);
foreach (var obj in syncedObjects)
{
obj.FixedUpdate();
}
foreach (var obj in syncedObjects)
{
var success = obj.SetSyncedData(buffer, ref index, eventType);
if (!success)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Malformed data reported by {obj.name} during event type {eventType}!");
HandleError();
return;
}
if (index > this.index)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Buffer overflow during {nameof(SyncedObject.SetSyncedData)} for {obj.name} in event type {eventType}!");
HandleError();
return;
}
}
var eventSize = BitConverter.ToUInt16(buffer, HeaderEventSizeIndex);
if (index != eventSize)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Amount of data read does not match event size! Expected {eventSize}, read {index}.");
HandleError();
return;
}
RemoveProcessedDataFromBuffer(index);
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Processed incoming event! Total {index} bytes.");
retriesWithoutSuccess = 0; // We had success!
}
private void SyncToTimestamp(uint newTime)
{
var timeToSyncTo = newTime - Delay;
startTimeTicks = DateTime.UtcNow.Ticks - timeToSyncTo * TimeSpan.TicksPerMillisecond;
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Synced to time {newTime}, startTimeTicks is now {startTimeTicks}");
}
private bool EnsureSpaceToStoreEvent(int eventSize)
{
if (index + eventSize <= buffer.Length)
{
return true; // Enough space!
}
var newBufferSize = ((index + eventSize) / BufferIncrementSizeBytes + 1) * BufferIncrementSizeBytes;
var success = IncreaseBufferSize(newBufferSize);
if (success)
{
return true;
}
if (index == 0)
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Buffer is not large enough to store event!");
}
else
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Too much data in buffer to store event!");
}
HandleError(); // We can store event now that we cleared the buffer.
return false;
}
private bool IncreaseBufferSize(int newSize)
{
if (newSize < buffer.Length)
{
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Cannot decrease the size of the buffer!");
return false;
}
if (newSize > BufferMaxSizeBytes)
{
return false;
}
var oldBuffer = buffer;
buffer = new byte[newSize];
oldBuffer.CopyTo(buffer, 0);
return true;
}
private void InitializeEvent(NetworkEventType eventType, uint eventTime, int maxSize, out byte[][] data, out int index)
{
data = new byte[maxSize][];
index = 3;
data[0] = new byte[2]; // Placeholder for event size
data[1] = BitConverter.GetBytes(eventTime);
data[2] = new byte[] { GameManager.Int32ToByte((int)eventType) };
}
private void FlattenAndCopy(byte[][] data, int length, byte[] target, ref int index)
{
for (int i = 0; i < length; i++)
{
var values = data[i];
Array.Copy(values, 0, target, index, values.Length);
index += values.Length;
}
}
private void RemoveProcessedDataFromBuffer(int amountProcessed)
{
var oldBuffer = buffer;
index -= amountProcessed;
buffer = new byte[BufferMaxSizeBytes];
Array.Copy(oldBuffer, amountProcessed, buffer, 0, index);
}
private void ClearBuffer()
{
buffer = new byte[BufferMaxSizeBytes];
index = 0;
}
private void HandleError()
{
retriesWithoutSuccess++;
if (retriesWithoutSuccess > 3)
{
Debug.LogError($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Fatal: Retried 3 times without success.");
var zero = 0;
Debug.Log(1 / zero); // Intentionally crash
return;
}
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Encountered data error, attempting to recover via full sync.");
ClearBuffer();
if (!isOwner)
{
RequestEvent(NetworkEventType.FullSync);
}
else
{
SendEvent(NetworkEventType.FullSync);
}
}
private void SetOwner(bool isOwner)
{
this.isOwner = isOwner;
if (DebugImageToIndicateOwner != null)
{
DebugImageToIndicateOwner.SetFloat("Color", isOwner ? 1 : 0);
}
}
public override void OnOwnershipTransferred(VRCPlayerApi newOwner)
{
SetOwner(newOwner == Networking.LocalPlayer);
if(isOwner)
{
HandleError();
}
}
public override void OnPreSerialization()
{
if (isOwner)
{
networkedData = new byte[index];
Array.Copy(buffer, networkedData, index);
}
else
{
networkedData = new byte[0]; // Prevent exception loop in VRChat SDK
}
}
public override void OnPostSerialization(SerializationResult result)
{
if (!result.success)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Serialization failed! Tried to send {result.byteCount} bytes.");
return;
}
if (!isOwner || networkedData.Length == 0)
{
return;
}
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Serialized with {networkedData.Length} bytes!\nBytes sent:\n{BytesToString(networkedData)}");
// Remove all transferred data from the buffer, leaving data that came in after serialization
RemoveProcessedDataFromBuffer(networkedData.Length);
networkedData = null;
}
public override void OnDeserialization()
{
if (!isOwner)
{
ProcessIncomingData();
}
}
private void UpdateTime(long timeTicks)
{
CurrentTimeTicks = timeTicks;
foreach (var obj in syncedObjects)
{
obj.Dt = (timeTicks - obj.LastUpdateTicks) / (float)TimeSpan.TicksPerSecond;
obj.LastUpdateTicks = timeTicks;
}
}
public uint GetTimestamp(long timeTicks)
{
return (uint)((timeTicks - startTimeTicks) / TimeSpan.TicksPerMillisecond);
}
public long GetTimeTicks(uint timeStamp)
{
return timeStamp * TimeSpan.TicksPerMillisecond + startTimeTicks;
}
public bool IsOwner => isOwner;
public string BytesToString(byte[] bytes)
{
var sb = new StringBuilder("new byte[] { ");
foreach (var b in bytes)
{
sb.Append(b + ", ");
}
sb.Append("}");
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ac984c07ae3e9674a850c3916be56ca3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@
public class PacMan : GridMover
{
private GameController gameController;
private GameManager gameController;
private PlayerInput input;
private float defaultSpeed;
private float powerPelletSpeed;
@@ -28,14 +28,24 @@
private Vector2[] predefinedPath;
private int predefinedPathIndex;
[UdonSynced] private Vector2 syncedPosition;
[UdonSynced] private Vector2 targetDirection;
[UdonSynced] private Vector2 direction;
[UdonSynced] private float freezeSeconds;
[UdonSynced] private bool frozen;
private Vector2 syncedPosition;
private Vector2 targetDirection;
private float freezeSeconds;
private bool frozen;
#region Animator constants
private const string AnimatorKeyDead = "Dead";
private const string AnimatorKeyDirection = "Direction";
private const float AnimatorDirectionNone = 0f;
private const float AnimatorDirectionRight = 0.25f;
private const float AnimatorDirectionLeft = 0.50f;
private const float AnimatorDirectionUp = 0.75f;
private const float AnimatorDirectionDown = 1f;
private const float AnimatorDirectionRightBig = 1.25f;
#endregion
public void Initialize(PlayerInput input, VRCObjectPool pelletPool, GameController gameController)
public void Initialize(PlayerInput input, VRCObjectPool pelletPool, GameManager gameController)
{
this.gameController = gameController;
this.input = input;
@@ -65,7 +75,7 @@
animator.SetTrigger("Reset");
}
void FixedUpdate()
public override void FixedUpdate()
{
// gameStateManager.statusDisplay.SetDebugText(1, this.targetDirection.ToString());
@@ -196,13 +206,13 @@
return nextPosition;
}
private void UpdateAnimator()
protected override void UpdateAnimator()
{
// Debug.Log($"{gameObject} UpdateAnimator with direction {direction}, dead {dead}, frozen {frozen}");
if (!gameObject.activeInHierarchy)
return;
animator.SetBool("Dead", dead);
animator.SetBool(AnimatorKeyDead, dead);
if (dead)
{
animator.speed = 1;
@@ -211,7 +221,7 @@
if (frozen || direction.Equals(Vector2.zero))
{
animator.SetFloat("Direction", 0f);
animator.SetFloat(AnimatorKeyDirection, AnimatorDirectionNone);
animator.speed = 0;
}
else
@@ -219,31 +229,23 @@
animator.speed = 1;
if (targetDirection.Equals(Vector2.right))
{
animator.SetFloat("Direction", 0.25f);
animator.SetFloat(AnimatorKeyDirection, AnimatorDirectionRight);
}
else if (targetDirection.Equals(Vector2.left))
{
animator.SetFloat("Direction", 0.5f);
animator.SetFloat(AnimatorKeyDirection, AnimatorDirectionLeft);
}
else if (targetDirection.Equals(Vector2.up))
{
animator.SetFloat("Direction", 0.75f);
animator.SetFloat(AnimatorKeyDirection, AnimatorDirectionUp);
}
else if (targetDirection.Equals(Vector2.down))
{
animator.SetFloat("Direction", 1f);
animator.SetFloat(AnimatorKeyDirection, AnimatorDirectionDown);
}
}
}
// public Vector2 GetTarget(Vector2 gridPosition, Vector2 currentDirection) {
// Vector2 nextDirection = input.GetRotatedDirection();
// if(!nextDirection.Equals(currentDirection) && !GridMoverTools.CheckCollisionInDirection(transform, gridPosition, nextDirection)) {
// return nextDirection;
// }
// return Vector2.zero;
// }
public void SetDead(bool dead)
{
this.dead = dead;
@@ -303,50 +305,22 @@
predefinedPathIndex = 0;
}
public void BecomeBig()
{
animator.SetFloat(AnimatorKeyDirection, AnimatorDirectionRightBig);
}
void SetVisibility(bool visible)
{
renderer.enabled = visible;
}
public override Vector2 GetPosition()
{
return (Vector2)transform.localPosition;
}
public override void SetPosition(Vector2 position)
{
GridMoverTools.SetPosition(position, transform);
}
public override Vector2 GetDirection()
{
return direction;
}
public void SetDirection(Vector2 direction)
{
this.direction = direction;
RequestSerialization();
UpdateAnimator();
}
public void SetTargetDirection(Vector2 targetDirection)
{
this.targetDirection = targetDirection;
UpdateAnimator();
}
public override void OnPreSerialization()
{
syncedPosition = GetPosition();
}
public override void OnDeserialization()
{
SetPosition(syncedPosition);
UpdateAnimator();
}
void OnTriggerEnter(Collider other)
{
Pellet pellet = other.gameObject.GetComponent<Pellet>();
@@ -364,16 +338,14 @@
if (pellet.isPowerPellet)
{
if (Networking.IsOwner(gameObject)) gameController.GotPowerPellet();
gameController.GotPowerPellet();
freezeSeconds = 0.05f;
}
else
{
if (Networking.IsOwner(gameObject)) gameController.GotPellet();
gameController.GotPellet();
freezeSeconds = 0.0166666666666667f;
}
if (Networking.IsOwner(gameObject)) RequestSerialization();
return;
}
else if (Networking.IsOwner(gameObject) && other.gameObject.GetComponent<BonusFruit>())

View File

@@ -34,6 +34,7 @@ namespace Marro.PacManUdon
{
AttractScreenIntroduction,
AttractScreenDemo,
AttractScreenWaitToRestart,
WaitForStart,
WaitForStartTimeout,
StartNewGame,
@@ -42,7 +43,10 @@ namespace Marro.PacManUdon
GhostCaught,
PacManCaught,
RestartLevel,
GameOver
GameOver,
Intermission1,
Intermission2,
Intermission3
}
public static class PacManConstants

View File

@@ -30,7 +30,7 @@
}
powerPellets = GetComponentsInChildren<Animator>(true);
Debug.Log($"{gameObject} Initialized, powerPellets: {powerPellets}");
// Debug.Log($"{gameObject} Initialized, powerPellets: {powerPellets}");
powerPelletBlinkToggleInterval = PacManConstants.GetPowerPelletBlinkToggleInterval();
SetPowerPelletsBlink(false);
}
@@ -67,7 +67,7 @@
void SetPowerPelletsVisible(bool visible)
{
Debug.Log($"{gameObject} SetPowerPelletVisible {visible}, powerPellets.Length: {powerPellets.Length}");
// Debug.Log($"{gameObject} SetPowerPelletVisible {visible}, powerPellets.Length: {powerPellets.Length}");
foreach (Animator powerPellet in powerPellets)
{
powerPellet.SetBool("Visible", visible);

View File

@@ -103,19 +103,19 @@ MonoBehaviour:
Data:
- Name: $k
Entry: 1
Data: gameController
Data: gameManager
- Name: $v
Entry: 7
Data: 5|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: gameController
Data: gameManager
- Name: <UserType>k__BackingField
Entry: 7
Data: 6|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: Marro.PacManUdon.GameController, Assembly-CSharp
Data: Marro.PacManUdon.GameManager, Assembly-CSharp
- Name:
Entry: 8
Data:

View File

@@ -10,7 +10,7 @@
public class PlayerInput : UdonSharpBehaviour
{
public bool active;
private GameController gameController;
private GameManager gameManager;
Vector2 inputHorizontal;
Vector2 inputVertical;
float horizontalValue;
@@ -18,9 +18,9 @@
bool horizontalPriority;
VRCPlayerApi player;
public void Initialize(GameController gameController)
public void Initialize(GameManager gameManager)
{
this.gameController = gameController;
this.gameManager = gameManager;
inputHorizontal = Vector2.zero;
inputVertical = Vector2.zero;
horizontalPriority = false;
@@ -35,7 +35,7 @@
player.SetRunSpeed(0);
player.SetStrafeSpeed(0);
gameController.JoystickGrabbed();
gameManager.JoystickGrabbed();
}
public void Deactivate()
@@ -46,7 +46,7 @@
player.SetStrafeSpeed(2);
active = false;
gameController.JoystickReleased();
gameManager.JoystickReleased();
}
public override void InputJump(bool pressed, UdonInputEventArgs args)
@@ -128,6 +128,7 @@
// horizontalPriority = true;
SetPriority(true);
}
// Debug.Log("Vertical Input Event: " + value + " | Direction: " + direction + " | lastDirection : " + lastDirection);
}

View File

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

View File

@@ -0,0 +1,348 @@
using UnityEngine;
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceStepAttractScreenDemo(int sequenceProgress)
{
switch (sequenceProgress)
{
case 0:
PrepareForCutscene();
SetGameState(PacManGameState.AttractModeDemo);
break;
case 1:
InitializeLevel();
SetMazeVisible(true);
SetLevel(1);
break;
case 2:
// Setup ghosts
ghostManager.Ghosts[0].SetPredefinedPath(new Vector2[]{ // Blinky
Vector2.down,
Vector2.left,
Vector2.up,
Vector2.right,
Vector2.zero,
Vector2.zero,
Vector2.up,
Vector2.right,
Vector2.down,
Vector2.zero,
Vector2.right,
Vector2.up,
Vector2.left,
Vector2.down,
Vector2.right,
Vector2.up,
Vector2.zero,
Vector2.left,
Vector2.down,
Vector2.zero,
Vector2.left,
Vector2.down,
Vector2.right,
// Goes through tunnel
Vector2.zero,
Vector2.up,
Vector2.left,
Vector2.down,
Vector2.right,
Vector2.down,
Vector2.right,
Vector2.down,
Vector2.right,
Vector2.up,
Vector2.right,
Vector2.up,
Vector2.left,
Vector2.zero,
Vector2.down,
Vector2.left,
Vector2.zero,
Vector2.up,
Vector2.left,
// Gets eaten
Vector2.zero,
Vector2.up,
Vector2.right,
Vector2.up,
Vector2.right,
Vector2.down,
Vector2.right,
Vector2.down,
Vector2.left,
Vector2.down,
Vector2.left,
Vector2.down,
Vector2.right,
Vector2.down,
Vector2.left,
});
ghostManager.Ghosts[1].SetPredefinedPath(new Vector2[]{ // Pinky
Vector2.down,
Vector2.left,
Vector2.up,
Vector2.zero,
Vector2.zero,
Vector2.left,
Vector2.down,
Vector2.right,
// Pellet starts
Vector2.up,
Vector2.right,
Vector2.down,
Vector2.left,
Vector2.up,
Vector2.right,
// Pellet ends
Vector2.zero,
Vector2.down,
// Pellet starts
Vector2.left,
Vector2.down,
Vector2.zero,
Vector2.left,
// Caught
Vector2.up,
Vector2.right,
Vector2.zero,
Vector2.down,
Vector2.right,
Vector2.down,
Vector2.right,
// Home
Vector2.down,
Vector2.left,
Vector2.up,
Vector2.right,
Vector2.down,
Vector2.zero,
Vector2.right,
Vector2.down,
Vector2.right,
Vector2.up,
Vector2.right,
Vector2.up,
Vector2.left,
Vector2.zero,
Vector2.down,
Vector2.left,
// Power pellet active
Vector2.up,
Vector2.right,
Vector2.up,
Vector2.left,
Vector2.up,
Vector2.left,
Vector2.down,
Vector2.right,
Vector2.down,
Vector2.left,
Vector2.down,
Vector2.right,
Vector2.down,
Vector2.left,
Vector2.up
});
ghostManager.Ghosts[2].SetPredefinedPath(new Vector2[]{ // Inky
Vector2.up,
Vector2.right,
Vector2.up,
Vector2.left,
Vector2.zero,
Vector2.zero,
Vector2.down,
Vector2.right,
// Pellet starts
Vector2.up,
Vector2.right,
Vector2.up,
// Caught
Vector2.right,
Vector2.down,
Vector2.right,
Vector2.down,
Vector2.left,
Vector2.down,
Vector2.left,
Vector2.down,
Vector2.left,
Vector2.up,
Vector2.left,
Vector2.down,
Vector2.right,
Vector2.down,
Vector2.right,
Vector2.zero,
Vector2.down,
Vector2.right,
Vector2.down,
Vector2.left,
Vector2.zero,
Vector2.zero,
Vector2.up,
Vector2.right,
Vector2.up,
Vector2.left,
Vector2.up,
Vector2.right,
Vector2.up,
Vector2.left,
Vector2.up,
Vector2.right,
Vector2.down,
Vector2.left,
Vector2.down,
Vector2.left,
Vector2.zero,
Vector2.up,
Vector2.left
});
ghostManager.Ghosts[3].SetPredefinedPath(new Vector2[]{ // Clyde
Vector2.down,
Vector2.right,
Vector2.up,
Vector2.left,
Vector2.down,
Vector2.zero,
Vector2.left,
Vector2.zero,
Vector2.down,
Vector2.right,
Vector2.down,
Vector2.right,
Vector2.up,
Vector2.right,
Vector2.zero,
Vector2.down,
Vector2.left,
Vector2.down,
Vector2.left,
Vector2.zero,
Vector2.up,
Vector2.right,
Vector2.zero,
Vector2.up,
Vector2.left,
Vector2.down,
Vector2.right,
Vector2.up,
Vector2.left,
Vector2.up,
Vector2.right,
Vector2.down,
Vector2.left,
Vector2.down,
Vector2.left,
Vector2.zero,
Vector2.up,
Vector2.right
});
pacMan.SetPredefinedPath(new Vector2[]{
Vector2.down,
Vector2.right,
Vector2.down,
Vector2.right,
Vector2.zero,
Vector2.up,
Vector2.left,
Vector2.up,
Vector2.right,
Vector2.up,
Vector2.left,
Vector2.zero,
Vector2.up,
Vector2.zero,
Vector2.left,
Vector2.down,
Vector2.left,
Vector2.up,
Vector2.zero,
Vector2.zero,
Vector2.left,
Vector2.down,
Vector2.right,
Vector2.zero,
Vector2.up,
Vector2.left,
Vector2.down,
Vector2.zero,
Vector2.left,
Vector2.up,
Vector2.right,
Vector2.zero,
Vector2.down,
Vector2.right,
Vector2.down,
Vector2.left,
Vector2.down,
Vector2.left,
Vector2.zero,
Vector2.down,
Vector2.zero,
Vector2.right,
Vector2.down,
Vector2.left,
Vector2.zero,
Vector2.zero,
Vector2.up,
Vector2.right,
Vector2.up,
Vector2.left,
Vector2.up,
Vector2.right,
Vector2.zero,
Vector2.down,
Vector2.right,
Vector2.up,
Vector2.right,
Vector2.zero,
Vector2.down,
Vector2.left,
Vector2.down,
Vector2.right,
Vector2.down,
Vector2.left,
Vector2.zero,
Vector2.zero,
Vector2.up,
Vector2.right,
Vector2.up,
Vector2.left,
Vector2.up,
Vector2.right,
});
break;
case 3:
SetPelletsActive(true);
pelletManager.RestoreAllPellets();
statusDisplay.SetGameOverTextVisible(true);
break;
case 4:
// Show pacman, show ghosts
SetPacManActive(true);
SetGhostsActive(true);
break;
case 5:
// Unfreeze
SetFrozen(false);
break;
case 6:
break;
}
}
private void TimeSequenceFinishedAttractScreenDemo()
{
StartTimeSequence(PacManTimeSequence.AttractScreenWaitToRestart);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c021fd7df80d25746b58cf4c48c6d95a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,181 @@
using UnityEngine;
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceStepAttractScreenIntroduction(int sequenceProgress)
{
switch (sequenceProgress)
{
case 0:
PrepareForCutscene();
SetGameState(PacManGameState.AttractMode);
// Initialize
soundManager.SuppressSound(true);
attractScreen.gameObject.SetActive(true);
attractScreen.Initialize();
for (int i = 0; i <= 15; i++)
{
// Debug.Log($"{gameObject} TimeSequenceAttractScreen deactivating with iteration i");
attractScreenElements[i].SetActive(false);
}
attractScreen.SetPowerPelletsBlink(false);
break;
case 1:
// show "Character / Nickname"
attractScreenElements[0].SetActive(true);
break;
case 2:
// Show blinky sprite
attractScreenElements[1].SetActive(true);
break;
case 3:
// Show blinky character
attractScreenElements[2].SetActive(true);
break;
case 4:
// Show blinky nickname
attractScreenElements[3].SetActive(true);
break;
case 5:
// Show pinky sprite
attractScreenElements[4].SetActive(true);
break;
case 6:
// Show pinky character
attractScreenElements[5].SetActive(true);
break;
case 7:
// Show pinky nickname
attractScreenElements[6].SetActive(true);
break;
case 8:
// Show inky sprite
attractScreenElements[7].SetActive(true);
break;
case 9:
// Show inky character
attractScreenElements[8].SetActive(true);
break;
case 10:
// Show inky nickname
attractScreenElements[9].SetActive(true);
break;
case 11:
// Show clyde sprite
attractScreenElements[10].SetActive(true);
break;
case 12:
// Show clyde character
attractScreenElements[11].SetActive(true);
break;
case 13:
// Show clyde nickname
attractScreenElements[12].SetActive(true);
break;
case 14:
// Show pellet point values
attractScreenElements[13].SetActive(true);
break;
case 15:
// Show copyright message, setup pellet demonstration
attractScreenElements[14].SetActive(true);
attractScreenElements[15].SetActive(true);
pacMan.Reset();
pacMan.SetLevel(1);
pacMan.SetKinematic(true);
pacMan.SetActive(true);
pacMan.SetPosition(attractScreenElements[16].transform.localPosition);
pacMan.SetDirection(Vector2.left);
ghostManager.Reset();
ghostManager.SetLevel(2);
ghostManager.SetKinematic(true);
ghostManager.SetActive(true);
Ghost[] ghosts = ghostManager.Ghosts;
for (int i = 0; i < ghosts.Length; i++)
{
ghosts[i].SetPosition(attractScreenElements[17 + i].transform.localPosition);
ghosts[i].SetDirection(Vector2.left);
ghosts[i].SetState(PacManGhostState.Normal);
}
break;
case 16:
attractScreen.SetPowerPelletsBlink(true);
SetFrozen(false);
break;
case 17:
ghostManager.SetPowerPellet(true);
pacMan.SetPowerPellet(true);
attractScreenElements[15].SetActive(false);
break;
case 18:
// Turn PacMan around after eating power pellet
pacMan.SetDirection(Vector2.right);
pacMan.SetTargetDirection(Vector2.right);
break;
case 19:
ghostManager.Ghosts[0].Caught(200);
pacMan.SetActive(false);
SetFrozen(true);
break;
case 20:
ghostManager.Ghosts[0].ReturnHome();
ghostManager.Ghosts[0].SetActive(false);
pacMan.SetActive(true);
SetFrozen(false);
break;
case 21:
ghostManager.Ghosts[1].Caught(400);
pacMan.SetActive(false);
SetFrozen(true);
break;
case 22:
ghostManager.Ghosts[1].ReturnHome();
ghostManager.Ghosts[1].SetActive(false);
pacMan.SetActive(true);
SetFrozen(false);
break;
case 23:
ghostManager.Ghosts[2].Caught(800);
pacMan.SetActive(false);
SetFrozen(true);
break;
case 24:
ghostManager.Ghosts[2].ReturnHome();
ghostManager.Ghosts[2].SetActive(false);
pacMan.SetActive(true);
SetFrozen(false);
break;
case 25:
ghostManager.Ghosts[3].Caught(1600);
pacMan.SetActive(false);
SetFrozen(true);
break;
case 26:
ghostManager.Ghosts[3].ReturnHome();
ghostManager.Ghosts[3].SetActive(false);
break;
}
}
private void TimeSequenceFinalizeAttractScreenIntroduction()
{
attractScreen.gameObject.SetActive(false);
}
private void TimeSequenceFinishedAttractScreenIntroduction()
{
StartTimeSequence(PacManTimeSequence.AttractScreenDemo);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e68e4d7063d5ae3439ad77dde2ff4d8b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceFinishedAttractScreenWaitToRestart()
{
StartAttractMode();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2b178dfcf6f9185448d2a2cdd4869abd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,68 @@
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceStepBoardClear(int sequenceProgress)
{
switch (sequenceProgress)
{
case 0:
// Freeze
SetFrozen(true);
soundManager.StopAllSound();
break;
case 1:
// Start board blinking, hide pellets in case of rack test
BoardClearAnimation();
SetPelletsActive(false);
break;
case 2:
// Hide ghosts
SetGhostsActive(false);
break;
case 3:
// Hide maze, lives indicator, level indicator
SetMazeVisible(false);
statusDisplay.SetExtraLivesDisplayVisible(false);
statusDisplay.SetLevelDisplayVisible(false);
break;
case 4:
// Hide score bar
statusDisplay.SetScoreDisplayVisible(false);
break;
case 5:
// Hide pacman, show level indicator with old level
SetPacManActive(false);
statusDisplay.SetLevelDisplayVisible(true);
break;
case 6:
break;
}
}
private void TimeSequenceFinishedBoardClear()
{
// Call handler for what should happen next
PacManTimeSequence nextSequence;
switch (level)
{
case 2:
nextSequence = PacManTimeSequence.Intermission1;
break;
case 5:
nextSequence = PacManTimeSequence.Intermission2;
break;
case 9:
case 13:
case 17:
nextSequence = PacManTimeSequence.Intermission3;
break;
default:
nextSequence = PacManTimeSequence.StartNewLevel;
break;
}
StartTimeSequence(nextSequence);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dfb426d2ba016fe4f994057627f457f9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceStepGameOver(int sequenceProgress)
{
switch (sequenceProgress)
{
case 0:
// Show game over text, freeze power pellet blink
statusDisplay.SetGameOverTextVisible(true);
pelletManager.FreezePowerPelletsBlink(true);
break;
case 1:
break;
}
}
private void TimeSequenceFinishedGameOver()
{
// Stop text blinking, transition to attract screen
statusDisplay.SetLabel1UPTextBlinking(false);
StartAttractMode();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8b7f368ee62421d44a31d95b0e18ef5a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceStepGhostCaught(int sequenceProgress)
{
switch (sequenceProgress)
{
case 0:
// Freeze and hide pacman, but let ghosts already in the caught animation continue
SetFrozen(true, ghostIgnoreIfCaught: true);
SetPacManActive(false);
soundManager.PlayGhostEatSound();
break;
case 1:
break;
}
}
private void TimeSequenceFinalizeGhostCaught()
{
// Unfreeze and reveal pacman
SetPacManActive(true);
SetFrozen(false);
ghostManager.GhostCaughtContinue();
soundManager.SetGhostRetreat(true);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7289f833229ba214487c6752af911043
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,72 @@
using UnityEngine;
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceStepIntermission1(int sequenceProgress)
{
var blinky = ghostManager.Ghosts[0];
switch (sequenceProgress)
{
case 0:
PrepareForCutscene();
// Show just level display
statusDisplay.SetLevelDisplayVisible(true);
break;
case 1:
// Start animation, pacman running and blinky prepared to chase
soundManager.SuppressSound(false);
soundManager.StartIntermissionSound();
pacMan.SetLevel(4);
pacMan.SetPowerPellet(false); // Update speed
pacMan.SetKinematic(true);
pacMan.SetActive(true);
pacMan.SetPosition(intermissionScreenElements[0].transform.localPosition);
pacMan.SetDirection(Vector2.left);
ghostManager.SetLevel(5);
ghostManager.SetKinematic(true);
ghostManager.gameObject.SetActive(true);
blinky.SetElroy(2);
blinky.SetPosition(intermissionScreenElements[1].transform.localPosition);
blinky.SetDirection(Vector2.left);
blinky.SetState(PacManGhostState.Normal);
SetFrozen(false);
break;
case 2:
// Start blinky chasing
blinky.SetActive(true);
break;
case 3:
// Reached end, make ghost scared and turn around
blinky.BecomeScared();
blinky.SetPosition(intermissionScreenElements[3].transform.localPosition);
pacMan.SetDirection(Vector2.zero);
pacMan.SetPosition(intermissionScreenElements[2].transform.localPosition);
pacMan.SetPowerPellet(true);
break;
case 4:
// Pacman starts chasing ghosts
pacMan.SetDirection(Vector2.right);
pacMan.BecomeBig();
break;
case 5:
// End cutscene
soundManager.StopAllSound();
SetFrozen(true);
break;
}
}
private void TimeSequenceFinishedIntermission1()
{
StartTimeSequence(PacManTimeSequence.StartNewLevel);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 343ec2edec89234428ef86d00b0c6430
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,96 @@
using UnityEngine;
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceStepIntermission2(int sequenceProgress)
{
var blinky = ghostManager.Ghosts[0];
switch (sequenceProgress)
{
case 0:
PrepareForCutscene();
// Show just level display
statusDisplay.SetLevelDisplayVisible(true);
break;
case 1:
// Show pole
SetIntermissionScreenVisible(true);
intermission2Pole.Reset();
break;
case 2:
// Start music
soundManager.SuppressSound(false);
soundManager.StartIntermissionSound();
break;
case 3:
// Start animation, pacman running and blinky prepared to chase
pacMan.SetLevel(4);
pacMan.SetPowerPellet(false); // Update speed
pacMan.SetKinematic(true);
pacMan.SetActive(true);
pacMan.SetPosition(intermissionScreenElements[0].transform.localPosition);
pacMan.SetDirection(Vector2.left);
ghostManager.SetLevel(5);
ghostManager.SetKinematic(true);
ghostManager.gameObject.SetActive(true);
blinky.SetElroy(2);
blinky.SetPosition(intermissionScreenElements[1].transform.localPosition);
blinky.SetDirection(Vector2.left);
blinky.SetState(PacManGhostState.Normal);
SetFrozen(false);
break;
case 4:
// Start blinky chasing
blinky.SetActive(true);
break;
case 5:
// Blinky catches on pole
blinky.SetSpeed(1.25f);
break;
case 6:
// Blinky cover about to tear
blinky.SetFrozen(true);
break;
case 7:
// Blinky cover tears
intermission2Pole.SetStrechLevel(PoleStrechLevels.Separated);
break;
case 8:
// Blinky sprite updates with broken cover
blinky.SetSpecialLook(true);
blinky.SetDirection(Vector2.up);
blinky.SetPosition(blinky.GetPosition() + new Vector2(-0.250f, 0f));
break;
case 9:
// Blinky looks at broken cover
blinky.SetDirection(Vector2.down);
break;
case 10:
// Cutscene starts to unload
blinky.SetDirection(Vector2.zero);
break;
case 11:
// End cutscene
SetFrozen(true);
break;
}
}
private void TimeSequenceFinalizeIntermission2()
{
SetIntermissionScreenVisible(false);
soundManager.StopAllSound();
}
private void TimeSequenceFinishedIntermission2()
{
StartTimeSequence(PacManTimeSequence.StartNewLevel);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 902323f14d974674c82c40bb2061609b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,73 @@
using UnityEngine;
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceStepIntermission3(int sequenceProgress)
{
var blinky = ghostManager.Ghosts[0];
switch (sequenceProgress)
{
case 0:
PrepareForCutscene();
// Show just level display
statusDisplay.SetLevelDisplayVisible(true);
break;
case 1:
// Start animation, pacman running and blinky prepared to chase
soundManager.SuppressSound(false);
soundManager.StartIntermissionSound();
pacMan.SetLevel(4);
pacMan.SetPowerPellet(false); // Update speed
pacMan.SetKinematic(true);
pacMan.SetActive(true);
pacMan.SetPosition(intermissionScreenElements[0].transform.localPosition);
pacMan.SetDirection(Vector2.left);
ghostManager.SetLevel(5);
ghostManager.SetKinematic(true);
ghostManager.gameObject.SetActive(true);
blinky.SetElroy(2);
blinky.SetPosition(intermissionScreenElements[1].transform.localPosition);
blinky.SetDirection(Vector2.left);
blinky.SetState(PacManGhostState.Normal);
blinky.SetSpecialLook(true);
SetFrozen(false);
break;
case 2:
// Start blinky chasing
blinky.SetActive(true);
break;
case 3:
// Reached end, freeze
pacMan.SetDirection(Vector2.zero);
blinky.SetDirection(Vector2.zero);
break;
case 4:
// Ghost runs back on screen
blinky.SetPosition(intermissionScreenElements[3].transform.localPosition);
blinky.SetDirection(Vector2.right);
break;
case 5:
// End cutscene
SetFrozen(true);
break;
}
}
private void TimeSequenceFinalizeIntermission3()
{
soundManager.StopAllSound();
}
private void TimeSequenceFinishedIntermission3()
{
StartTimeSequence(PacManTimeSequence.StartNewLevel);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4f4714f9d9e4e8a4682d26d67d5ac4c9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,49 @@
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceStepPacManCaught(int sequenceProgress)
{
switch (sequenceProgress)
{
case 0:
// Freeze (except for the ghost animations)
SetFrozen(true, ghostKeepAnimating: true);
soundManager.StopAllSound();
break;
case 1:
// Hide ghosts, start pacman death animation
SetGhostsActive(false);
pacMan.SetDead(true);
break;
case 2:
// Start playing death sound
soundManager.PlayDeathSound();
break;
case 3:
// Hide pacman
SetPacManActive(false);
break;
}
}
private void TimeSequenceFinishedPacManCaught()
{
PacManTimeSequence nextSequence;
if (gameState == PacManGameState.AttractModeDemo)
{
nextSequence = PacManTimeSequence.AttractScreenWaitToRestart;
}
else if (extraLives > 0)
{
nextSequence = PacManTimeSequence.RestartLevel;
}
else
{
nextSequence = PacManTimeSequence.GameOver;
}
StartTimeSequence(nextSequence);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 44ac2b1481d4fb14fa9ba70526ae9a11
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,48 @@
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceStepRestartLevel(int sequenceProgress)
{
switch (sequenceProgress)
{
case 0:
// Hide playfield and pellets
SetMazeVisible(false);
SetPelletsActive(false);
break;
case 1:
// Make maze visible
RestartLevel();
SetMazeVisible(true);
break;
case 2:
// Take life, show ready, show pellets
DecrementLives();
statusDisplay.SetReadyTextVisible(true);
SetPelletsActive(true);
break;
case 3:
// Show pacman, show ghosts
SetPacManActive(true);
SetGhostsActive(true);
break;
case 4:
// Hide ready
statusDisplay.SetReadyTextVisible(false);
break;
case 5:
break;
}
}
private void TimeSequenceFinalizeRestartLevel()
{
// Unfreeze
SetFrozen(false);
soundManager.SuppressSound(false);
soundManager.StartGhostSound();
soundManager.UpdatePelletCount(pelletCountRemaining);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5afb156778fca6c449652276697f346a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,61 @@
using UnityEngine;
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceStepStartNewGame(int sequenceProgress)
{
switch (sequenceProgress)
{
case 0:
// Prepare new game, hide everything except score bar
gameState = PacManGameState.InGame;
InitializeNewGame();
InitializeLevel();
PrepareForCutscene();
soundManager.SuppressSound(false);
soundManager.PlayGameStartSound();
break;
case 1:
// Show maze, lives indicator, level indicator, player 1 and ready text
SetPelletsActive(true);
SetMazeVisible(true);
statusDisplay.SetExtraLivesDisplayVisible(true);
statusDisplay.SetLevelDisplayVisible(true);
statusDisplay.SetPlayer1TextVisible(true);
statusDisplay.SetReadyTextVisible(true);
statusDisplay.SetLabel1UPTextBlinking(true);
break;
case 2:
// Subtract a life
DecrementLives();
break;
case 3:
// Remove Player 1 text
statusDisplay.SetPlayer1TextVisible(false);
break;
case 4:
// Show ghosts and pacman
SetGhostsActive(true);
SetPacManActive(true);
break;
case 5:
// Remove ready text
statusDisplay.SetReadyTextVisible(false);
break;
case 6:
break;
}
}
private void TimeSequenceFinalizeStartNewGame()
{
// Start game, end sequence
soundManager.StartGhostSound();
SetFrozen(false);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: db81dd1c2ea086643af71ac8484c2fa5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceStepStartNewLevel(int sequenceProgress)
{
switch (sequenceProgress)
{
case 0:
PrepareForCutscene();
// Reset, show maze and score display
InitializeLevel();
SetMazeVisible(true);
statusDisplay.SetScoreDisplayVisible(true);
break;
case 1:
// Increment level, show ready, show pellets, show lives indicators
IncrementLevel();
statusDisplay.SetExtraLivesDisplayVisible(true);
statusDisplay.SetReadyTextVisible(true);
SetPelletsActive(true);
break;
case 2:
// Show pacman, show ghosts
SetPacManActive(true);
SetGhostsActive(true);
break;
case 3:
// Hide ready
statusDisplay.SetReadyTextVisible(false);
break;
case 4:
break;
}
}
private void TimeSequenceFinalizeStartNewLevel()
{
// Unfreeze
SetFrozen(false);
soundManager.SuppressSound(false);
soundManager.StartGhostSound();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7bdc932910f22bf49b3de1b3883359d0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,462 @@
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.SDK3.Data;
namespace Marro.PacManUdon
{
public partial class GameManager
{
// A note about the quality of the code here:
// I intended to write this using proper classes, right until I realized Udon does not support instantiating classes.
// While I'm not a big fan of the partial class solution that I ended up doing (static classes would still be neater, or perhaps separate UdonSharpBehaviour instances),
// I'm not redoing this unless I get instantiatable classes before I wrap up this project.
bool currentlyInTimeSequence;
bool waitingForTimeSequenceFinalize;
bool jumpingToTimeSequence;
PacManTimeSequence currentTimeSequence;
[UdonSynced] float timeSequenceSecondsPassed;
int timeSequenceProgress;
float[] timeSequenceKeyframeTimes;
private void StartTimeSequence(PacManTimeSequence timeSequence)
{
Debug.Log($"StartTimeSequence: {timeSequence}");
if (currentlyInTimeSequence)
{
TimeSequenceEndCurrent();
}
TimeSequencePrepareForStart(timeSequence);
currentlyInTimeSequence = true;
currentTimeSequence = timeSequence;
timeSequenceProgress = 0;
timeSequenceSecondsPassed = 0;
timeSequenceKeyframeTimes = GetTimeSequenceKeyframeTimes(timeSequence);
TimeSequenceProgressToTime(timeSequenceSecondsPassed);
}
private void TimeSequenceEndCurrent()
{
jumpingToTimeSequence = true;
TimeSequenceProgressToTime(100000f);
TryFinalizeTimeSequence();
jumpingToTimeSequence = false;
}
private void TimeSequenceUpdate(float deltaSeconds)
{
if (!currentlyInTimeSequence)
{
return;
}
TimeSequenceProgressToTime(timeSequenceSecondsPassed + deltaSeconds);
}
private void TimeSequenceSkipToNextStep()
{
// Debug.Log($"{gameObject} TimeSequenceSkipToNextStep");
if (timeSequenceProgress < timeSequenceKeyframeTimes.Length)
{
TimeSequenceProgressToTime(timeSequenceKeyframeTimes[timeSequenceProgress]);
}
else
{
Debug.LogWarning($"{gameObject} Tried skipping to next time sequence step when already on last step!");
currentlyInTimeSequence = false;
}
}
private void TimeSequenceProgressToTime(float seconds)
{
timeSequenceSecondsPassed = seconds;
while (timeSequenceSecondsPassed >= timeSequenceKeyframeTimes[timeSequenceProgress])
{
TimeSequenceExecuteStep(currentTimeSequence, timeSequenceProgress);
timeSequenceProgress += 1;
if (timeSequenceProgress >= timeSequenceKeyframeTimes.Length)
{
currentlyInTimeSequence = false;
TimeSequencePrepareForFinish(currentTimeSequence);
break;
}
}
}
private void TimeSequencePrepareForFinish(PacManTimeSequence timeSequence)
{
if (Networking.IsOwner(gameObject))
{
TimeSequenceExecuteFinalize(timeSequence);
if (!jumpingToTimeSequence)
{
TimeSequenceExecuteFinished(timeSequence);
}
}
else
{
waitingForTimeSequenceFinalize = true;
}
}
private void TryFinalizeTimeSequence()
{
if (!waitingForTimeSequenceFinalize)
{
return;
}
TimeSequenceExecuteFinalize(currentTimeSequence);
waitingForTimeSequenceFinalize = false;
}
private void TimeSequenceSyncWithRemote(bool currentlyInTimeSequence, PacManTimeSequence currentTimeSequence, float timeSequenceProgress)
{
// If the remote is in a time sequence but we're not, or we're in a different time sequence, jump to the remote's time sequence.
if (currentlyInTimeSequence && (!this.currentlyInTimeSequence || currentTimeSequence != this.currentTimeSequence))
{
StartTimeSequence(currentTimeSequence);
}
// If we're (now) in a time sequence, jump our progress to match the one on the remote
if (this.currentlyInTimeSequence)
{
TimeSequenceProgressToTime(timeSequenceProgress);
}
// If the remote has finished it's time sequence and we have one waiting to be finalized, we can do so now
if (!currentlyInTimeSequence)
{
TryFinalizeTimeSequence();
}
}
#region Events
public void JumpToTimeSequenceAttractScreenIntroduction()
{
StartTimeSequence(PacManTimeSequence.AttractScreenIntroduction);
}
public void JumpToTimeSequenceAttractScreenDemo()
{
StartTimeSequence(PacManTimeSequence.AttractScreenDemo);
}
public void JumpToTimeSequenceAttractScreenWaitToRestart()
{
StartTimeSequence(PacManTimeSequence.AttractScreenWaitToRestart);
}
public void JumpToTimeSequenceBoardClear()
{
StartTimeSequence(PacManTimeSequence.BoardClear);
}
public void JumpToTimeSequenceGameOver()
{
StartTimeSequence(PacManTimeSequence.GameOver);
}
public void JumpToTimeSequenceGhostCaught()
{
StartTimeSequence(PacManTimeSequence.GhostCaught);
}
public void JumpToTimeSequenceIntermission1()
{
StartTimeSequence(PacManTimeSequence.Intermission1);
}
public void JumpToTimeSequenceIntermission2()
{
StartTimeSequence(PacManTimeSequence.Intermission2);
}
public void JumpToTimeSequenceIntermission3()
{
StartTimeSequence(PacManTimeSequence.Intermission3);
}
public void JumpToTimeSequencePacManCaught()
{
StartTimeSequence(PacManTimeSequence.PacManCaught);
}
public void JumpToTimeSequenceRestartLevel()
{
StartTimeSequence(PacManTimeSequence.RestartLevel);
}
public void JumpToTimeSequenceStartNewGame()
{
StartTimeSequence(PacManTimeSequence.StartNewGame);
}
public void JumpToTimeSequenceStartNewLevel()
{
StartTimeSequence(PacManTimeSequence.StartNewLevel);
}
public void JumpToTimeSequenceWaitForStart()
{
StartTimeSequence(PacManTimeSequence.WaitForStart);
}
public void JumpToTimeSequenceWaitForStartTimeout()
{
StartTimeSequence(PacManTimeSequence.WaitForStartTimeout);
}
#endregion
#region Jump tables
private void TimeSequencePrepareForStart(PacManTimeSequence timeSequence)
{
switch (timeSequence)
{
default:
Debug.LogError($"{gameObject} No time sequence start known for sequence {currentTimeSequence}");
break;
case PacManTimeSequence.AttractScreenIntroduction:
case PacManTimeSequence.AttractScreenDemo:
case PacManTimeSequence.StartNewGame:
case PacManTimeSequence.WaitForStart:
case PacManTimeSequence.StartNewLevel:
case PacManTimeSequence.Intermission1:
case PacManTimeSequence.Intermission2:
case PacManTimeSequence.Intermission3:
case PacManTimeSequence.AttractScreenWaitToRestart:
case PacManTimeSequence.WaitForStartTimeout:
case PacManTimeSequence.GhostCaught:
case PacManTimeSequence.GameOver:
case PacManTimeSequence.PacManCaught:
case PacManTimeSequence.BoardClear:
case PacManTimeSequence.RestartLevel:
// These don't have start logic
break;
}
}
private void TimeSequenceExecuteStep(PacManTimeSequence timeSequence, int sequenceProgress)
{
// Debug.Log($"{gameObject} Triggered time sequence step for sequence {currentTimeSequence} with progress {sequenceProgress}");
switch (timeSequence)
{
default:
Debug.LogError($"{gameObject} No time sequence keyframes known for sequence {currentTimeSequence}");
break;
case PacManTimeSequence.AttractScreenIntroduction:
TimeSequenceStepAttractScreenIntroduction(sequenceProgress);
break;
case PacManTimeSequence.AttractScreenDemo:
TimeSequenceStepAttractScreenDemo(sequenceProgress);
break;
case PacManTimeSequence.WaitForStart:
TimeSequenceStepWaitForStart(sequenceProgress);
break;
case PacManTimeSequence.StartNewGame:
TimeSequenceStepStartNewGame(sequenceProgress);
break;
case PacManTimeSequence.BoardClear:
TimeSequenceStepBoardClear(sequenceProgress);
break;
case PacManTimeSequence.StartNewLevel:
TimeSequenceStepStartNewLevel(sequenceProgress);
break;
case PacManTimeSequence.GhostCaught:
TimeSequenceStepGhostCaught(sequenceProgress);
break;
case PacManTimeSequence.PacManCaught:
TimeSequenceStepPacManCaught(sequenceProgress);
break;
case PacManTimeSequence.RestartLevel:
TimeSequenceStepRestartLevel(sequenceProgress);
break;
case PacManTimeSequence.GameOver:
TimeSequenceStepGameOver(sequenceProgress);
break;
case PacManTimeSequence.Intermission1:
TimeSequenceStepIntermission1(sequenceProgress);
break;
case PacManTimeSequence.Intermission2:
TimeSequenceStepIntermission2(sequenceProgress);
break;
case PacManTimeSequence.Intermission3:
TimeSequenceStepIntermission3(sequenceProgress);
break;
case PacManTimeSequence.AttractScreenWaitToRestart:
case PacManTimeSequence.WaitForStartTimeout:
// These don't have steps
break;
}
}
private void TimeSequenceExecuteFinalize(PacManTimeSequence timeSequence)
{
// Debug.Log($"{gameObject} Triggered time sequence step for sequence {currentTimeSequence} with progress {sequenceProgress}");
switch (timeSequence)
{
default:
Debug.LogError($"{gameObject} No time sequence finalize known for sequence {currentTimeSequence}");
break;
case PacManTimeSequence.AttractScreenIntroduction:
TimeSequenceFinalizeAttractScreenIntroduction();
break;
case PacManTimeSequence.WaitForStart:
TimeSequenceFinalizeWaitForStart();
break;
case PacManTimeSequence.StartNewGame:
TimeSequenceFinalizeStartNewGame();
break;
case PacManTimeSequence.StartNewLevel:
TimeSequenceFinalizeStartNewLevel();
break;
case PacManTimeSequence.GhostCaught:
TimeSequenceFinalizeGhostCaught();
break;
case PacManTimeSequence.RestartLevel:
TimeSequenceFinalizeRestartLevel();
break;
case PacManTimeSequence.Intermission2:
TimeSequenceFinalizeIntermission2();
break;
case PacManTimeSequence.Intermission3:
TimeSequenceFinalizeIntermission3();
break;
case PacManTimeSequence.AttractScreenDemo:
case PacManTimeSequence.WaitForStartTimeout:
case PacManTimeSequence.AttractScreenWaitToRestart:
case PacManTimeSequence.GameOver:
case PacManTimeSequence.Intermission1:
case PacManTimeSequence.PacManCaught:
case PacManTimeSequence.BoardClear:
// These don't have a finalize
break;
}
}
private void TimeSequenceExecuteFinished(PacManTimeSequence timeSequence)
{
// Debug.Log($"{gameObject} Triggered time sequence step for sequence {currentTimeSequence} with progress {sequenceProgress}");
switch (timeSequence)
{
default:
Debug.LogError($"{gameObject} No time sequence finish known for sequence {currentTimeSequence}");
break;
case PacManTimeSequence.AttractScreenIntroduction:
TimeSequenceFinishedAttractScreenIntroduction();
break;
case PacManTimeSequence.AttractScreenDemo:
TimeSequenceFinishedAttractScreenDemo();
break;
case PacManTimeSequence.AttractScreenWaitToRestart:
TimeSequenceFinishedAttractScreenWaitToRestart();
break;
case PacManTimeSequence.WaitForStartTimeout:
TimeSequenceFinishedWaitForStartTimeout();
break;
case PacManTimeSequence.BoardClear:
TimeSequenceFinishedBoardClear();
break;
case PacManTimeSequence.PacManCaught:
TimeSequenceFinishedPacManCaught();
break;
case PacManTimeSequence.GameOver:
TimeSequenceFinishedGameOver();
break;
case PacManTimeSequence.Intermission1:
TimeSequenceFinishedIntermission1();
break;
case PacManTimeSequence.Intermission2:
TimeSequenceFinishedIntermission2();
break;
case PacManTimeSequence.Intermission3:
TimeSequenceFinishedIntermission3();
break;
case PacManTimeSequence.RestartLevel:
case PacManTimeSequence.StartNewLevel:
case PacManTimeSequence.GhostCaught:
case PacManTimeSequence.WaitForStart:
case PacManTimeSequence.StartNewGame:
// These don't have a finished
break;
}
}
private float[] GetTimeSequenceKeyframeTimes(PacManTimeSequence timeSequence)
{
switch (timeSequence)
{
default:
Debug.LogError($"{gameObject} No time sequence keyframe times known for sequence {timeSequence}");
return new float[0];
case PacManTimeSequence.AttractScreenIntroduction:
return DeltaToAbsolute(new float[] { 0, 0.032f, 1f, 1f, .5f, .5f, 1f, .5f, .5f, 1f, .5f, .5f, 1f, .5f, 1f, 1f, 1f,
5f, 0.2f, 2f, 0.91667f, 2f, 0.91667f, 2f, 0.91667f, 2f, 0.91667f });
case PacManTimeSequence.AttractScreenDemo:
return DeltaToAbsolute(new float[] { 0, 0.016f, 0.05f, 0.16f, 0.33f, 1.85f, 54f });
case PacManTimeSequence.AttractScreenWaitToRestart:
return DeltaToAbsolute(new float[] { 0, 2f });
case PacManTimeSequence.WaitForStart:
return DeltaToAbsolute(new float[] { 0, 0.016f });
case PacManTimeSequence.WaitForStartTimeout:
return DeltaToAbsolute(new float[] { 0, 5f });
case PacManTimeSequence.StartNewGame:
return DeltaToAbsolute(new float[] { 0, 0.016f, 2.2f, 0.032f, 0.032f, 1.92f, 0.032f });
case PacManTimeSequence.BoardClear:
return DeltaToAbsolute(new float[] { 0, 2f, 0.016f, 1.6f - 0.016f, 0.016f, 0.032f, 0.3f });
case PacManTimeSequence.StartNewLevel:
return DeltaToAbsolute(new float[] { 0, 0.064f, 0.032f, 1.85f, 0.016f });
case PacManTimeSequence.GhostCaught:
return DeltaToAbsolute(new float[] { 0, 0.91667f });
case PacManTimeSequence.PacManCaught:
return DeltaToAbsolute(new float[] { 0, 1, 0.35f, 2.40f });
case PacManTimeSequence.RestartLevel:
return DeltaToAbsolute(new float[] { 0, 0.016f, 0.064f, 0.032f, 1.85f, 0.016f });
case PacManTimeSequence.GameOver:
return DeltaToAbsolute(new float[] { 0, 1.95f });
case PacManTimeSequence.Intermission1:
return DeltaToAbsolute(new float[] { 0, 0.316f, 0.3f, 3.96f, 2.25f, 3.93f });
case PacManTimeSequence.Intermission2:
return DeltaToAbsolute(new float[] { 0, 0.25f, 0.083f, 0.3f, 1.43f, 2.5f, 1.816f, 1.25f, 0.017f, 1f, 1.966f, 0.033f });
case PacManTimeSequence.Intermission3:
return DeltaToAbsolute(new float[] { 0, 0.316f, 0.7f, 3.35f, 0.83f, 3.67f });
}
}
private static float[] DeltaToAbsolute(float[] delta)
{
if (delta.Length < 1)
{
return new float[0];
}
float[] absolute = new float[delta.Length];
absolute[0] = delta[0];
for (int i = 1; i < delta.Length; i++)
{
absolute[i] = delta[i] + absolute[i - 1];
}
return absolute;
}
#endregion
public int TimeSequenceProgress
{
get => timeSequenceProgress;
}
public float TimeSequenceSecondsPassed
{
get => timeSequenceSecondsPassed;
set => TimeSequenceProgressToTime(value);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 506fd020620e6d24787a909c153b2da5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceStepWaitForStart(int sequenceProgress)
{
switch (sequenceProgress)
{
case 0:
PrepareForCutscene();
SetGameState(PacManGameState.WaitForStart);
soundManager.SuppressSound(false);
soundManager.PlayCoinSound();
break;
case 1:
SetPressStartButtonScreenVisible(true);
break;
}
}
private void TimeSequenceFinalizeWaitForStart()
{
if (playerInput.active == false)
{
StartTimeSequence(PacManTimeSequence.WaitForStartTimeout);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b977750eeccea07469ed2ed566ad0b4c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,13 @@
namespace Marro.PacManUdon
{
public partial class GameManager
{
private void TimeSequenceFinishedWaitForStartTimeout()
{
if (playerInput.active == false)
{
StartAttractMode();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 445b4cd5c436f3645824ef18948c8593
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -6,41 +6,250 @@ using VRC.Udon;
public class SoundManager : UdonSharpBehaviour
{
[SerializeField] private AudioSource audioSourcePlayer;
[SerializeField] private AudioSource audioSourcePacMan;
[SerializeField] private AudioSource audioSourceGhosts;
[SerializeField] private AudioSource audioSourceExtraLife;
[SerializeField] private AudioClip pacStart;
[SerializeField] private AudioClip intermission;
[SerializeField] private AudioClip pacDot1;
[SerializeField] private AudioClip pacDot2;
[SerializeField] private AudioClip pacGhost1;
[SerializeField] private AudioClip pacDie1;
[SerializeField] private AudioClip pacFruit;
[SerializeField] private AudioClip pacCoin;
[SerializeField] private AudioClip pacGhostEat;
[SerializeField] private AudioClip pacGhostBlue;
[SerializeField] private AudioClip pacGhostRetreat;
[SerializeField] private AudioClip pacExtraLife;
private AudioClip nextDotSound;
[SerializeField] private AudioClip siren0;
[SerializeField] private AudioClip siren1;
[SerializeField] private AudioClip siren2;
[SerializeField] private AudioClip siren3;
[SerializeField] private AudioClip siren4;
private AudioClip _nextDotSound;
private bool _ghostRetreating;
private bool _ghostBlue;
private int _ghostSoundLevel;
private bool _currentlyPlayingSiren;
private bool _suppress;
public void Initialize()
{
nextDotSound = pacDot2;
Reset();
}
public void Reset()
{
StopAllSound();
_nextDotSound = pacDot2;
_ghostRetreating = false;
_ghostBlue = false;
_ghostSoundLevel = 0;
_currentlyPlayingSiren = false;
_suppress = true;
}
public void SuppressSound(bool suppress)
{
_suppress = suppress;
if (suppress)
{
StopAllSound();
}
}
public void PlayGameStartSound()
{
PlaySound(audioSourcePlayer, pacStart);
PlaySound(audioSourcePacMan, pacStart);
}
public void StartIntermissionSound()
{
PlaySound(audioSourcePacMan, intermission, true);
}
public void PlayPelletSound()
{
PlaySound(audioSourcePlayer, nextDotSound);
nextDotSound = nextDotSound == pacDot1 ? pacDot2 : pacDot1;
PlaySound(audioSourcePacMan, _nextDotSound);
_nextDotSound = _nextDotSound == pacDot1 ? pacDot2 : pacDot1;
}
public void PlayDeathSound()
{
PlaySound(audioSourcePacMan, pacDie1);
}
public void PlayFruitSound()
{
PlaySound(audioSourcePacMan, pacFruit);
}
public void PlayCoinSound()
{
PlaySound(audioSourcePacMan, pacCoin);
}
public void PlayGhostEatSound()
{
PlaySound(audioSourcePacMan, pacGhostEat);
}
public void PlayExtraLifeSound()
{
PlaySound(audioSourceExtraLife, pacExtraLife);
}
public void StartGhostSound()
{
PlaySound(audioSourceGhosts, pacGhost1, true);
UpdateGhostSound();
}
public void SetGhostBlue(bool isBlue)
{
_ghostBlue = isBlue;
UpdateGhostSound();
}
public void SetGhostRetreat(bool isRetreating)
{
_ghostRetreating = isRetreating;
UpdateGhostSound();
}
public void StopAllSound()
{
audioSourcePacMan.Stop();
audioSourceGhosts.Stop();
// audioSourceExtraLife is not stopped on purpose, this sound is never interrupted
}
public void UpdatePelletCount(int pelletCount)
{
int level = 0;
if (pelletCount < 16)
{
level = 4;
}
else if (pelletCount < 32)
{
level = 3;
}
else if (pelletCount < 64)
{
level = 2;
}
else if (pelletCount < 128)
{
level = 1;
}
// Debug.Log($"UpdatePelletCount: {pelletCount}, level: {level}");
if (_ghostSoundLevel >= level)
{
return;
}
_ghostSoundLevel = level;
UpdateGhostSound();
}
private void PlaySound(AudioSource audioSource, AudioClip audioClip, bool loop = false)
{
// Debug.Log($"PlaySound, audioSource: {audioSource}, audioClip: {audioClip}, loop: {loop}, suppress: {_suppress}");
if (_suppress)
{
return;
}
if (loop && audioSource.clip == audioClip && audioSource.isPlaying)
{
// Don't restart a looping sound
return;
}
audioSource.clip = audioClip;
audioSource.Play();
audioSource.loop = loop;
}
private void SwitchSound(AudioSource audioSource, AudioClip audioClip, bool loop)
{
if (_suppress)
{
return;
}
if (!audioSource.isPlaying || audioSource.clip == null)
{
PlaySound(audioSource, audioClip, loop);
}
if (audioSource.clip == audioClip)
{
// No need to switch
return;
}
var newTimeSamples = (int)(audioSource.timeSamples / (double)audioSource.clip.samples * audioClip.samples);
audioSource.clip = audioClip;
audioSource.timeSamples = newTimeSamples;
audioSource.Play();
}
private void UpdateGhostSound()
{
if (_ghostRetreating)
{
PlaySound(audioSourceGhosts, pacGhostRetreat, true);
_currentlyPlayingSiren = false;
return;
}
if (_ghostBlue)
{
PlaySound(audioSourceGhosts, pacGhostBlue, true);
_currentlyPlayingSiren = false;
return;
}
var currentGhostLevelSound = GetSoundForGhostLevel(_ghostSoundLevel);
if (_currentlyPlayingSiren)
{
SwitchSound(audioSourceGhosts, currentGhostLevelSound, true);
}
else
{
PlaySound(audioSourceGhosts, currentGhostLevelSound, true);
}
_currentlyPlayingSiren = true;
}
private AudioClip GetSoundForGhostLevel(int ghostLevel)
{
switch (ghostLevel)
{
case 1:
return siren1;
case 2:
return siren2;
case 3:
return siren3;
case 4:
return siren4;
default:
return siren0;
};
}
}

View File

@@ -44,7 +44,7 @@
{
extraLifeIndicators[i - 1] = extraLifeIndicatorTransforms[i].gameObject;
}
Debug.Log($"{gameObject} extraLifeIndicators.Length: {extraLifeIndicators.Length}");
// Debug.Log($"{gameObject} extraLifeIndicators.Length: {extraLifeIndicators.Length}");
}

View File

@@ -0,0 +1,15 @@
using System.Collections;
using UdonSharp;
using UnityEngine;
namespace Marro.PacManUdon
{
public abstract class SyncedObject : UdonSharpBehaviour
{
public long LastUpdateTicks { get; set; }
public float Dt { get; set; }
public abstract void FixedUpdate();
public abstract void AppendSyncedData(byte[][] data, ref int index, NetworkEventType eventType);
public abstract bool SetSyncedData(byte[] data, ref int index, NetworkEventType eventType);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d09fe6fd5a83df9468f5ffcb43d73af3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

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