Make combine animations and smacks ground Pulve

This commit is contained in:
Michal Pikulski
2025-10-27 14:43:24 +01:00
parent f5c1ae51cd
commit fdfddaec95
13 changed files with 788 additions and 70 deletions

View File

@@ -288,7 +288,7 @@ AnimationClip:
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 2.3999999
m_StopTime: 2.4
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
@@ -370,4 +370,11 @@ AnimationClip:
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []
m_Events:
- time: 2.4
functionName: OnStationaryAnimationComplete
data:
objectReferenceParameter: {fileID: 0}
floatParameter: 0
intParameter: 0
messageOptions: 0

View File

@@ -336,4 +336,11 @@ AnimationClip:
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []
m_Events:
- time: 1.6666666
functionName: OnStationaryAnimationComplete
data:
objectReferenceParameter: {fileID: 0}
floatParameter: 0
intParameter: 0
messageOptions: 0

View File

@@ -12,6 +12,22 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: fde0d25a170598d46a0b9dc16b4527a5, type: 3}
m_Name: ActivationPlayableAsset
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.ActivationPlayableAsset
--- !u!114 &-7800811525781169865
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: 15c38f6fa1940124db1ab7f6fe7268d1, type: 3}
m_Name: Signal Emitter
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.SignalEmitter
m_Time: 0
m_Retroactive: 0
m_EmitOnce: 0
m_Asset: {fileID: 11400000, guid: 2a32e2abdb44cb1469e5c6b9a25f98bc, type: 2}
--- !u!114 &-7584736085941489071
MonoBehaviour:
m_ObjectHideFlags: 1
@@ -139,6 +155,22 @@ MonoBehaviour:
m_bufferingTime: 0.1
m_ClipProperties:
volume: 0.683
--- !u!114 &-5035745444053599677
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: 15c38f6fa1940124db1ab7f6fe7268d1, type: 3}
m_Name: Signal Emitter
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.SignalEmitter
m_Time: 1.65
m_Retroactive: 0
m_EmitOnce: 0
m_Asset: {fileID: 11400000, guid: 2ec36cde76b6baf4299c0dd9ab54714e, type: 2}
--- !u!114 &-4664548104421960294
MonoBehaviour:
m_ObjectHideFlags: 1
@@ -491,12 +523,13 @@ MonoBehaviour:
- {fileID: 5194333105783184030}
- {fileID: 8484886637748558501}
- {fileID: 8776627858148209300}
- {fileID: 6964431640287062015}
m_FixedDuration: 0
m_EditorSettings:
m_Framerate: 60
m_ScenePreview: 1
m_DurationMode: 0
m_MarkerTrack: {fileID: 0}
m_MarkerTrack: {fileID: 7948415667162652308}
--- !u!114 &297111036028248502
MonoBehaviour:
m_ObjectHideFlags: 1
@@ -746,6 +779,54 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: fde0d25a170598d46a0b9dc16b4527a5, type: 3}
m_Name: ActivationPlayableAsset
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.ActivationPlayableAsset
--- !u!114 &6964431640287062015
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: b46e36075dd1c124a8422c228e75e1fb, type: 3}
m_Name: Signal Track
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.SignalTrack
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:
- {fileID: -7800811525781169865}
- {fileID: -5035745444053599677}
--- !u!114 &7948415667162652308
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 &8484886637748558501
MonoBehaviour:
m_ObjectHideFlags: 1

View File

