diff --git a/Assets/Art/Sprites/Spritesheets/Quarry/Placeholders/TennisBall.png b/Assets/Art/Sprites/Spritesheets/Quarry/Placeholders/TennisBall.png new file mode 100644 index 00000000..5b1b8063 Binary files /dev/null and b/Assets/Art/Sprites/Spritesheets/Quarry/Placeholders/TennisBall.png differ diff --git a/Assets/Art/Sprites/Spritesheets/Quarry/Placeholders/TennisBall.png.meta b/Assets/Art/Sprites/Spritesheets/Quarry/Placeholders/TennisBall.png.meta new file mode 100644 index 00000000..720b5e54 --- /dev/null +++ b/Assets/Art/Sprites/Spritesheets/Quarry/Placeholders/TennisBall.png.meta @@ -0,0 +1,195 @@ +fileFormatVersion: 2 +guid: 44a64b7a80921694790236bab7765357 +TextureImporter: + internalIDToNameTable: + - first: + 213: -8897872742393391051 + second: TennisBall_0 + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 2 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: iOS + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: WebGL + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: WindowsStoreApps + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: + - serializedVersion: 2 + name: TennisBall_0 + rect: + serializedVersion: 2 + x: 21 + y: 29 + width: 219 + height: 190 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + customData: + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 538d20d32e7648480800000000000000 + internalID: -8897872742393391051 + vertices: [] + indices: + edges: [] + weights: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: + TennisBall_0: -8897872742393391051 + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/InteractableEditor.cs b/Assets/Editor/InteractableEditor.cs new file mode 100644 index 00000000..be98db98 --- /dev/null +++ b/Assets/Editor/InteractableEditor.cs @@ -0,0 +1,127 @@ +using UnityEngine; +using UnityEditor; + +namespace Interactions +{ + [CustomEditor(typeof(Interactable))] + public class InteractableEditor : UnityEditor.Editor + { + SerializedProperty isOneTimeProp; + SerializedProperty cooldownProp; + SerializedProperty characterToInteractProp; + SerializedProperty interactionStartedProp; + SerializedProperty interactionInterruptedProp; + SerializedProperty characterArrivedProp; + SerializedProperty interactionCompleteProp; + + private void OnEnable() + { + isOneTimeProp = serializedObject.FindProperty("isOneTime"); + cooldownProp = serializedObject.FindProperty("cooldown"); + characterToInteractProp = serializedObject.FindProperty("characterToInteract"); + interactionStartedProp = serializedObject.FindProperty("interactionStarted"); + interactionInterruptedProp = serializedObject.FindProperty("interactionInterrupted"); + characterArrivedProp = serializedObject.FindProperty("characterArrived"); + interactionCompleteProp = serializedObject.FindProperty("interactionComplete"); + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + EditorGUILayout.LabelField("Interaction Settings", EditorStyles.boldLabel); + EditorGUILayout.PropertyField(isOneTimeProp); + EditorGUILayout.PropertyField(cooldownProp); + EditorGUILayout.PropertyField(characterToInteractProp); + + // Add the buttons for creating move targets + EditorGUILayout.Space(10); + EditorGUILayout.LabelField("Character Move Targets", EditorStyles.boldLabel); + + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Add Trafalgar Target")) + { + CreateMoveTarget(CharacterToInteract.Trafalgar); + } + if (GUILayout.Button("Add Pulver Target")) + { + CreateMoveTarget(CharacterToInteract.Pulver); + } + EditorGUILayout.EndHorizontal(); + + // Add a button for creating a "Both" target + if (GUILayout.Button("Add Both Characters Target")) + { + CreateMoveTarget(CharacterToInteract.Both); + } + + // Display character target counts + Interactable interactable = (Interactable)target; + CharacterMoveToTarget[] moveTargets = interactable.GetComponentsInChildren(); + int trafalgarTargets = 0; + int pulverTargets = 0; + int bothTargets = 0; + + foreach (var target in moveTargets) + { + if (target.characterType == CharacterToInteract.Trafalgar) + trafalgarTargets++; + else if (target.characterType == CharacterToInteract.Pulver) + pulverTargets++; + else if (target.characterType == CharacterToInteract.Both) + bothTargets++; + } + + EditorGUILayout.LabelField($"Trafalgar Targets: {trafalgarTargets}, Pulver Targets: {pulverTargets}, Both Targets: {bothTargets}"); + + if (trafalgarTargets > 1 || pulverTargets > 1 || bothTargets > 1 || + (bothTargets > 0 && (trafalgarTargets > 0 || pulverTargets > 0))) + { + EditorGUILayout.HelpBox("Warning: Multiple move targets found that may conflict. Priority order: Both > Character-specific targets.", MessageType.Warning); + } + + EditorGUILayout.Space(10); + EditorGUILayout.LabelField("Interaction Events", EditorStyles.boldLabel); + EditorGUILayout.PropertyField(interactionStartedProp); + EditorGUILayout.PropertyField(interactionInterruptedProp); + EditorGUILayout.PropertyField(characterArrivedProp); + EditorGUILayout.PropertyField(interactionCompleteProp); + + serializedObject.ApplyModifiedProperties(); + } + + private void CreateMoveTarget(CharacterToInteract characterType) + { + Interactable interactable = (Interactable)target; + + // Create a new GameObject + GameObject targetObj = new GameObject($"{characterType}MoveTarget"); + + // Set parent + targetObj.transform.SetParent(interactable.transform); + targetObj.transform.localPosition = Vector3.zero; // Start at the same position as the interactable + + // Add CharacterMoveToTarget component + CharacterMoveToTarget moveTarget = targetObj.AddComponent(); + moveTarget.characterType = characterType; + + // Position it based on character type (offset for better visibility) + switch (characterType) + { + case CharacterToInteract.Trafalgar: + moveTarget.positionOffset = new Vector3(1.0f, 0, 0); + break; + case CharacterToInteract.Pulver: + moveTarget.positionOffset = new Vector3(0, 0, 1.0f); + break; + case CharacterToInteract.Both: + moveTarget.positionOffset = new Vector3(0.7f, 0, 0.7f); + break; + } + + // Select the newly created object + Selection.activeGameObject = targetObj; + Undo.RegisterCreatedObjectUndo(targetObj, $"Create {characterType} Move Target"); + } + } +} diff --git a/Assets/Editor/InteractableEditor.cs.meta b/Assets/Editor/InteractableEditor.cs.meta new file mode 100644 index 00000000..e09a0d68 --- /dev/null +++ b/Assets/Editor/InteractableEditor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e2011e96b1b84886825d0509dd0a5cee +timeCreated: 1759744192 \ No newline at end of file diff --git a/Assets/Editor/InteractionTimelineActionEditor.cs b/Assets/Editor/InteractionTimelineActionEditor.cs new file mode 100644 index 00000000..1956082f --- /dev/null +++ b/Assets/Editor/InteractionTimelineActionEditor.cs @@ -0,0 +1,184 @@ +using UnityEngine; +using UnityEditor; +using UnityEditor.Playables; +using UnityEngine.Playables; + +namespace Interactions +{ + [CustomEditor(typeof(InteractionTimelineAction))] + public class InteractionTimelineActionEditor : UnityEditor.Editor + { + private SerializedProperty respondToEventsProp; + private SerializedProperty pauseInteractionFlowProp; + private SerializedProperty playableDirectorProp; + private SerializedProperty timelineMappingsProp; + + private void OnEnable() + { + respondToEventsProp = serializedObject.FindProperty("respondToEvents"); + pauseInteractionFlowProp = serializedObject.FindProperty("pauseInteractionFlow"); + playableDirectorProp = serializedObject.FindProperty("playableDirector"); + timelineMappingsProp = serializedObject.FindProperty("timelineMappings"); + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + // Basic properties from the base class + EditorGUILayout.LabelField("Basic Settings", EditorStyles.boldLabel); + + // Show the pause interaction flow property + EditorGUILayout.PropertyField(pauseInteractionFlowProp, new GUIContent("Pause Interaction Flow", + "If true, the interaction will wait for the timeline to complete before proceeding")); + + // Show the respondToEvents list + EditorGUILayout.PropertyField(respondToEventsProp, new GUIContent("Respond To Events", + "Select which interaction events this timeline action should respond to"), true); + + // Show the playable director reference + EditorGUILayout.PropertyField(playableDirectorProp, new GUIContent("Playable Director", + "The director component that will play the timeline. Auto-assigned if not specified.")); + + // Show the timeline mappings + EditorGUILayout.Space(10); + EditorGUILayout.LabelField("Timeline Mappings", EditorStyles.boldLabel); + + if (timelineMappingsProp.arraySize == 0) + { + EditorGUILayout.HelpBox("No timeline mappings added yet. Add one to assign timeline assets to specific interaction events.", MessageType.Info); + } + + EditorGUILayout.PropertyField(timelineMappingsProp, new GUIContent("Timeline Mappings"), true); + + // Add buttons for quickly adding timeline mappings for common events + EditorGUILayout.Space(10); + EditorGUILayout.LabelField("Quick Add Mappings", EditorStyles.boldLabel); + + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Add Player Arrival")) + { + AddTimelineMapping(InteractionEventType.PlayerArrived); + } + if (GUILayout.Button("Add Interacting Character")) + { + AddTimelineMapping(InteractionEventType.InteractingCharacterArrived); + } + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Add Interaction Started")) + { + AddTimelineMapping(InteractionEventType.InteractionStarted); + } + if (GUILayout.Button("Add Interaction Complete")) + { + AddTimelineMapping(InteractionEventType.InteractionComplete); + } + EditorGUILayout.EndHorizontal(); + + // Check for configuration issues + InteractionTimelineAction timelineAction = (InteractionTimelineAction)target; + ValidateConfiguration(timelineAction); + + serializedObject.ApplyModifiedProperties(); + } + + private void AddTimelineMapping(InteractionEventType eventType) + { + int index = timelineMappingsProp.arraySize; + timelineMappingsProp.InsertArrayElementAtIndex(index); + SerializedProperty newElement = timelineMappingsProp.GetArrayElementAtIndex(index); + + // Set default values + newElement.FindPropertyRelative("eventType").enumValueIndex = (int)eventType; + + // Create a default array with one empty slot for the timeline + SerializedProperty timelinesArray = newElement.FindPropertyRelative("timelines"); + timelinesArray.ClearArray(); + timelinesArray.InsertArrayElementAtIndex(0); + timelinesArray.GetArrayElementAtIndex(0).objectReferenceValue = null; + + // Set default binding values + newElement.FindPropertyRelative("bindPlayerCharacter").boolValue = false; + newElement.FindPropertyRelative("bindPulverCharacter").boolValue = false; + newElement.FindPropertyRelative("playerTrackName").stringValue = "Player"; + newElement.FindPropertyRelative("pulverTrackName").stringValue = "Pulver"; + newElement.FindPropertyRelative("timeoutSeconds").floatValue = 30f; + newElement.FindPropertyRelative("loopLast").boolValue = false; + newElement.FindPropertyRelative("loopAll").boolValue = false; + + // Also add the event to the respondToEvents list if it's not already there + bool found = false; + for (int i = 0; i < respondToEventsProp.arraySize; i++) + { + if (respondToEventsProp.GetArrayElementAtIndex(i).enumValueIndex == (int)eventType) + { + found = true; + break; + } + } + + if (!found) + { + int responseIndex = respondToEventsProp.arraySize; + respondToEventsProp.InsertArrayElementAtIndex(responseIndex); + respondToEventsProp.GetArrayElementAtIndex(responseIndex).enumValueIndex = (int)eventType; + } + } + + private void ValidateConfiguration(InteractionTimelineAction timelineAction) + { + // Check if we have a PlayableDirector component + PlayableDirector director = timelineAction.GetComponent(); + if (director == null) + { + EditorGUILayout.HelpBox("This GameObject is missing a PlayableDirector component, which is required for timeline playback.", MessageType.Error); + } + + // Check if we have mappings but no events to respond to + if (timelineMappingsProp.arraySize > 0 && respondToEventsProp.arraySize == 0) + { + EditorGUILayout.HelpBox("You have timeline mappings but no events to respond to. Add events to the 'Respond To Events' list.", MessageType.Warning); + } + + // Check if we have events to respond to but no mappings for them + bool hasUnmappedEvents = false; + for (int i = 0; i < respondToEventsProp.arraySize; i++) + { + InteractionEventType eventType = (InteractionEventType)respondToEventsProp.GetArrayElementAtIndex(i).enumValueIndex; + bool found = false; + + for (int j = 0; j < timelineMappingsProp.arraySize; j++) + { + SerializedProperty mappingProp = timelineMappingsProp.GetArrayElementAtIndex(j); + InteractionEventType mappingEventType = (InteractionEventType)mappingProp.FindPropertyRelative("eventType").enumValueIndex; + + if (mappingEventType == eventType) + { + found = true; + + // Check if the mapping has timelines assigned + SerializedProperty timelinesArray = mappingProp.FindPropertyRelative("timelines"); + if (timelinesArray.arraySize == 0 || timelinesArray.GetArrayElementAtIndex(0).objectReferenceValue == null) + { + EditorGUILayout.HelpBox($"The mapping for {eventType} has no timeline assets assigned.", MessageType.Warning); + } + break; + } + } + + if (!found) + { + hasUnmappedEvents = true; + break; + } + } + + if (hasUnmappedEvents) + { + EditorGUILayout.HelpBox("Some events in 'Respond To Events' have no timeline mapping.", MessageType.Warning); + } + } + } +} diff --git a/Assets/Editor/InteractionTimelineActionEditor.cs.meta b/Assets/Editor/InteractionTimelineActionEditor.cs.meta new file mode 100644 index 00000000..b3160fff --- /dev/null +++ b/Assets/Editor/InteractionTimelineActionEditor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6ab56ee48f1445529a62d30c1985f059 +timeCreated: 1759746824 \ No newline at end of file diff --git a/Assets/Editor/TimelineEventMappingDrawer.cs b/Assets/Editor/TimelineEventMappingDrawer.cs new file mode 100644 index 00000000..53de41da --- /dev/null +++ b/Assets/Editor/TimelineEventMappingDrawer.cs @@ -0,0 +1,48 @@ +using UnityEngine; +using UnityEditor; +using Interactions; +using System; + +[CustomPropertyDrawer(typeof(InteractionTimelineAction.TimelineEventMapping))] +public class TimelineEventMappingDrawer : PropertyDrawer +{ + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + // Use default property drawer, but initialize values if needed + InitializeDefaultValues(property); + EditorGUI.PropertyField(position, property, label, true); + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + return EditorGUI.GetPropertyHeight(property, label, true); + } + + // Called when property is created to initialize default values + private void InitializeDefaultValues(SerializedProperty property) + { + // Check if this is a new/empty property that needs initialization + SerializedProperty timelinesArray = property.FindPropertyRelative("timelines"); + if (timelinesArray != null && timelinesArray.arraySize == 0) + { + // This appears to be a new property, so initialize default values + + // Initialize timelines array with one empty element + timelinesArray.ClearArray(); + timelinesArray.InsertArrayElementAtIndex(0); + timelinesArray.GetArrayElementAtIndex(0).objectReferenceValue = null; + + // Set default binding values + property.FindPropertyRelative("bindPlayerCharacter").boolValue = true; + property.FindPropertyRelative("bindPulverCharacter").boolValue = true; + property.FindPropertyRelative("playerTrackName").stringValue = "Player"; + property.FindPropertyRelative("pulverTrackName").stringValue = "Pulver"; + property.FindPropertyRelative("timeoutSeconds").floatValue = 30f; + property.FindPropertyRelative("loopLast").boolValue = false; + property.FindPropertyRelative("loopAll").boolValue = false; + + // Make sure to apply modifications + property.serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Assets/Editor/TimelineEventMappingDrawer.cs.meta b/Assets/Editor/TimelineEventMappingDrawer.cs.meta new file mode 100644 index 00000000..3fe1888f --- /dev/null +++ b/Assets/Editor/TimelineEventMappingDrawer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c5a227e33ab14a0f86bf391016c57b00 +timeCreated: 1759756346 \ No newline at end of file diff --git a/Assets/Playables/PulverCucumberSmack.playable b/Assets/Playables/PulverCucumberSmack.playable new file mode 100644 index 00000000..9a730e26 --- /dev/null +++ b/Assets/Playables/PulverCucumberSmack.playable @@ -0,0 +1,854 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-1185821560092742700 +MonoBehaviour: + m_ObjectHideFlags: 1 + 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: d21dcc2386d650c4597f3633c75a1f98, type: 3} + m_Name: Pulver + m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.AnimationTrack + m_Version: 3 + m_AnimClip: {fileID: 0} + m_Locked: 0 + m_Muted: 0 + m_CustomPlayableFullTypename: + m_Curves: {fileID: 0} + m_Parent: {fileID: 11400000} + m_Children: [] + m_Clips: + - m_Version: 1 + m_Start: 0 + m_ClipIn: 0 + m_Asset: {fileID: -744416834715362379} + m_Duration: 0.8333333333333334 + m_TimeScale: 1 + m_ParentTrack: {fileID: -1185821560092742700} + m_EaseInDuration: 0 + m_EaseOutDuration: 0 + m_BlendInDuration: -1 + m_BlendOutDuration: -1 + m_MixInCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_MixOutCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_BlendInCurveMode: 0 + m_BlendOutCurveMode: 0 + m_ExposedParameterNames: [] + m_AnimationCurves: {fileID: 0} + m_Recordable: 0 + m_PostExtrapolationMode: 1 + m_PreExtrapolationMode: 1 + m_PostExtrapolationTime: Infinity + m_PreExtrapolationTime: 0 + m_DisplayName: Pulver_Cucumbatacc + m_Markers: + m_Objects: [] + m_InfiniteClipPreExtrapolation: 0 + m_InfiniteClipPostExtrapolation: 0 + m_InfiniteClipOffsetPosition: {x: 0, y: 0, z: 0} + m_InfiniteClipOffsetEulerAngles: {x: 0, y: 0, z: 0} + m_InfiniteClipTimeOffset: 0 + m_InfiniteClipRemoveOffset: 0 + m_InfiniteClipApplyFootIK: 1 + mInfiniteClipLoop: 0 + m_MatchTargetFields: 63 + m_Position: {x: 0, y: 0, z: 0} + m_EulerAngles: {x: 0, y: 0, z: 0} + m_AvatarMask: {fileID: 0} + m_ApplyAvatarMask: 1 + m_TrackOffset: 0 + m_InfiniteClip: {fileID: 0} + m_OpenClipOffsetRotation: {x: 0, y: 0, z: 0, w: 1} + m_Rotation: {x: 0, y: 0, z: 0, w: 1} + m_ApplyOffsets: 0 +--- !u!114 &-744416834715362379 +MonoBehaviour: + m_ObjectHideFlags: 1 + 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: 030f85c3f73729f4f976f66ffb23b875, type: 3} + m_Name: AnimationPlayableAsset + m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.AnimationPlayableAsset + m_Clip: {fileID: 7400000, guid: 09d7dd4e84cbed54bb4ca4e63ad0c6fa, type: 2} + m_Position: {x: 0, y: 0, z: 0} + m_EulerAngles: {x: 0, y: 0, z: 0} + m_UseTrackMatchFields: 1 + m_MatchTargetFields: 63 + m_RemoveStartOffset: 1 + m_ApplyFootIK: 1 + m_Loop: 0 + m_Version: 1 + m_Rotation: {x: 0, y: 0, z: 0, w: 1} +--- !u!114 &-461426874464204690 +MonoBehaviour: + m_ObjectHideFlags: 1 + 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: 2a16748d9461eae46a725db9776d5390, type: 3} + m_Name: Markers + m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.MarkerTrack + m_Version: 3 + m_AnimClip: {fileID: 0} + m_Locked: 0 + m_Muted: 0 + m_CustomPlayableFullTypename: + m_Curves: {fileID: 0} + m_Parent: {fileID: 11400000} + m_Children: [] + m_Clips: [] + m_Markers: + m_Objects: [] +--- !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: bfda56da833e2384a9677cd3c976a436, type: 3} + m_Name: PulverCucumberSmack + m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.TimelineAsset + m_Version: 0 + m_Tracks: + - {fileID: -1185821560092742700} + - {fileID: 1662278050270751211} + m_FixedDuration: 0 + m_EditorSettings: + m_Framerate: 60 + m_ScenePreview: 1 + m_DurationMode: 0 + m_MarkerTrack: {fileID: -461426874464204690} +--- !u!114 &1662278050270751211 +MonoBehaviour: + m_ObjectHideFlags: 1 + 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: d21dcc2386d650c4597f3633c75a1f98, type: 3} + m_Name: Animation Track (2) + m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.AnimationTrack + m_Version: 3 + m_AnimClip: {fileID: 0} + m_Locked: 0 + m_Muted: 0 + m_CustomPlayableFullTypename: + m_Curves: {fileID: 0} + m_Parent: {fileID: 11400000} + m_Children: [] + m_Clips: [] + m_Markers: + m_Objects: [] + m_InfiniteClipPreExtrapolation: 1 + m_InfiniteClipPostExtrapolation: 1 + m_InfiniteClipOffsetPosition: {x: -36.32, y: 104.64, z: 0} + m_InfiniteClipOffsetEulerAngles: {x: -0, y: 0, z: 0} + m_InfiniteClipTimeOffset: 0 + m_InfiniteClipRemoveOffset: 0 + m_InfiniteClipApplyFootIK: 1 + mInfiniteClipLoop: 0 + m_MatchTargetFields: 63 + m_Position: {x: 0, y: 0, z: 0} + m_EulerAngles: {x: 0, y: 0, z: 0} + m_AvatarMask: {fileID: 0} + m_ApplyAvatarMask: 1 + m_TrackOffset: 0 + m_InfiniteClip: {fileID: 7057870124182637150} + m_OpenClipOffsetRotation: {x: 0, y: 0, z: 0, w: 1} + m_Rotation: {x: 0, y: 0, z: 0, w: 1} + m_ApplyOffsets: 0 +--- !u!74 &7057870124182637150 +AnimationClip: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Recorded (1) + serializedVersion: 7 + m_Legacy: 0 + m_Compressed: 0 + m_UseHighQualityCurve: 1 + m_RotationCurves: [] + m_CompressedRotationCurves: [] + m_EulerCurves: [] + m_PositionCurves: + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: {x: 0, y: -0.40000153, z: 0} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 0.23333333 + value: {x: 0, y: -0.40000153, z: 0} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 0.35 + value: {x: -5.6000023, y: 3, z: 0} + inSlope: {x: -48.00001, y: 0, z: 0} + outSlope: {x: -48.00001, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 0.45 + value: {x: -10.400002, y: -1.199997, z: 0} + inSlope: {x: -25.999998, y: -55.99996, z: 0} + outSlope: {x: -25.999998, y: -55.99996, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 0.65 + value: {x: -13.400002, y: -14.599998, z: 0} + inSlope: {x: -5.6470795, y: 0, z: 0} + outSlope: {x: -5.6470795, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 0.73333335 + value: {x: -13.800003, y: -13.599998, z: 0} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 0.8333333 + value: {x: -13.800003, y: -14.799995, z: 0} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 0.96666664 + value: {x: -14.800003, y: -14.199997, z: 0} + inSlope: {x: -6.3999925, y: 0, z: 0} + outSlope: {x: -6.3999925, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 1.0833334 + value: {x: -15.400002, y: -15.199997, z: 0} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + path: + m_ScaleCurves: [] + m_FloatCurves: + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1.1666666 + value: 1 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_Enabled + path: + classID: 114 + script: {fileID: 11500000, guid: 73d6494a73174ffabc6a7d3089d51e73, type: 3} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1.1666666 + value: 1 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_Enabled + path: + classID: 114 + script: {fileID: 11500000, guid: 7846448751da4bdbaaa5cb87890dca42, type: 3} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1.1666666 + value: 1 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_Enabled + path: + classID: 114 + script: {fileID: 11500000, guid: 1101f6c4eb04423b89dc78dc7c9f1aae, type: 3} + flags: 0 + m_PPtrCurves: [] + 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: 1 + script: {fileID: 0} + typeID: 4 + customType: 0 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + - serializedVersion: 2 + path: 0 + attribute: 3305885265 + script: {fileID: 11500000, guid: 73d6494a73174ffabc6a7d3089d51e73, type: 3} + typeID: 114 + customType: 24 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + - serializedVersion: 2 + path: 0 + attribute: 3305885265 + script: {fileID: 11500000, guid: 7846448751da4bdbaaa5cb87890dca42, type: 3} + typeID: 114 + customType: 24 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + - serializedVersion: 2 + path: 0 + attribute: 3305885265 + script: {fileID: 11500000, guid: 1101f6c4eb04423b89dc78dc7c9f1aae, type: 3} + typeID: 114 + customType: 24 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + pptrCurveMapping: [] + m_AnimationClipSettings: + serializedVersion: 2 + m_AdditiveReferencePoseClip: {fileID: 0} + m_AdditiveReferencePoseTime: 0 + m_StartTime: 0 + m_StopTime: 1.1666666 + 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: + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.23333333 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.35 + value: -5.6000023 + inSlope: -48.00001 + outSlope: -48.00001 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.45 + value: -10.400002 + inSlope: -25.999998 + outSlope: -25.999998 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.65 + value: -13.400002 + inSlope: -5.6470795 + outSlope: -5.6470795 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.73333335 + value: -13.800003 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.8333333 + value: -13.800003 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.96666664 + value: -14.800003 + inSlope: -6.3999925 + outSlope: -6.3999925 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1.0833334 + value: -15.400002 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.x + path: + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: -0.40000153 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.23333333 + value: -0.40000153 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.35 + value: 3 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.45 + value: -1.199997 + inSlope: -55.99996 + outSlope: -55.99996 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.65 + value: -14.599998 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.73333335 + value: -13.599998 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.8333333 + value: -14.799995 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.96666664 + value: -14.199997 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1.0833334 + value: -15.199997 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.y + path: + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.23333333 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.35 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.45 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.65 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.73333335 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.8333333 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.96666664 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1.0833334 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.z + path: + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1.1666666 + value: 1 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_Enabled + path: + classID: 114 + script: {fileID: 11500000, guid: 73d6494a73174ffabc6a7d3089d51e73, type: 3} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1.1666666 + value: 1 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_Enabled + path: + classID: 114 + script: {fileID: 11500000, guid: 7846448751da4bdbaaa5cb87890dca42, type: 3} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1.1666666 + value: 1 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_Enabled + path: + classID: 114 + script: {fileID: 11500000, guid: 1101f6c4eb04423b89dc78dc7c9f1aae, type: 3} + flags: 0 + m_EulerEditorCurves: [] + m_HasGenericRootTransform: 1 + m_HasMotionFloatCurves: 0 + m_Events: [] diff --git a/Assets/Playables/PulverCucumberSmack.playable.meta b/Assets/Playables/PulverCucumberSmack.playable.meta new file mode 100644 index 00000000..e188c606 --- /dev/null +++ b/Assets/Playables/PulverCucumberSmack.playable.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 27f5954bda3e24b48b33e5a6605eb33f +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Playables/PulverCucumberSmack2.playable b/Assets/Playables/PulverCucumberSmack2.playable new file mode 100644 index 00000000..aa6828cd --- /dev/null +++ b/Assets/Playables/PulverCucumberSmack2.playable @@ -0,0 +1,811 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-7584736085941489071 +MonoBehaviour: + m_ObjectHideFlags: 1 + 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: d21dcc2386d650c4597f3633c75a1f98, type: 3} + m_Name: Animation Track + m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.AnimationTrack + m_Version: 3 + m_AnimClip: {fileID: 0} + m_Locked: 0 + m_Muted: 0 + m_CustomPlayableFullTypename: + m_Curves: {fileID: 0} + m_Parent: {fileID: 11400000} + m_Children: [] + m_Clips: [] + m_Markers: + m_Objects: [] + m_InfiniteClipPreExtrapolation: 0 + m_InfiniteClipPostExtrapolation: 0 + m_InfiniteClipOffsetPosition: {x: 0, y: 0, z: 0} + m_InfiniteClipOffsetEulerAngles: {x: 0, y: 0, z: 0} + m_InfiniteClipTimeOffset: 0 + m_InfiniteClipRemoveOffset: 0 + m_InfiniteClipApplyFootIK: 1 + mInfiniteClipLoop: 0 + m_MatchTargetFields: 63 + m_Position: {x: 0, y: 0, z: 0} + m_EulerAngles: {x: 0, y: 0, z: 0} + m_AvatarMask: {fileID: 0} + m_ApplyAvatarMask: 1 + m_TrackOffset: 0 + m_InfiniteClip: {fileID: 0} + m_OpenClipOffsetRotation: {x: 0, y: 0, z: 0, w: 1} + m_Rotation: {x: 0, y: 0, z: 0, w: 1} + m_ApplyOffsets: 0 +--- !u!114 &-7231857257271738743 +MonoBehaviour: + m_ObjectHideFlags: 1 + 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: d21dcc2386d650c4597f3633c75a1f98, type: 3} + m_Name: Animation Track (2) + m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.AnimationTrack + m_Version: 3 + m_AnimClip: {fileID: 0} + m_Locked: 0 + m_Muted: 0 + m_CustomPlayableFullTypename: + m_Curves: {fileID: 0} + m_Parent: {fileID: 11400000} + m_Children: [] + m_Clips: [] + m_Markers: + m_Objects: [] + m_InfiniteClipPreExtrapolation: 1 + m_InfiniteClipPostExtrapolation: 1 + m_InfiniteClipOffsetPosition: {x: -3.4, y: 0, z: 0} + m_InfiniteClipOffsetEulerAngles: {x: -0, y: 0, z: 0} + m_InfiniteClipTimeOffset: 0 + m_InfiniteClipRemoveOffset: 0 + m_InfiniteClipApplyFootIK: 1 + mInfiniteClipLoop: 0 + m_MatchTargetFields: 63 + m_Position: {x: 0, y: 0, z: 0} + m_EulerAngles: {x: 0, y: 0, z: 0} + m_AvatarMask: {fileID: 0} + m_ApplyAvatarMask: 1 + m_TrackOffset: 0 + m_InfiniteClip: {fileID: -6922421277477507865} + m_OpenClipOffsetRotation: {x: 0, y: 0, z: 0, w: 1} + m_Rotation: {x: 0, y: 0, z: 0, w: 1} + m_ApplyOffsets: 0 +--- !u!74 &-7150935952859310220 +AnimationClip: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Recorded (1) + serializedVersion: 7 + m_Legacy: 0 + m_Compressed: 0 + m_UseHighQualityCurve: 1 + m_RotationCurves: [] + m_CompressedRotationCurves: [] + m_EulerCurves: [] + m_PositionCurves: + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0.11666667 + value: {x: 0, y: 0, z: 0} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 0.18333334 + value: {x: 3, y: 2.2000046, z: 0} + inSlope: {x: 31.500008, y: 0, z: 0} + outSlope: {x: 31.500008, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 0.25 + value: {x: 4.200001, y: -1.3999939, z: 0} + inSlope: {x: 3.200012, y: -57.599976, z: 0} + outSlope: {x: 3.200012, y: -57.599976, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 0.43333334 + value: {x: 4.4000015, y: -12.399994, z: 0} + inSlope: {x: 3.0000045, y: 0, z: 0} + outSlope: {x: 3.0000045, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 0.51666665 + value: {x: 5.000002, y: -11.199997, z: 0} + inSlope: {x: 9.333332, y: 0, z: 0} + outSlope: {x: 9.333332, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 0.5833333 + value: {x: 5.800001, y: -12.799995, z: 0} + inSlope: {x: 7.199992, y: 0, z: 0} + outSlope: {x: 7.199992, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 0.68333334 + value: {x: 6.200001, y: -11.999992, z: 0} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 0.76666665 + value: {x: 6.200001, y: -12.799995, z: 0} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + path: + m_ScaleCurves: [] + m_FloatCurves: [] + m_PPtrCurves: [] + 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: 1 + script: {fileID: 0} + typeID: 4 + customType: 0 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + pptrCurveMapping: [] + m_AnimationClipSettings: + serializedVersion: 2 + m_AdditiveReferencePoseClip: {fileID: 0} + m_AdditiveReferencePoseTime: 0 + m_StartTime: 0 + m_StopTime: 0.76666665 + 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: + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0.11666667 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.18333334 + value: 3 + inSlope: 31.500008 + outSlope: 31.500008 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.25 + value: 4.200001 + inSlope: 3.200012 + outSlope: 3.200012 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.43333334 + value: 4.4000015 + inSlope: 3.0000045 + outSlope: 3.0000045 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.51666665 + value: 5.000002 + inSlope: 9.333332 + outSlope: 9.333332 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.5833333 + value: 5.800001 + inSlope: 7.199992 + outSlope: 7.199992 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.68333334 + value: 6.200001 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.76666665 + value: 6.200001 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.x + path: + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0.11666667 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.18333334 + value: 2.2000046 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.25 + value: -1.3999939 + inSlope: -57.599976 + outSlope: -57.599976 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.43333334 + value: -12.399994 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.51666665 + value: -11.199997 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.5833333 + value: -12.799995 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.68333334 + value: -11.999992 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.76666665 + value: -12.799995 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.y + path: + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0.11666667 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.18333334 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.25 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.43333334 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.51666665 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.5833333 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.68333334 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.76666665 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.z + path: + classID: 4 + script: {fileID: 0} + flags: 0 + m_EulerEditorCurves: [] + m_HasGenericRootTransform: 1 + m_HasMotionFloatCurves: 0 + m_Events: [] +--- !u!74 &-6922421277477507865 +AnimationClip: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Recorded + serializedVersion: 7 + m_Legacy: 0 + m_Compressed: 0 + m_UseHighQualityCurve: 1 + m_RotationCurves: [] + m_CompressedRotationCurves: [] + m_EulerCurves: [] + m_PositionCurves: + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: {x: -39.2, y: 92, z: 0} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0, y: 0.33333334, z: 0.33333334} + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + path: + m_ScaleCurves: [] + m_FloatCurves: [] + m_PPtrCurves: [] + 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: 1 + script: {fileID: 0} + typeID: 4 + customType: 0 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + pptrCurveMapping: [] + m_AnimationClipSettings: + serializedVersion: 2 + m_AdditiveReferencePoseClip: {fileID: 0} + m_AdditiveReferencePoseTime: 0 + m_StartTime: 0 + m_StopTime: 0 + 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: + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: -39.2 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.x + path: + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 92 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.y + path: + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.z + path: + classID: 4 + script: {fileID: 0} + flags: 0 + m_EulerEditorCurves: [] + m_HasGenericRootTransform: 1 + m_HasMotionFloatCurves: 0 + m_Events: [] +--- !u!114 &-4100604165561699402 +MonoBehaviour: + m_ObjectHideFlags: 1 + 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: d21dcc2386d650c4597f3633c75a1f98, type: 3} + m_Name: Animation Track (3) + m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.AnimationTrack + m_Version: 3 + m_AnimClip: {fileID: 0} + m_Locked: 0 + m_Muted: 0 + m_CustomPlayableFullTypename: + m_Curves: {fileID: 0} + m_Parent: {fileID: 11400000} + m_Children: [] + m_Clips: [] + m_Markers: + m_Objects: [] + m_InfiniteClipPreExtrapolation: 1 + m_InfiniteClipPostExtrapolation: 1 + m_InfiniteClipOffsetPosition: {x: -32.90073, y: 103.51327, z: 0} + m_InfiniteClipOffsetEulerAngles: {x: -0, y: 0, z: 0} + m_InfiniteClipTimeOffset: 0 + m_InfiniteClipRemoveOffset: 0 + m_InfiniteClipApplyFootIK: 1 + mInfiniteClipLoop: 0 + m_MatchTargetFields: 63 + m_Position: {x: 0, y: 0, z: 0} + m_EulerAngles: {x: 0, y: 0, z: 0} + m_AvatarMask: {fileID: 0} + m_ApplyAvatarMask: 1 + m_TrackOffset: 0 + m_InfiniteClip: {fileID: -7150935952859310220} + m_OpenClipOffsetRotation: {x: 0, y: 0, z: 0, w: 1} + m_Rotation: {x: 0, y: 0, z: 0, w: 1} + m_ApplyOffsets: 0 +--- !u!114 &-2395336864975438248 +MonoBehaviour: + m_ObjectHideFlags: 1 + 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: d21dcc2386d650c4597f3633c75a1f98, type: 3} + m_Name: Animation Track (1) + m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.AnimationTrack + m_Version: 3 + m_AnimClip: {fileID: 0} + m_Locked: 0 + m_Muted: 0 + m_CustomPlayableFullTypename: + m_Curves: {fileID: 0} + m_Parent: {fileID: 11400000} + m_Children: [] + m_Clips: + - m_Version: 1 + m_Start: 0 + m_ClipIn: 0 + m_Asset: {fileID: 3115908604919352715} + m_Duration: 0.8333333333333334 + m_TimeScale: 1 + m_ParentTrack: {fileID: -2395336864975438248} + m_EaseInDuration: 0 + m_EaseOutDuration: 0 + m_BlendInDuration: -1 + m_BlendOutDuration: -1 + m_MixInCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_MixOutCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_BlendInCurveMode: 0 + m_BlendOutCurveMode: 0 + m_ExposedParameterNames: [] + m_AnimationCurves: {fileID: 0} + m_Recordable: 0 + m_PostExtrapolationMode: 1 + m_PreExtrapolationMode: 1 + m_PostExtrapolationTime: Infinity + m_PreExtrapolationTime: 0 + m_DisplayName: Pulver_Cucumbatacc + m_Markers: + m_Objects: [] + m_InfiniteClipPreExtrapolation: 0 + m_InfiniteClipPostExtrapolation: 0 + m_InfiniteClipOffsetPosition: {x: 0, y: 0, z: 0} + m_InfiniteClipOffsetEulerAngles: {x: 0, y: 0, z: 0} + m_InfiniteClipTimeOffset: 0 + m_InfiniteClipRemoveOffset: 0 + m_InfiniteClipApplyFootIK: 1 + mInfiniteClipLoop: 0 + m_MatchTargetFields: 63 + m_Position: {x: 0, y: 0, z: 0} + m_EulerAngles: {x: 0, y: 0, z: 0} + m_AvatarMask: {fileID: 0} + m_ApplyAvatarMask: 1 + m_TrackOffset: 0 + m_InfiniteClip: {fileID: 0} + m_OpenClipOffsetRotation: {x: 0, y: 0, z: 0, w: 1} + m_Rotation: {x: 0, y: 0, z: 0, w: 1} + m_ApplyOffsets: 0 +--- !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: bfda56da833e2384a9677cd3c976a436, type: 3} + m_Name: PulverCucumberSmack2 + m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.TimelineAsset + m_Version: 0 + m_Tracks: + - {fileID: -7584736085941489071} + - {fileID: -2395336864975438248} + - {fileID: -7231857257271738743} + - {fileID: -4100604165561699402} + m_FixedDuration: 0 + m_EditorSettings: + m_Framerate: 60 + m_ScenePreview: 1 + m_DurationMode: 0 + m_MarkerTrack: {fileID: 0} +--- !u!114 &3115908604919352715 +MonoBehaviour: + m_ObjectHideFlags: 1 + 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: 030f85c3f73729f4f976f66ffb23b875, type: 3} + m_Name: AnimationPlayableAsset + m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.AnimationPlayableAsset + m_Clip: {fileID: 7400000, guid: 09d7dd4e84cbed54bb4ca4e63ad0c6fa, type: 2} + m_Position: {x: 0, y: 0, z: 0} + m_EulerAngles: {x: 0, y: 0, z: 0} + m_UseTrackMatchFields: 1 + m_MatchTargetFields: 63 + m_RemoveStartOffset: 1 + m_ApplyFootIK: 1 + m_Loop: 0 + m_Version: 1 + m_Rotation: {x: 0, y: 0, z: 0, w: 1} diff --git a/Assets/Playables/PulverCucumberSmack2.playable.meta b/Assets/Playables/PulverCucumberSmack2.playable.meta new file mode 100644 index 00000000..0047f54e --- /dev/null +++ b/Assets/Playables/PulverCucumberSmack2.playable.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dd9566026364e814a8dad109e6c365ca +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Characters/PlayerCharacter.prefab b/Assets/Prefabs/Characters/PlayerCharacter.prefab index cb050fe0..29511fc0 100644 --- a/Assets/Prefabs/Characters/PlayerCharacter.prefab +++ b/Assets/Prefabs/Characters/PlayerCharacter.prefab @@ -313,6 +313,14 @@ PrefabInstance: propertyPath: m_Layer value: 7 objectReference: {fileID: 0} + - target: {fileID: 6109476811019011833, guid: 361ccc9ef82acef4784b24b72013d971, type: 3} + propertyPath: m_Size.x + value: 3.8700001 + objectReference: {fileID: 0} + - target: {fileID: 6109476811019011833, guid: 361ccc9ef82acef4784b24b72013d971, type: 3} + propertyPath: m_Size.y + value: 7.55122 + objectReference: {fileID: 0} - target: {fileID: 6109476811019011833, guid: 361ccc9ef82acef4784b24b72013d971, type: 3} propertyPath: m_SortingOrder value: 1 diff --git a/Assets/Prefabs/Characters/PulverCharacter.prefab b/Assets/Prefabs/Characters/PulverCharacter.prefab index d545ce4e..6ee7e13a 100644 --- a/Assets/Prefabs/Characters/PulverCharacter.prefab +++ b/Assets/Prefabs/Characters/PulverCharacter.prefab @@ -136,7 +136,7 @@ MonoBehaviour: radius: 2 height: 2 canMove: 1 - maxSpeed: 15 + maxSpeed: 30 gravity: {x: 0, y: 0, z: 0} groundMask: serializedVersion: 2 @@ -236,6 +236,8 @@ SpriteRenderer: m_RayTracingAccelStructBuildFlagsOverride: 0 m_RayTracingAccelStructBuildFlags: 1 m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -257,6 +259,7 @@ SpriteRenderer: m_AutoUVMaxDistance: 0.5 m_AutoUVMaxAngle: 89 m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 2 diff --git a/Assets/Prefabs/Environment/Placeholders/BallTree.prefab b/Assets/Prefabs/Environment/Placeholders/BallTree.prefab index db3f03ba..f49f6fc6 100644 --- a/Assets/Prefabs/Environment/Placeholders/BallTree.prefab +++ b/Assets/Prefabs/Environment/Placeholders/BallTree.prefab @@ -1,5 +1,51 @@ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: +--- !u!1 &1646387898454772943 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7371967679236352629} + - component: {fileID: 2280359367130513804} + m_Layer: 0 + m_Name: PulverMoveTarget + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7371967679236352629 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1646387898454772943} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -4.4615383, y: 0.61538696, z: 0} + m_LocalScale: {x: 0.7692308, y: 0.7692308, z: 0.7692308} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4937390562043858043} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2280359367130513804 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1646387898454772943} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2bcf343b3ef74f0fb3c64be6fd2893b6, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::Interactions.CharacterMoveToTarget + characterType: 2 + positionOffset: {x: 0, y: 0, z: 1} --- !u!1 &3591802784221671576 GameObject: m_ObjectHideFlags: 0 @@ -94,6 +140,11 @@ GameObject: - component: {fileID: 4937390562043858043} - component: {fileID: 2720557426779044373} - component: {fileID: 8897661028274890141} + - component: {fileID: 8437452310832126615} + - component: {fileID: 492578671844741631} + - component: {fileID: 8984729148657672365} + - component: {fileID: 1569498917964935965} + - component: {fileID: 3871210969445384207} m_Layer: 10 m_Name: BallTree m_TagString: Untagged @@ -115,6 +166,7 @@ Transform: m_ConstrainProportionsScale: 1 m_Children: - {fileID: 6631072601870453588} + - {fileID: 7371967679236352629} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!212 &2720557426779044373 @@ -137,6 +189,8 @@ SpriteRenderer: m_RayTracingAccelStructBuildFlagsOverride: 0 m_RayTracingAccelStructBuildFlags: 1 m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -158,6 +212,7 @@ SpriteRenderer: m_AutoUVMaxDistance: 0.5 m_AutoUVMaxAngle: 89 m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 1 @@ -218,3 +273,115 @@ BoxCollider2D: m_AutoTiling: 0 m_Size: {x: 3.437712, y: 7.532383} m_EdgeRadius: 0 +--- !u!114 &8437452310832126615 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7379304988657006554} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 73d6494a73174ffabc6a7d3089d51e73, type: 3} + m_Name: + m_EditorClassIdentifier: + isOneTime: 0 + cooldown: -1 + characterToInteract: 2 + interactionStarted: + m_PersistentCalls: + m_Calls: [] + interactionInterrupted: + m_PersistentCalls: + m_Calls: [] + characterArrived: + m_PersistentCalls: + m_Calls: [] + interactionComplete: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &492578671844741631 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7379304988657006554} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1101f6c4eb04423b89dc78dc7c9f1aae, type: 3} + m_Name: + m_EditorClassIdentifier: + stepData: {fileID: 11400000, guid: 8ac614a698631554ab8ac39aed04a189, type: 2} + puzzleIndicator: {fileID: 0} + drawPromptRangeGizmo: 1 +--- !u!114 &8984729148657672365 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7379304988657006554} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 42e77a0c97604b6eb7674e58726c831a, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::Interactions.InteractionTimelineAction + respondToEvents: 04000000 + pauseInteractionFlow: 1 + playableDirector: {fileID: 0} + timelineMappings: + - eventType: 4 + timelines: [] + bindPlayerCharacter: 0 + bindPulverCharacter: 0 + playerTrackName: + pulverTrackName: + timeoutSeconds: 30 + loopLast: 0 + loopAll: 0 +--- !u!320 &1569498917964935965 +PlayableDirector: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7379304988657006554} + m_Enabled: 1 + serializedVersion: 3 + m_PlayableAsset: {fileID: 11400000, guid: dd9566026364e814a8dad109e6c365ca, type: 2} + m_InitialState: 0 + m_WrapMode: 2 + m_DirectorUpdateMode: 1 + m_InitialTime: 0 + m_SceneBindings: + - key: {fileID: -7584736085941489071, guid: dd9566026364e814a8dad109e6c365ca, type: 2} + value: {fileID: 3871210969445384207} + - key: {fileID: -2395336864975438248, guid: dd9566026364e814a8dad109e6c365ca, type: 2} + value: {fileID: 0} + - key: {fileID: -7231857257271738743, guid: dd9566026364e814a8dad109e6c365ca, type: 2} + value: {fileID: 0} + m_ExposedReferences: + m_References: [] +--- !u!95 &3871210969445384207 +Animator: + serializedVersion: 7 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7379304988657006554} + m_Enabled: 1 + m_Avatar: {fileID: 0} + m_Controller: {fileID: 0} + m_CullingMode: 0 + m_UpdateMode: 0 + m_ApplyRootMotion: 0 + m_LinearVelocityBlending: 0 + m_StabilizeFeet: 0 + m_AnimatePhysics: 0 + m_WarningMessage: + m_HasTransformHierarchy: 1 + m_AllowConstantClipSamplingOptimization: 1 + m_KeepAnimatorStateOnDisable: 0 + m_WriteDefaultValuesOnDisable: 0 diff --git a/Assets/Scripts/Interactions/CharacterMoveToTarget.cs b/Assets/Scripts/Interactions/CharacterMoveToTarget.cs new file mode 100644 index 00000000..ed652b00 --- /dev/null +++ b/Assets/Scripts/Interactions/CharacterMoveToTarget.cs @@ -0,0 +1,58 @@ +using UnityEngine; + +namespace Interactions +{ + /// + /// Defines a target position for character movement during interaction. + /// Attach this to an interactable object's child to specify where + /// characters should move during interaction rather than using the default calculations. + /// + public class CharacterMoveToTarget : MonoBehaviour + { + [Tooltip("Which character this target position is for")] + public CharacterToInteract characterType = CharacterToInteract.Pulver; + + [Tooltip("Optional offset from this transform's position")] + public Vector3 positionOffset = Vector3.zero; + + /// + /// Get the target position for this character to move to + /// + public Vector3 GetTargetPosition() + { + return transform.position + positionOffset; + } + + #if UNITY_EDITOR + private void OnDrawGizmos() + { + // Draw a different colored sphere based on which character this target is for + switch (characterType) + { + case CharacterToInteract.Trafalgar: + Gizmos.color = new Color(0f, 0.5f, 1f, 0.8f); // Blue for player + break; + case CharacterToInteract.Pulver: + Gizmos.color = new Color(1f, 0.5f, 0f, 0.8f); // Orange for follower + break; + case CharacterToInteract.Both: + Gizmos.color = new Color(0.7f, 0f, 0.7f, 0.8f); // Purple for both + break; + default: + Gizmos.color = new Color(0.5f, 0.5f, 0.5f, 0.8f); // Gray for none + break; + } + + Vector3 targetPos = GetTargetPosition(); + Gizmos.DrawSphere(targetPos, 0.2f); + + // Draw a line from the parent interactable to this target + Interactable parentInteractable = GetComponentInParent(); + if (parentInteractable != null) + { + Gizmos.DrawLine(parentInteractable.transform.position, targetPos); + } + } + #endif + } +} diff --git a/Assets/Scripts/Interactions/CharacterMoveToTarget.cs.meta b/Assets/Scripts/Interactions/CharacterMoveToTarget.cs.meta new file mode 100644 index 00000000..e86f918e --- /dev/null +++ b/Assets/Scripts/Interactions/CharacterMoveToTarget.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2bcf343b3ef74f0fb3c64be6fd2893b6 +timeCreated: 1759744130 \ No newline at end of file diff --git a/Assets/Scripts/Interactions/Interactable.cs b/Assets/Scripts/Interactions/Interactable.cs index 1bdb6b78..496d45b6 100644 --- a/Assets/Scripts/Interactions/Interactable.cs +++ b/Assets/Scripts/Interactions/Interactable.cs @@ -1,22 +1,27 @@ using Input; using UnityEngine; using System; +using System.Collections.Generic; using UnityEngine.Events; +using System.Threading.Tasks; namespace Interactions { public enum CharacterToInteract { + None, Trafalgar, - Pulver + Pulver, + Both } + /// /// Represents an interactable object that can respond to tap input events. /// public class Interactable : MonoBehaviour, ITouchInputConsumer { [Header("Interaction Settings")] - public bool isOneTime = false; + public bool isOneTime; public float cooldown = -1f; public CharacterToInteract characterToInteract = CharacterToInteract.Pulver; @@ -30,15 +35,64 @@ namespace Interactions private bool _interactionInProgress; private PlayerTouchController _playerRef; private FollowerController _followerController; - private bool _isActive = true; + private InteractionEventType _currentEventType; + // Action component system + private List _registeredActions = new List(); + private void Awake() { // Subscribe to interactionComplete event interactionComplete.AddListener(OnInteractionComplete); } + /// + /// Register an action component with this interactable + /// + public void RegisterAction(InteractionActionBase action) + { + if (!_registeredActions.Contains(action)) + { + _registeredActions.Add(action); + } + } + + /// + /// Unregister an action component from this interactable + /// + public void UnregisterAction(InteractionActionBase action) + { + _registeredActions.Remove(action); + } + + /// + /// Dispatch an interaction event to all registered actions and await their completion + /// + private async Task DispatchEventAsync(InteractionEventType eventType) + { + _currentEventType = eventType; + + // Collect all tasks from actions that want to respond + List> tasks = new List>(); + + foreach (var action in _registeredActions) + { + Task task = action.OnInteractionEvent(eventType, _playerRef, _followerController); + if (task != null) + { + tasks.Add(task); + } + } + + if (tasks.Count > 0) + { + // Wait for all tasks to complete + await Task.WhenAll(tasks); + } + // If no tasks were added, the method will complete immediately (no need for await) + } + /// /// Handles tap input. Triggers interaction logic. /// @@ -50,11 +104,12 @@ namespace Interactions return; } Debug.Log($"[Interactable] OnTap at {worldPosition} on {gameObject.name}"); - // Broadcast interaction started event - TryInteract(); + + // Start the interaction process asynchronously + _ = TryInteractAsync(); } - public void TryInteract() + private async Task TryInteractAsync() { _interactionInProgress = true; @@ -63,68 +118,278 @@ namespace Interactions interactionStarted?.Invoke(_playerRef, _followerController); + // Dispatch the InteractionStarted event to action components + await DispatchEventAsync(InteractionEventType.InteractionStarted); + + // After all InteractionStarted actions complete, proceed to player movement + await StartPlayerMovementAsync(); + } + + private async Task StartPlayerMovementAsync() + { if (_playerRef == null) { Debug.Log($"[Interactable] Player character could not be found. Aborting interaction."); interactionInterrupted.Invoke(); + await DispatchEventAsync(InteractionEventType.InteractionInterrupted); + return; + } + + // If characterToInteract is None, immediately trigger the characterArrived event + if (characterToInteract == CharacterToInteract.None) + { + await BroadcastCharacterArrivedAsync(); return; } - // Compute closest point on the interaction radius - Vector3 interactablePos = transform.position; - Vector3 playerPos = _playerRef.transform.position; - float stopDistance = characterToInteract == CharacterToInteract.Pulver - ? GameManager.Instance.PlayerStopDistance - : GameManager.Instance.PlayerStopDistanceDirectInteraction; - Vector3 toPlayer = (playerPos - interactablePos).normalized; - Vector3 stopPoint = interactablePos + toPlayer * stopDistance; + // Check for a CharacterMoveToTarget component for Trafalgar (player) or Both + Vector3 stopPoint; + bool customTargetFound = false; + + CharacterMoveToTarget[] moveTargets = GetComponentsInChildren(); + foreach (var target in moveTargets) + { + // Target is valid if it matches Trafalgar specifically or is set to Both + if (target.characterType == CharacterToInteract.Trafalgar || target.characterType == CharacterToInteract.Both) + { + stopPoint = target.GetTargetPosition(); + customTargetFound = true; + + // We need to wait for the player to arrive, so use a TaskCompletionSource + var tcs = new TaskCompletionSource(); + + // Use local functions instead of circular lambda references + void OnPlayerArrivedLocal() + { + // First remove both event handlers to prevent memory leaks + if (_playerRef != null) + { + _playerRef.OnArrivedAtTarget -= OnPlayerArrivedLocal; + _playerRef.OnMoveToCancelled -= OnPlayerMoveCancelledLocal; + } + + // Then continue with the interaction flow + OnPlayerArrivedAsync().ContinueWith(_ => tcs.TrySetResult(true)); + } + + void OnPlayerMoveCancelledLocal() + { + // First remove both event handlers to prevent memory leaks + if (_playerRef != null) + { + _playerRef.OnArrivedAtTarget -= OnPlayerArrivedLocal; + _playerRef.OnMoveToCancelled -= OnPlayerMoveCancelledLocal; + } + + // Then handle the cancellation + OnPlayerMoveCancelledAsync().ContinueWith(_ => tcs.TrySetResult(false)); + } + + // Unsubscribe previous handlers (if any) + _playerRef.OnArrivedAtTarget -= OnPlayerArrived; + _playerRef.OnMoveToCancelled -= OnPlayerMoveCancelled; + + // Subscribe our new handlers + _playerRef.OnArrivedAtTarget += OnPlayerArrivedLocal; + _playerRef.OnMoveToCancelled += OnPlayerMoveCancelledLocal; + + // Start the player movement + _playerRef.MoveToAndNotify(stopPoint); + + // Await player arrival + await tcs.Task; + return; + } + } + + // If no custom target was found, use the default behavior + if (!customTargetFound) + { + // Compute closest point on the interaction radius + Vector3 interactablePos = transform.position; + Vector3 playerPos = _playerRef.transform.position; + float stopDistance = characterToInteract == CharacterToInteract.Pulver + ? GameManager.Instance.PlayerStopDistance + : GameManager.Instance.PlayerStopDistanceDirectInteraction; + Vector3 toPlayer = (playerPos - interactablePos).normalized; + stopPoint = interactablePos + toPlayer * stopDistance; - // Unsubscribe previous to avoid duplicate calls - _playerRef.OnArrivedAtTarget -= OnPlayerArrived; - _playerRef.OnMoveToCancelled -= OnPlayerMoveCancelled; - _playerRef.OnArrivedAtTarget += OnPlayerArrived; - _playerRef.OnMoveToCancelled += OnPlayerMoveCancelled; - _playerRef.MoveToAndNotify(stopPoint); + // We need to wait for the player to arrive, so use a TaskCompletionSource + var tcs = new TaskCompletionSource(); + + // Use local functions instead of circular lambda references + void OnPlayerArrivedLocal() + { + // First remove both event handlers to prevent memory leaks + if (_playerRef != null) + { + _playerRef.OnArrivedAtTarget -= OnPlayerArrivedLocal; + _playerRef.OnMoveToCancelled -= OnPlayerMoveCancelledLocal; + } + + // Then continue with the interaction flow + OnPlayerArrivedAsync().ContinueWith(_ => tcs.TrySetResult(true)); + } + + void OnPlayerMoveCancelledLocal() + { + // First remove both event handlers to prevent memory leaks + if (_playerRef != null) + { + _playerRef.OnArrivedAtTarget -= OnPlayerArrivedLocal; + _playerRef.OnMoveToCancelled -= OnPlayerMoveCancelledLocal; + } + + // Then handle the cancellation + OnPlayerMoveCancelledAsync().ContinueWith(_ => tcs.TrySetResult(false)); + } + + // Unsubscribe previous handlers (if any) + _playerRef.OnArrivedAtTarget -= OnPlayerArrived; + _playerRef.OnMoveToCancelled -= OnPlayerMoveCancelled; + + // Subscribe our new handlers + _playerRef.OnArrivedAtTarget += OnPlayerArrivedLocal; + _playerRef.OnMoveToCancelled += OnPlayerMoveCancelledLocal; + + // Start the player movement + _playerRef.MoveToAndNotify(stopPoint); + + // Await player arrival + await tcs.Task; + } } - private void OnPlayerMoveCancelled() + private async Task OnPlayerMoveCancelledAsync() { _interactionInProgress = false; interactionInterrupted?.Invoke(); + await DispatchEventAsync(InteractionEventType.InteractionInterrupted); } - private void OnPlayerArrived() + private async Task OnPlayerArrivedAsync() { if (!_interactionInProgress) return; - // Unsubscribe to avoid memory leaks - _playerRef.OnArrivedAtTarget -= OnPlayerArrived; + // Dispatch PlayerArrived event + await DispatchEventAsync(InteractionEventType.PlayerArrived); + // After all PlayerArrived actions complete, proceed to character interaction + await HandleCharacterInteractionAsync(); + } + + private async Task HandleCharacterInteractionAsync() + { if (characterToInteract == CharacterToInteract.Pulver) { - _followerController.OnPickupArrived -= OnFollowerArrived; - _followerController.OnPickupArrived += OnFollowerArrived; - _followerController.GoToPointAndReturn(transform.position, _playerRef.transform); + // We need to wait for the follower to arrive, so use a TaskCompletionSource + var tcs = new TaskCompletionSource(); + + // Create a proper local function for the event handler + void OnFollowerArrivedLocal() + { + // First remove the event handler to prevent memory leaks + if (_followerController != null) + { + _followerController.OnPickupArrived -= OnFollowerArrivedLocal; + } + + // Then continue with the interaction flow + OnFollowerArrivedAsync().ContinueWith(_ => tcs.TrySetResult(true)); + } + + // Register our new local function handler + _followerController.OnPickupArrived += OnFollowerArrivedLocal; + + // Check for a CharacterMoveToTarget component for Pulver or Both + Vector3 targetPosition = transform.position; + CharacterMoveToTarget[] moveTargets = GetComponentsInChildren(); + foreach (var target in moveTargets) + { + if (target.characterType == CharacterToInteract.Pulver || target.characterType == CharacterToInteract.Both) + { + targetPosition = target.GetTargetPosition(); + break; + } + } + + _followerController.GoToPointAndReturn(targetPosition, _playerRef.transform); + + // Await follower arrival + await tcs.Task; } else if (characterToInteract == CharacterToInteract.Trafalgar) { - BroadcastCharacterArrived(); + await BroadcastCharacterArrivedAsync(); + } + else if (characterToInteract == CharacterToInteract.Both) + { + // We need to wait for the follower to arrive, so use a TaskCompletionSource + var tcs = new TaskCompletionSource(); + + // Create a proper local function for the event handler + void OnFollowerArrivedLocal() + { + // First remove the event handler to prevent memory leaks + if (_followerController != null) + { + _followerController.OnPickupArrived -= OnFollowerArrivedLocal; + } + + // Then continue with the interaction flow + OnFollowerArrivedAsync().ContinueWith(_ => tcs.TrySetResult(true)); + } + + // Register our new local function handler + _followerController.OnPickupArrived += OnFollowerArrivedLocal; + + // Check for a CharacterMoveToTarget component for Pulver or Both + Vector3 targetPosition = transform.position; + CharacterMoveToTarget[] moveTargets = GetComponentsInChildren(); + foreach (var target in moveTargets) + { + if (target.characterType == CharacterToInteract.Pulver || target.characterType == CharacterToInteract.Both) + { + targetPosition = target.GetTargetPosition(); + break; + } + } + + _followerController.GoToPointAndReturn(targetPosition, _playerRef.transform); + + // Await follower arrival + await tcs.Task; } } - private void OnFollowerArrived() + private async Task OnFollowerArrivedAsync() { if (!_interactionInProgress) return; - // Unsubscribe to avoid memory leaks - _followerController.OnPickupArrived -= OnFollowerArrived; + // Dispatch FollowerArrived event + await DispatchEventAsync(InteractionEventType.InteractingCharacterArrived); - BroadcastCharacterArrived(); + // After all FollowerArrived actions complete, proceed to character arrived + await BroadcastCharacterArrivedAsync(); } - private void BroadcastCharacterArrived() + // Legacy non-async method to maintain compatibility with existing code + private void OnPlayerArrived() + { + // This is now just a wrapper for the async version + _ = OnPlayerArrivedAsync(); + } + + // Legacy non-async method to maintain compatibility with existing code + private void OnPlayerMoveCancelled() + { + // This is now just a wrapper for the async version + _ = OnPlayerMoveCancelledAsync(); + } + + private async Task BroadcastCharacterArrivedAsync() { // Check for ObjectiveStepBehaviour and lock state var step = GetComponent(); @@ -138,16 +403,24 @@ namespace Interactions _followerController = null; return; } + + // Dispatch CharacterArrived event + // await DispatchEventAsync(InteractionEventType.InteractingCharacterArrived); + // Broadcast appropriate event characterArrived?.Invoke(); + // Reset variables for next time _interactionInProgress = false; _playerRef = null; _followerController = null; } - private void OnInteractionComplete(bool success) + private async void OnInteractionComplete(bool success) { + // Dispatch InteractionComplete event + await DispatchEventAsync(InteractionEventType.InteractionComplete); + if (success) { if (isOneTime) diff --git a/Assets/Scripts/Interactions/InteractionActionBase.cs b/Assets/Scripts/Interactions/InteractionActionBase.cs new file mode 100644 index 00000000..3805f188 --- /dev/null +++ b/Assets/Scripts/Interactions/InteractionActionBase.cs @@ -0,0 +1,91 @@ +using System.Collections.Generic; +using UnityEngine; +using System.Linq; +using System.Threading.Tasks; +using Input; + +namespace Interactions +{ + /// + /// Base class for all interaction action components + /// These components respond to interaction events and can control the interaction flow + /// + public abstract class InteractionActionBase : MonoBehaviour + { + [Tooltip("Which interaction events this action should respond to")] + public List respondToEvents = new List(); + + [Tooltip("Whether the interaction flow should wait for this action to complete")] + public bool pauseInteractionFlow = true; + + protected Interactable parentInteractable; + + protected virtual void Awake() + { + // Get the parent interactable component + parentInteractable = GetComponentInParent(); + + if (parentInteractable == null) + { + Debug.LogError($"[{GetType().Name}] Cannot find parent Interactable component!"); + enabled = false; + return; + } + } + + protected virtual void OnEnable() + { + if (parentInteractable != null) + { + parentInteractable.RegisterAction(this); + } + } + + protected virtual void OnDisable() + { + if (parentInteractable != null) + { + parentInteractable.UnregisterAction(this); + } + } + + /// + /// Called when an interaction event occurs that this action is registered for + /// + /// The type of event that occurred + /// A task that completes when the action is finished, or null if action won't execute + public Task OnInteractionEvent(InteractionEventType eventType, PlayerTouchController player, FollowerController follower) + { + if (respondToEvents.Contains(eventType) && ShouldExecute(eventType, player, follower)) + { + if (pauseInteractionFlow) + { + return ExecuteAsync(eventType, player, follower); + } + else + { + // If we don't need to pause the flow, execute in the background + // and return a completed task + _ = ExecuteAsync(eventType, player, follower); + return Task.FromResult(false); + } + } + + return null; + } + + /// + /// Execute the action for the given event asynchronously + /// + protected abstract Task ExecuteAsync(InteractionEventType eventType, PlayerTouchController player, FollowerController follower); + + /// + /// Called to determine if this action should execute for the given event + /// Override this to add additional conditions for execution + /// + protected virtual bool ShouldExecute(InteractionEventType eventType, PlayerTouchController player, FollowerController follower) + { + return true; + } + } +} diff --git a/Assets/Scripts/Interactions/InteractionActionBase.cs.meta b/Assets/Scripts/Interactions/InteractionActionBase.cs.meta new file mode 100644 index 00000000..c42b2d30 --- /dev/null +++ b/Assets/Scripts/Interactions/InteractionActionBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5cf351d32dac4169a9db20609727a70f +timeCreated: 1759746705 \ No newline at end of file diff --git a/Assets/Scripts/Interactions/InteractionEventType.cs b/Assets/Scripts/Interactions/InteractionEventType.cs new file mode 100644 index 00000000..8f924db1 --- /dev/null +++ b/Assets/Scripts/Interactions/InteractionEventType.cs @@ -0,0 +1,16 @@ +using System; + +namespace Interactions +{ + /// + /// Defines the different types of events that can occur during an interaction + /// + public enum InteractionEventType + { + InteractionStarted, + PlayerArrived, + InteractingCharacterArrived, + InteractionComplete, + InteractionInterrupted + } +} diff --git a/Assets/Scripts/Interactions/InteractionEventType.cs.meta b/Assets/Scripts/Interactions/InteractionEventType.cs.meta new file mode 100644 index 00000000..9b6738c6 --- /dev/null +++ b/Assets/Scripts/Interactions/InteractionEventType.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 78684d31bd4d4636834a494c7cb74f48 +timeCreated: 1759746690 \ No newline at end of file diff --git a/Assets/Scripts/Interactions/InteractionTimelineAction.cs b/Assets/Scripts/Interactions/InteractionTimelineAction.cs new file mode 100644 index 00000000..995ec037 --- /dev/null +++ b/Assets/Scripts/Interactions/InteractionTimelineAction.cs @@ -0,0 +1,241 @@ +using System; +using UnityEngine; +using UnityEngine.Playables; +using System.Linq; +using System.Threading.Tasks; +using Input; + +namespace Interactions +{ + /// + /// Component that plays timeline animations in response to interaction events + /// + [RequireComponent(typeof(PlayableDirector))] + public class InteractionTimelineAction : InteractionActionBase + { + [System.Serializable] + public class TimelineEventMapping + { + public InteractionEventType eventType; + public PlayableAsset[] timelines; + + [Tooltip("Whether to bind the player character to the track named 'Player'")] + public bool bindPlayerCharacter = false; + + [Tooltip("Whether to bind the follower character to the track named 'Pulver'")] + public bool bindPulverCharacter = false; + + [Tooltip("Custom track name for player character binding")] + public string playerTrackName = "Player"; + + [Tooltip("Custom track name for follower character binding")] + public string pulverTrackName = "Pulver"; + + [Tooltip("Time in seconds before the timeline is automatically completed (safety feature)")] + public float timeoutSeconds = 30f; + + [Tooltip("Whether to loop the last timeline in the sequence")] + public bool loopLast = false; + + [Tooltip("Whether to loop through all timelines in the sequence")] + public bool loopAll = false; + + // Helper property to check if we have valid timelines + public bool HasValidTimelines => timelines != null && timelines.Length > 0 && timelines[0] != null; + } + + [Header("Timeline Configuration")] [SerializeField] + private PlayableDirector playableDirector; + + [SerializeField] private TimelineEventMapping[] timelineMappings; + + private TaskCompletionSource _currentPlaybackTCS; + private int _currentTimelineIndex = 0; + private TimelineEventMapping _currentMapping = null; + + protected override void Awake() + { + base.Awake(); + + if (playableDirector == null) + { + playableDirector = GetComponent(); + } + + if (playableDirector == null) + { + Debug.LogError("[InteractionTimelineAction] PlayableDirector component is missing!"); + enabled = false; + return; + } + + // Subscribe to the director's stopped event + playableDirector.stopped += OnPlayableDirectorStopped; + } + + private void OnDestroy() + { + if (playableDirector != null) + { + playableDirector.stopped -= OnPlayableDirectorStopped; + } + } + + protected override async Task ExecuteAsync(InteractionEventType eventType, PlayerTouchController player, + FollowerController follower) + { + // Find the timeline for this event type + TimelineEventMapping mapping = Array.Find(timelineMappings, m => m.eventType == eventType); + + if (mapping == null || !mapping.HasValidTimelines) + { + // No timeline configured for this event + return true; + } + + _currentMapping = mapping; + _currentTimelineIndex = 0; + + return await PlayTimelineSequence(player, follower); + } + + private async Task PlayTimelineSequence(PlayerTouchController player, FollowerController follower) + { + if (_currentMapping == null || !_currentMapping.HasValidTimelines) + { + return true; + } + + // Play the current timeline in the sequence + bool result = await PlaySingleTimeline(_currentMapping.timelines[_currentTimelineIndex], _currentMapping, player, follower); + + // Return false if the playback failed + if (!result) + { + return false; + } + + // Increment the timeline index for next playback + _currentTimelineIndex++; + + // Check if we've reached the end of the sequence + if (_currentTimelineIndex >= _currentMapping.timelines.Length) + { + // If loop all is enabled, start over + if (_currentMapping.loopAll) + { + _currentTimelineIndex = 0; + // Don't continue automatically, wait for next interaction + return true; + } + // If loop last is enabled, replay the last timeline + else if (_currentMapping.loopLast) + { + _currentTimelineIndex = _currentMapping.timelines.Length - 1; + // Don't continue automatically, wait for next interaction + return true; + } + // Otherwise, we're done with the sequence + else + { + _currentTimelineIndex = 0; + _currentMapping = null; + return true; + } + } + + // If we have more timelines in the sequence, we're done for now + // Next interaction will pick up where we left off + return true; + } + + private async Task PlaySingleTimeline(PlayableAsset timelineAsset, TimelineEventMapping mapping, + PlayerTouchController player, FollowerController follower) + { + if (timelineAsset == null) + { + Debug.LogWarning("[InteractionTimelineAction] Timeline asset is null"); + return true; + } + + // Set the timeline asset + playableDirector.playableAsset = timelineAsset; + + // Bind characters if needed + if (mapping.bindPlayerCharacter && player != null) + { + try + { + var trackOutput = playableDirector.playableAsset.outputs.FirstOrDefault(o => o.streamName == mapping.playerTrackName); + if (trackOutput.sourceObject != null) + { + playableDirector.SetGenericBinding(trackOutput.sourceObject, player.gameObject); + } + else + { + Debug.LogWarning($"[InteractionTimelineAction] Could not find track named '{mapping.playerTrackName}' for player binding"); + } + } + catch (Exception ex) + { + Debug.LogError($"[InteractionTimelineAction] Error binding player to timeline: {ex.Message}"); + } + } + + if (mapping.bindPulverCharacter && follower != null) + { + try + { + var trackOutput = playableDirector.playableAsset.outputs.FirstOrDefault(o => o.streamName == mapping.pulverTrackName); + if (trackOutput.sourceObject != null) + { + playableDirector.SetGenericBinding(trackOutput.sourceObject, follower.gameObject); + } + else + { + Debug.LogWarning($"[InteractionTimelineAction] Could not find track named '{mapping.pulverTrackName}' for follower binding"); + } + } + catch (Exception ex) + { + Debug.LogError($"[InteractionTimelineAction] Error binding follower to timeline: {ex.Message}"); + } + } + + // Create a task completion source to await the timeline completion + _currentPlaybackTCS = new TaskCompletionSource(); + + // Play the timeline + playableDirector.Play(); + + // Start a timeout coroutine for safety using the mapping's timeout + StartCoroutine(TimeoutCoroutine(mapping.timeoutSeconds)); + + // Wait for the timeline to complete (or timeout) + bool result = await _currentPlaybackTCS.Task; + _currentPlaybackTCS = null; + + return result; + } + + private void OnPlayableDirectorStopped(PlayableDirector director) + { + if (director == playableDirector && _currentPlaybackTCS != null) + { + _currentPlaybackTCS.TrySetResult(true); + } + } + + private System.Collections.IEnumerator TimeoutCoroutine(float timeoutDuration) + { + yield return new WaitForSeconds(timeoutDuration); + + // If the TCS still exists after timeout, complete it with failure + if (_currentPlaybackTCS != null) + { + Debug.LogWarning($"[InteractionTimelineAction] Timeline playback timed out after {timeoutDuration} seconds"); + _currentPlaybackTCS.TrySetResult(false); + } + } + } +} diff --git a/Assets/Scripts/Interactions/InteractionTimelineAction.cs.meta b/Assets/Scripts/Interactions/InteractionTimelineAction.cs.meta new file mode 100644 index 00000000..10fd60e9 --- /dev/null +++ b/Assets/Scripts/Interactions/InteractionTimelineAction.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 42e77a0c97604b6eb7674e58726c831a +timeCreated: 1759746720 \ No newline at end of file