Update to the timeline triggering logic

This commit is contained in:
Michal Pikulski
2025-10-06 16:16:41 +02:00
committed by Michal Pikulski
parent fd611ac27f
commit bdec77d36f
8 changed files with 875 additions and 933 deletions

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 27f5954bda3e24b48b33e5a6605eb33f guid: 1791fd5a24a3142418ed441a2a25b374
NativeFormatImporter: NativeFormatImporter:
externalObjects: {} externalObjects: {}
mainObjectFileID: 11400000 mainObjectFileID: 11400000

View File

@@ -41,47 +41,6 @@ MonoBehaviour:
m_OpenClipOffsetRotation: {x: 0, y: 0, z: 0, w: 1} m_OpenClipOffsetRotation: {x: 0, y: 0, z: 0, w: 1}
m_Rotation: {x: 0, y: 0, z: 0, w: 1} m_Rotation: {x: 0, y: 0, z: 0, w: 1}
m_ApplyOffsets: 0 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 --- !u!74 &-7150935952859310220
AnimationClip: AnimationClip:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -101,14 +60,23 @@ AnimationClip:
serializedVersion: 2 serializedVersion: 2
m_Curve: m_Curve:
- serializedVersion: 3 - serializedVersion: 3
time: 0.11666667 time: 0
value: {x: 0, y: 0, z: 0} value: {x: -0.000011444092, y: 0, z: 0}
inSlope: {x: 0, y: 0, z: 0} inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0} outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0 tangentMode: 0
weightedMode: 0 weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.11666667
value: {x: 0, y: 0, z: 0}
inSlope: {x: 0.00024968927, y: 0, z: 0}
outSlope: {x: 0.00024968927, 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 - serializedVersion: 3
time: 0.18333334 time: 0.18333334
value: {x: 3, y: 2.2000046, z: 0} value: {x: 3, y: 2.2000046, z: 0}
@@ -222,14 +190,23 @@ AnimationClip:
serializedVersion: 2 serializedVersion: 2
m_Curve: m_Curve:
- serializedVersion: 3 - serializedVersion: 3
time: 0.11666667 time: 0
value: 0 value: -0.000011444092
inSlope: 0 inSlope: 0
outSlope: 0 outSlope: 0
tangentMode: 136 tangentMode: 136
weightedMode: 0 weightedMode: 0
inWeight: 0.33333334 inWeight: 0.33333334
outWeight: 0.33333334 outWeight: 0.33333334
- serializedVersion: 3
time: 0.11666667
value: 0
inSlope: 0.00024968927
outSlope: 0.00024968927
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3 - serializedVersion: 3
time: 0.18333334 time: 0.18333334
value: 3 value: 3
@@ -305,6 +282,15 @@ AnimationClip:
curve: curve:
serializedVersion: 2 serializedVersion: 2
m_Curve: m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3 - serializedVersion: 3
time: 0.11666667 time: 0.11666667
value: 0 value: 0
@@ -389,6 +375,15 @@ AnimationClip:
curve: curve:
serializedVersion: 2 serializedVersion: 2
m_Curve: m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3 - serializedVersion: 3
time: 0.11666667 time: 0.11666667
value: 0 value: 0
@@ -473,145 +468,6 @@ AnimationClip:
m_HasGenericRootTransform: 1 m_HasGenericRootTransform: 1
m_HasMotionFloatCurves: 0 m_HasMotionFloatCurves: 0
m_Events: [] 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 --- !u!114 &-4100604165561699402
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 1 m_ObjectHideFlags: 1
@@ -779,7 +635,6 @@ MonoBehaviour:
m_Tracks: m_Tracks:
- {fileID: -7584736085941489071} - {fileID: -7584736085941489071}
- {fileID: -2395336864975438248} - {fileID: -2395336864975438248}
- {fileID: -7231857257271738743}
- {fileID: -4100604165561699402} - {fileID: -4100604165561699402}
m_FixedDuration: 0 m_FixedDuration: 0
m_EditorSettings: m_EditorSettings:

View File

@@ -0,0 +1,197 @@
%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 &-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: PulverCucumberSmack_empty
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.TimelineAsset
m_Version: 0
m_Tracks:
- {fileID: -7584736085941489071}
- {fileID: -2395336864975438248}
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}

View File

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

View File