@@ -14,6 +14,7 @@ GameObject:
- component: {fileID: 8947209170748834035}
- component: {fileID: 7852204877518954380}
- component: {fileID: 1621671461027776358}
- component: {fileID: 7002695641417196458}
m_Layer: 8
m_Name: PulverCharacter
m_TagString: Pulver
@@ -184,6 +185,51 @@ MonoBehaviour:
bezierTangentLength: 0.4
offset: 0.2
factor: 0.1
--- !u!114 &7002695641417196458
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1102400833121127473}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e52de21a22b6dd44c9cc19f810c65059, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.SignalReceiver
m_Events:
m_Signals:
- {fileID: 11400000, guid: 2a32e2abdb44cb1469e5c6b9a25f98bc, type: 2}
- {fileID: 11400000, guid: 2ec36cde76b6baf4299c0dd9ab54714e, type: 2}
m_Events:
- m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 3435632802124758411}
m_TargetAssemblyTypeName: FollowerController, AppleHillsScripts
m_MethodName: PauseMovement
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
- m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 3435632802124758411}
m_TargetAssemblyTypeName: FollowerController, AppleHillsScripts
m_MethodName: ResumeMovement
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
--- !u!1 &5934518940303293264
GameObject:
m_ObjectHideFlags: 0
@@ -338,8 +384,29 @@ PrefabInstance:
- {fileID: 2732140975288177209, guid: e3b439d398cffdd4194cdb360a46c5a6, type: 3}
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_AddedComponents:
- targetCorrespondingSourceObject: {fileID: 1102468210854536367, guid: e3b439d398cffdd4194cdb360a46c5a6, type: 3}
insertIndex: -1
addedObject: {fileID: 3454096590710680423}
m_SourcePrefab: {fileID: 100100000, guid: e3b439d398cffdd4194cdb360a46c5a6, type: 3}
--- !u!1 &780600094299918916 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 1102468210854536367, guid: e3b439d398cffdd4194cdb360a46c5a6, type: 3}
m_PrefabInstance: {fileID: 403634400421951211}
m_PrefabAsset: {fileID: 0}
--- !u!114 &3454096590710680423
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 780600094299918916}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 39f2e64420884f11a9022fea7b3be5d0, type: 3}
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::FollowerAnimationEventBridge
followerController: {fileID: 3435632802124758411}
--- !u!4 &6418503932309983819 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 6668392923879433376, guid: e3b439d398cffdd4194cdb360a46c5a6, type: 3}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,40 @@
using UnityEngine;
namespace Movement
{
/// <summary>
/// Bridge script that forwards Animation Events from the character art child object
/// to the FollowerController on the parent GameObject.
/// Attach this to the same GameObject that has the Animator component.
/// </summary>
public class FollowerAnimationEventBridge : MonoBehaviour
{
[SerializeField] private FollowerController followerController;
void Awake()
{
// Find the FollowerController on the parent
if (followerController == null)
{
followerController = GetComponentInParent<FollowerController>();
}
if (followerController == null)
{
Debug.LogError("[FollowerAnimationEventBridge] Could not find FollowerController in parent. This script must be on a child of the FollowerController.");
}
}
/// <summary>
/// Called by Animation Events. Forwards to the parent FollowerController.
/// </summary>
public void OnStationaryAnimationComplete()
{
if (followerController != null)
{
followerController.OnStationaryAnimationComplete();
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 39f2e64420884f11a9022fea7b3be5d0
timeCreated: 1761571513

View File

@@ -11,6 +11,8 @@ using Core;
/// </summary>
public class FollowerController: MonoBehaviour
{
private static readonly int CombineTrigger = Animator.StringToHash("Combine");
[Header("Follower Settings")]
public bool debugDrawTarget = true;
/// <summary>
@@ -52,6 +54,11 @@ public class FollowerController: MonoBehaviour
/// </summary>
public SpriteRenderer heldObjectRenderer;
// Stationary animation state
private bool _isPlayingStationaryAnimation = false;
private Coroutine _stationaryAnimationCoroutine;
private System.Action _stationaryAnimationCallback;
private bool _isReturningToPlayer = false;
private float _playerMaxSpeed = 5f;
private float _followerMaxSpeed = 6f;
@@ -117,6 +124,19 @@ public class FollowerController: MonoBehaviour
return;
}
// Skip all movement logic when playing a stationary animation
if (_isPlayingStationaryAnimation)
{
// Still update animator with zero speed to maintain idle state
if (_animator != null)
{
_animator.SetFloat("Speed", 0f);
_animator.SetFloat("DirX", _lastDirX);
_animator.SetFloat("DirY", _lastDirY);
}
return;
}
_timer += Time.deltaTime;
if (_timer >= _settings.FollowUpdateInterval)
{
@@ -420,6 +440,100 @@ public class FollowerController: MonoBehaviour
}
#endregion Movement
#region StationaryAnimations
/// <summary>
/// Pauses all movement. Can be called directly from Timeline, Animation Events, or code.
/// Call ResumeMovement() to resume.
/// </summary>
public void PauseMovement()
{
_isPlayingStationaryAnimation = true;
_currentSpeed = 0f;
Logging.Debug("[FollowerController] Movement paused");
}
/// <summary>
/// Resumes movement after being paused. Can be called from Timeline, Animation Events, or code.
/// </summary>
public void ResumeMovement()
{
_isPlayingStationaryAnimation = false;
Logging.Debug("[FollowerController] Movement resumed");
}
/// <summary>
/// Plays an animation while pausing all movement. Resumes movement when animation completes.
/// Uses a hybrid approach: Animation Events (if set up) OR timeout fallback (if not).
/// To use Animation Events: Add an event at the end of your animation that calls OnStationaryAnimationComplete().
/// </summary>
/// <param name="triggerName">The animator trigger name to activate</param>
/// <param name="maxDuration">Maximum time to wait before auto-resuming (fallback if no Animation Event)</param>
/// <param name="onComplete">Optional callback to invoke when animation completes</param>
public void PlayAnimationStationary(string triggerName, float maxDuration = 2f, System.Action onComplete = null)
{
if (_animator == null)
{
Logging.Warning("[FollowerController] Cannot play stationary animation - no Animator found");
onComplete?.Invoke();
return;
}
// Stop any existing stationary animation
if (_stationaryAnimationCoroutine != null)
{
StopCoroutine(_stationaryAnimationCoroutine);
}
_isPlayingStationaryAnimation = true;
_stationaryAnimationCallback = onComplete;
_currentSpeed = 0f; // Immediately stop movement
// Trigger the animation
_animator.SetTrigger(triggerName);
// Start timeout coroutine (will be stopped early if Animation Event fires)
_stationaryAnimationCoroutine = StartCoroutine(StationaryAnimationTimeoutCoroutine(maxDuration));
}
private System.Collections.IEnumerator StationaryAnimationTimeoutCoroutine(float maxDuration)
{
yield return new WaitForSeconds(maxDuration);
// If we reach here, the Animation Event didn't fire - use fallback
Logging.Debug($"[FollowerController] Stationary animation timeout reached ({maxDuration}s) - resuming movement");
ResumeMovementAfterAnimation();
}
/// <summary>
/// Public method to be called by Animation Events at the end of stationary animations.
/// Add this as an Animation Event in your animation clip for frame-perfect timing.
/// </summary>
public void OnStationaryAnimationComplete()
{
Logging.Debug("[FollowerController] Stationary animation completed via Animation Event");
ResumeMovementAfterAnimation();
}
private void ResumeMovementAfterAnimation()
{
if (!_isPlayingStationaryAnimation) return; // Already resumed
// Stop the timeout coroutine if it's still running
if (_stationaryAnimationCoroutine != null)
{
StopCoroutine(_stationaryAnimationCoroutine);
_stationaryAnimationCoroutine = null;
}
_isPlayingStationaryAnimation = false;
// Invoke callback if provided
var callback = _stationaryAnimationCallback;
_stationaryAnimationCallback = null;
callback?.Invoke();
}
#endregion StationaryAnimations
#region ItemInteractions
public void TryPickupItem(GameObject itemObject, PickupItemData itemData, bool dropItem = true)
{
@@ -445,7 +559,7 @@ public class FollowerController: MonoBehaviour
public CombinationResult TryCombineItems(Pickup pickupA, out GameObject newItem)
{
_animator.ResetTrigger("Combine");
_animator.ResetTrigger(CombineTrigger);
newItem = null;
if (_cachedPickupObject == null)
{
@@ -468,7 +582,7 @@ public class FollowerController: MonoBehaviour
Destroy(pickupA.gameObject);
Destroy(pickupB.gameObject);
TryPickupItem(newItem, itemData);
_animator.SetTrigger("Combine");
PlayAnimationStationary("Combine", 10.0f);
return CombinationResult.Successful;
}

8
Assets/Signals.meta Normal file
View File

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

View File

@@ -0,0 +1,14 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d6fa2d92fc1b3f34da284357edf89c3b, type: 3}
m_Name: PausePulverMovement
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.SignalAsset

View File

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

View File

@@ -0,0 +1,14 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d6fa2d92fc1b3f34da284357edf89c3b, type: 3}
m_Name: ResumePulverMovement
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.SignalAsset

View File

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