@@ -314,7 +314,8 @@ namespace Interactions
} }
} }
_followerController.GoToPointAndReturn(targetPosition, _playerRef.transform); // Use the new GoToPoint method instead of GoToPointAndReturn
_followerController.GoToPoint(targetPosition);
// Await follower arrival // Await follower arrival
await tcs.Task; await tcs.Task;
@@ -356,7 +357,8 @@ namespace Interactions
} }
} }
_followerController.GoToPointAndReturn(targetPosition, _playerRef.transform); // Use the new GoToPoint method instead of GoToPointAndReturn
_followerController.GoToPoint(targetPosition);
// Await follower arrival // Await follower arrival
await tcs.Task; await tcs.Task;
@@ -368,10 +370,32 @@ namespace Interactions
if (!_interactionInProgress) if (!_interactionInProgress)
return; return;
// Dispatch FollowerArrived event // Dispatch InteractingCharacterArrived event and WAIT for all actions to complete
// This ensures we wait for any timeline animations to finish before proceeding
Debug.Log("[Interactable] Follower arrived, dispatching InteractingCharacterArrived event and waiting for completion");
await DispatchEventAsync(InteractionEventType.InteractingCharacterArrived); await DispatchEventAsync(InteractionEventType.InteractingCharacterArrived);
Debug.Log("[Interactable] All InteractingCharacterArrived actions completed, proceeding with interaction");
// After all FollowerArrived actions complete, proceed to character arrived // Check if we have any components that might have paused the interaction flow
bool hasTimelineActions = false;
foreach (var action in _registeredActions)
{
if (action is InteractionTimelineAction timelineAction &&
timelineAction.respondToEvents.Contains(InteractionEventType.InteractingCharacterArrived) &&
timelineAction.pauseInteractionFlow)
{
hasTimelineActions = true;
break;
}
}
// Tell the follower to return to the player
if (_followerController != null && _playerRef != null)
{
_followerController.ReturnToPlayer(_playerRef.transform);
}
// After all InteractingCharacterArrived actions complete, proceed to character arrived
await BroadcastCharacterArrivedAsync(); await BroadcastCharacterArrivedAsync();
} }

View File

@@ -94,7 +94,7 @@ namespace Interactions
} }
_currentMapping = mapping; _currentMapping = mapping;
_currentTimelineIndex = 0; // _currentTimelineIndex = 0;
return await PlayTimelineSequence(player, follower); return await PlayTimelineSequence(player, follower);
} }
@@ -155,7 +155,7 @@ namespace Interactions
if (timelineAsset == null) if (timelineAsset == null)
{ {
Debug.LogWarning("[InteractionTimelineAction] Timeline asset is null"); Debug.LogWarning("[InteractionTimelineAction] Timeline asset is null");
return true; return true; // Return true to continue the interaction flow
} }
// Set the timeline asset // Set the timeline asset
@@ -205,14 +205,26 @@ namespace Interactions
// Create a task completion source to await the timeline completion // Create a task completion source to await the timeline completion
_currentPlaybackTCS = new TaskCompletionSource<bool>(); _currentPlaybackTCS = new TaskCompletionSource<bool>();
// Register for the stopped event if not already registered
playableDirector.stopped -= OnPlayableDirectorStopped;
playableDirector.stopped += OnPlayableDirectorStopped;
// Log the timeline playback
Debug.Log($"[InteractionTimelineAction] Playing timeline {timelineAsset.name} for event {mapping.eventType}");
// Play the timeline // Play the timeline
playableDirector.Play(); playableDirector.Play();
// Start a timeout coroutine for safety using the mapping's timeout // Start a timeout coroutine for safety using the mapping's timeout
StartCoroutine(TimeoutCoroutine(mapping.timeoutSeconds)); StartCoroutine(TimeoutCoroutine(mapping.timeoutSeconds));
// Wait for the timeline to complete (or timeout) // Await the timeline completion (will be signaled by the OnPlayableDirectorStopped callback)
bool result = await _currentPlaybackTCS.Task; bool result = await _currentPlaybackTCS.Task;
// Log completion
Debug.Log($"[InteractionTimelineAction] Timeline {timelineAsset.name} playback completed with result: {result}");
// Clear the task completion source
_currentPlaybackTCS = null; _currentPlaybackTCS = null;
return result; return result;
@@ -220,10 +232,13 @@ namespace Interactions
private void OnPlayableDirectorStopped(PlayableDirector director) private void OnPlayableDirectorStopped(PlayableDirector director)
{ {
if (director == playableDirector && _currentPlaybackTCS != null) if (director != playableDirector || _currentPlaybackTCS == null)
{ return;
_currentPlaybackTCS.TrySetResult(true);
} Debug.Log($"[InteractionTimelineAction] PlayableDirector stopped. Signaling completion.");
// Signal completion when the director stops
_currentPlaybackTCS.TrySetResult(true);
} }
private System.Collections.IEnumerator TimeoutCoroutine(float timeoutDuration) private System.Collections.IEnumerator TimeoutCoroutine(float timeoutDuration)

View File

@@ -268,25 +268,22 @@ public class FollowerController: MonoBehaviour
} }
} }
// Command follower to go to a specific point (pathfinding mode)
/// <summary> /// <summary>
/// Command follower to go to a specific point (pathfinding mode). /// Make the follower move to a specific point only. Will not automatically return.
/// </summary> /// </summary>
/// <param name="worldPosition">The world position to move to.</param> /// <param name="targetPosition">The position to move to.</param>
public void GoToPoint(Vector2 worldPosition) public void GoToPoint(Vector2 targetPosition)
{ {
_isManualFollowing = false; if (_pickupCoroutine != null)
StopCoroutine(_pickupCoroutine);
if (_aiPath != null) if (_aiPath != null)
{
_aiPath.enabled = true;
_aiPath.maxSpeed = _followerMaxSpeed; _aiPath.maxSpeed = _followerMaxSpeed;
_aiPath.destination = new Vector3(worldPosition.x, worldPosition.y, 0); _pickupCoroutine = StartCoroutine(GoToPointSequence(targetPosition));
}
} }
// Command follower to go to a specific point and return to player
/// <summary> /// <summary>
/// Command follower to go to a specific point and return to player. /// Command follower to go to a specific point and return to player after a brief delay.
/// Legacy method that combines GoToPoint and ReturnToPlayer for backward compatibility.
/// </summary> /// </summary>
/// <param name="itemPosition">The position of the item to pick up.</param> /// <param name="itemPosition">The position of the item to pick up.</param>
/// <param name="playerTransform">The transform of the player.</param> /// <param name="playerTransform">The transform of the player.</param>
@@ -299,6 +296,19 @@ public class FollowerController: MonoBehaviour
_pickupCoroutine = StartCoroutine(PickupSequence(itemPosition, playerTransform)); _pickupCoroutine = StartCoroutine(PickupSequence(itemPosition, playerTransform));
} }
/// <summary>
/// Make the follower return to the player after it has reached a point.
/// </summary>
/// <param name="playerTransform">The transform of the player to return to.</param>
public void ReturnToPlayer(Transform playerTransform)
{
if (_pickupCoroutine != null)
StopCoroutine(_pickupCoroutine);
if (_aiPath != null)
_aiPath.maxSpeed = _followerMaxSpeed;
_pickupCoroutine = StartCoroutine(ReturnToPlayerSequence(playerTransform));
}
private System.Collections.IEnumerator PickupSequence(Vector2 itemPosition, Transform playerTransform) private System.Collections.IEnumerator PickupSequence(Vector2 itemPosition, Transform playerTransform)
{ {
_isManualFollowing = false; _isManualFollowing = false;
@@ -340,6 +350,63 @@ public class FollowerController: MonoBehaviour
_aiPath.enabled = false; _aiPath.enabled = false;
_pickupCoroutine = null; _pickupCoroutine = null;
} }
private System.Collections.IEnumerator GoToPointSequence(Vector2 targetPosition)
{
_isManualFollowing = false;
_isReturningToPlayer = false;
if (_aiPath != null)
{
_aiPath.enabled = true;
_aiPath.maxSpeed = _followerMaxSpeed;
_aiPath.destination = new Vector3(targetPosition.x, targetPosition.y, 0);
}
// Wait until follower reaches target
while (Vector2.Distance(new Vector2(transform.position.x, transform.position.y),
new Vector2(targetPosition.x, targetPosition.y)) > GameManager.Instance.StopThreshold)
{
yield return null;
}
// Signal arrival
OnPickupArrived?.Invoke();
_pickupCoroutine = null;
}
private System.Collections.IEnumerator ReturnToPlayerSequence(Transform playerTransform)
{
if (_aiPath != null && playerTransform != null)
{
_aiPath.maxSpeed = _followerMaxSpeed;
_aiPath.destination = playerTransform.position;
}
_isReturningToPlayer = true;
// Wait until follower returns to player
while (playerTransform != null &&
Vector2.Distance(new Vector2(transform.position.x, transform.position.y),
new Vector2(playerTransform.position.x, playerTransform.position.y)) > GameManager.Instance.StopThreshold)
{
yield return null;
}
_isReturningToPlayer = false;
OnPickupReturned?.Invoke();
// Reset follower speed to normal after pickup
_followerMaxSpeed = _defaultFollowerMaxSpeed;
if (_aiPath != null)
_aiPath.maxSpeed = _followerMaxSpeed;
_isManualFollowing = true;
if (_aiPath != null)
_aiPath.enabled = false;
_pickupCoroutine = null;
}
#endregion Movement #endregion Movement
#region ItemInteractions #region ItemInteractions