Finalize work on the dump controller switching
This commit is contained in:
@@ -57,7 +57,7 @@ Material:
|
|||||||
- _Thickness: 0.01
|
- _Thickness: 0.01
|
||||||
m_Colors:
|
m_Colors:
|
||||||
- White: {r: 1, g: 1, b: 1, a: 1}
|
- White: {r: 1, g: 1, b: 1, a: 1}
|
||||||
- _Color: {r: 1, g: 0.87843144, b: 0.57254905, a: 1}
|
- _Color: {r: 1, g: 0.8784314, b: 0.57254905, a: 1}
|
||||||
- _Colour: {r: 0.9341286, g: 1, b: 0, a: 1}
|
- _Colour: {r: 0.9341286, g: 1, b: 0, a: 1}
|
||||||
m_BuildTextureStacks: []
|
m_BuildTextureStacks: []
|
||||||
m_AllowLocking: 1
|
m_AllowLocking: 1
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -363479,6 +363479,10 @@ PrefabInstance:
|
|||||||
propertyPath: targetCameraState
|
propertyPath: targetCameraState
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 5320225058563658919, guid: 67a60833f9f205940a2308bd74a2863e, type: 3}
|
||||||
|
propertyPath: characterToInteract
|
||||||
|
value: 2
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 5320225058563658919, guid: 67a60833f9f205940a2308bd74a2863e, type: 3}
|
- target: {fileID: 5320225058563658919, guid: 67a60833f9f205940a2308bd74a2863e, type: 3}
|
||||||
propertyPath: targetControllerName
|
propertyPath: targetControllerName
|
||||||
value: trafalgar
|
value: trafalgar
|
||||||
@@ -365941,6 +365945,10 @@ PrefabInstance:
|
|||||||
propertyPath: m_Name
|
propertyPath: m_Name
|
||||||
value: Player
|
value: Player
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7393789300602426170, guid: 301b4e0735896334f8f6fb9a68a7e419, type: 3}
|
||||||
|
propertyPath: endReachedDistance
|
||||||
|
value: 0.5
|
||||||
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
|
|||||||
@@ -330,6 +330,31 @@ namespace Input
|
|||||||
|
|
||||||
#region IInteractingCharacter Implementation
|
#region IInteractingCharacter Implementation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controller-driven interaction movement. Base implementation moves this controller to the interactable.
|
||||||
|
/// Override in derived classes for custom behavior (e.g., PlayerTouchController handles follower dispatch).
|
||||||
|
/// </summary>
|
||||||
|
public virtual async System.Threading.Tasks.Task<bool> MoveToInteractableAsync(Interactions.InteractableBase interactable)
|
||||||
|
{
|
||||||
|
// Default behavior: move self to interactable position
|
||||||
|
Vector3 targetPosition = interactable.transform.position;
|
||||||
|
|
||||||
|
// Check for custom CharacterMoveToTarget
|
||||||
|
var moveTargets = interactable.GetComponentsInChildren<Interactions.CharacterMoveToTarget>();
|
||||||
|
foreach (var target in moveTargets)
|
||||||
|
{
|
||||||
|
if (target.characterType == Interactions.CharacterToInteract.Trafalgar ||
|
||||||
|
target.characterType == Interactions.CharacterToInteract.Both)
|
||||||
|
{
|
||||||
|
targetPosition = target.GetTargetPosition();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use MovementUtilities to handle movement
|
||||||
|
return await Utils.MovementUtilities.MoveToPositionAsync(this, targetPosition);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Moves the character to a specific target position and notifies via events when arrived or cancelled.
|
/// Moves the character to a specific target position and notifies via events when arrived or cancelled.
|
||||||
/// This is used by systems like interactions to orchestrate scripted movement.
|
/// This is used by systems like interactions to orchestrate scripted movement.
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using UnityEngine;
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Input
|
namespace Input
|
||||||
{
|
{
|
||||||
@@ -9,6 +10,14 @@ namespace Input
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IInteractingCharacter
|
public interface IInteractingCharacter
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Controller-driven interaction movement. Each controller implements its own behavior
|
||||||
|
/// based on the interactable's settings (characterToInteract, CharacterMoveToTarget, etc.)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="interactable">The interactable to move to</param>
|
||||||
|
/// <returns>True if movement succeeded and character arrived, false if cancelled/failed</returns>
|
||||||
|
Task<bool> MoveToInteractableAsync(Interactions.InteractableBase interactable);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Moves character to target position and notifies when arrived/cancelled
|
/// Moves character to target position and notifies when arrived/cancelled
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -46,6 +46,114 @@ namespace Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region IInteractingCharacter Override
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PlayerTouchController-specific interaction movement.
|
||||||
|
/// Handles main character movement + follower dispatch based on interactable.characterToInteract setting.
|
||||||
|
/// </summary>
|
||||||
|
public override async System.Threading.Tasks.Task<bool> MoveToInteractableAsync(Interactions.InteractableBase interactable)
|
||||||
|
{
|
||||||
|
var characterToInteract = interactable.characterToInteract;
|
||||||
|
|
||||||
|
// If None, skip movement
|
||||||
|
if (characterToInteract == Interactions.CharacterToInteract.None)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine stop distance based on interaction type
|
||||||
|
float stopDistance;
|
||||||
|
if (characterToInteract == Interactions.CharacterToInteract.Trafalgar)
|
||||||
|
{
|
||||||
|
// Move ONLY main character directly to item (close distance)
|
||||||
|
stopDistance = Core.GameManager.Instance.PlayerStopDistanceDirectInteraction;
|
||||||
|
}
|
||||||
|
else // Pulver or Both
|
||||||
|
{
|
||||||
|
// Move main character to radius (far distance)
|
||||||
|
stopDistance = Core.GameManager.Instance.PlayerStopDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate stop position for main character
|
||||||
|
Vector3 stopPoint = interactable.transform.position;
|
||||||
|
bool customTargetFound = false;
|
||||||
|
|
||||||
|
// Check for custom CharacterMoveToTarget for main character
|
||||||
|
var moveTargets = interactable.GetComponentsInChildren<Interactions.CharacterMoveToTarget>();
|
||||||
|
foreach (var target in moveTargets)
|
||||||
|
{
|
||||||
|
if (target.characterType == Interactions.CharacterToInteract.Trafalgar ||
|
||||||
|
target.characterType == Interactions.CharacterToInteract.Both)
|
||||||
|
{
|
||||||
|
stopPoint = target.GetTargetPosition();
|
||||||
|
customTargetFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no custom target, calculate based on distance
|
||||||
|
if (!customTargetFound)
|
||||||
|
{
|
||||||
|
stopPoint = Utils.MovementUtilities.CalculateStopPosition(
|
||||||
|
interactable.transform.position,
|
||||||
|
transform.position,
|
||||||
|
stopDistance
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move main character
|
||||||
|
bool mainCharacterArrived = await Utils.MovementUtilities.MoveToPositionAsync(this, stopPoint);
|
||||||
|
|
||||||
|
if (!mainCharacterArrived)
|
||||||
|
{
|
||||||
|
return false; // Movement cancelled
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle follower dispatch based on interaction type
|
||||||
|
if (characterToInteract == Interactions.CharacterToInteract.Pulver ||
|
||||||
|
characterToInteract == Interactions.CharacterToInteract.Both)
|
||||||
|
{
|
||||||
|
// Find follower and dispatch to interactable
|
||||||
|
var followerController = FindFirstObjectByType<FollowerController>();
|
||||||
|
if (followerController != null)
|
||||||
|
{
|
||||||
|
// Determine follower target position
|
||||||
|
Vector3 followerTarget = interactable.transform.position;
|
||||||
|
|
||||||
|
// Check for custom target for Pulver
|
||||||
|
foreach (var target in moveTargets)
|
||||||
|
{
|
||||||
|
if (target.characterType == Interactions.CharacterToInteract.Pulver ||
|
||||||
|
target.characterType == Interactions.CharacterToInteract.Both)
|
||||||
|
{
|
||||||
|
followerTarget = target.GetTargetPosition();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for follower to arrive
|
||||||
|
var tcs = new System.Threading.Tasks.TaskCompletionSource<bool>();
|
||||||
|
|
||||||
|
void OnFollowerArrived()
|
||||||
|
{
|
||||||
|
followerController.OnPickupArrived -= OnFollowerArrived;
|
||||||
|
followerController.ReturnToPlayer(transform);
|
||||||
|
tcs.TrySetResult(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
followerController.OnPickupArrived += OnFollowerArrived;
|
||||||
|
followerController.GoToPoint(followerTarget);
|
||||||
|
|
||||||
|
await tcs.Task;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // Success
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Save/Load Lifecycle Hooks
|
#region Save/Load Lifecycle Hooks
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using UnityEngine.Events;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Core;
|
using Core;
|
||||||
using Core.Lifecycle;
|
using Core.Lifecycle;
|
||||||
using Utils;
|
|
||||||
|
|
||||||
namespace Interactions
|
namespace Interactions
|
||||||
{
|
{
|
||||||
@@ -146,7 +145,14 @@ namespace Interactions
|
|||||||
await DispatchEventAsync(InteractionEventType.InteractionStarted, playerRef);
|
await DispatchEventAsync(InteractionEventType.InteractionStarted, playerRef);
|
||||||
|
|
||||||
// 5. Orchestrate character movement
|
// 5. Orchestrate character movement
|
||||||
await MoveCharactersAsync(playerRef);
|
bool movementSucceeded = await MoveCharactersAsync(playerRef);
|
||||||
|
|
||||||
|
// If movement was cancelled, stop the interaction flow
|
||||||
|
if (!movementSucceeded)
|
||||||
|
{
|
||||||
|
Logging.Debug($"[Interactable] Interaction cancelled due to movement failure on {gameObject.name}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 6. Virtual hook: Arrival reaction
|
// 6. Virtual hook: Arrival reaction
|
||||||
OnInteractingCharacterArrived();
|
OnInteractingCharacterArrived();
|
||||||
@@ -280,130 +286,37 @@ namespace Interactions
|
|||||||
#region Character Movement Orchestration
|
#region Character Movement Orchestration
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Orchestrates character movement based on characterToInteract setting.
|
/// Delegates movement to the interacting character's controller.
|
||||||
|
/// Each controller implements its own movement behavior based on this interactable's settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task MoveCharactersAsync(PlayerTouchController playerRef = null)
|
/// <returns>True if movement succeeded, false if cancelled or failed</returns>
|
||||||
|
private async Task<bool> MoveCharactersAsync(PlayerTouchController playerRef = null)
|
||||||
{
|
{
|
||||||
if (_interactingCharacter == null)
|
if (_interactingCharacter == null)
|
||||||
{
|
{
|
||||||
Logging.Debug($"[Interactable] No interacting character found. Aborting interaction.");
|
Logging.Debug($"[Interactable] No interacting character found. Aborting interaction.");
|
||||||
interactionInterrupted.Invoke();
|
interactionInterrupted.Invoke();
|
||||||
await DispatchEventAsync(InteractionEventType.InteractionInterrupted, playerRef);
|
await DispatchEventAsync(InteractionEventType.InteractionInterrupted, playerRef);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If characterToInteract is None, skip movement
|
// If characterToInteract is None, skip movement
|
||||||
if (characterToInteract == CharacterToInteract.None)
|
if (characterToInteract == CharacterToInteract.None)
|
||||||
{
|
{
|
||||||
return; // Continue to arrival
|
return true; // Continue to arrival
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the appropriate character based on characterToInteract setting
|
// Delegate to controller - let it decide how to handle the interaction
|
||||||
if (characterToInteract == CharacterToInteract.Trafalgar)
|
bool arrived = await _interactingCharacter.MoveToInteractableAsync(this);
|
||||||
{
|
|
||||||
await MoveCharacterAsync(_interactingCharacter, CharacterToInteract.Trafalgar, playerRef);
|
|
||||||
}
|
|
||||||
else if (characterToInteract == CharacterToInteract.Pulver)
|
|
||||||
{
|
|
||||||
await MoveCharacterAsync(_interactingCharacter, CharacterToInteract.Pulver, playerRef);
|
|
||||||
}
|
|
||||||
else if (characterToInteract == CharacterToInteract.Both)
|
|
||||||
{
|
|
||||||
await MoveCharacterAsync(_interactingCharacter, CharacterToInteract.Trafalgar, playerRef); // Move first character to range
|
|
||||||
await MoveFollowerAsync(playerRef); // Then move follower to interaction point
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Moves a character controller to the interaction point or custom target.
|
|
||||||
/// Works with any controller implementing IInteractingCharacter.
|
|
||||||
/// </summary>
|
|
||||||
private async Task MoveCharacterAsync(IInteractingCharacter character, CharacterToInteract targetCharacterType, PlayerTouchController playerRef = null)
|
|
||||||
{
|
|
||||||
if (character == null)
|
|
||||||
{
|
|
||||||
Logging.Warning("[Interactable] Cannot move null character");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 stopPoint = transform.position; // Default to interactable position
|
|
||||||
bool customTargetFound = false;
|
|
||||||
|
|
||||||
// Check for a CharacterMoveToTarget component
|
|
||||||
CharacterMoveToTarget[] moveTargets = GetComponentsInChildren<CharacterMoveToTarget>();
|
|
||||||
foreach (var target in moveTargets)
|
|
||||||
{
|
|
||||||
if (target.characterType == targetCharacterType || target.characterType == CharacterToInteract.Both)
|
|
||||||
{
|
|
||||||
stopPoint = target.GetTargetPosition();
|
|
||||||
customTargetFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no custom target, use default distance
|
|
||||||
if (!customTargetFound)
|
|
||||||
{
|
|
||||||
Vector3 interactablePos = transform.position;
|
|
||||||
Vector3 characterPos = character.transform.position;
|
|
||||||
float stopDistance = targetCharacterType == CharacterToInteract.Pulver
|
|
||||||
? GameManager.Instance.PlayerStopDistance
|
|
||||||
: GameManager.Instance.PlayerStopDistanceDirectInteraction;
|
|
||||||
stopPoint = MovementUtilities.CalculateStopPosition(interactablePos, characterPos, stopDistance);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use MovementUtilities to handle movement
|
|
||||||
bool arrived = await MovementUtilities.MoveToPositionAsync(character, stopPoint);
|
|
||||||
|
|
||||||
if (!arrived)
|
if (!arrived)
|
||||||
{
|
{
|
||||||
_ = HandleInteractionCancelledAsync(playerRef);
|
Logging.Debug($"[Interactable] Movement cancelled for {gameObject.name}");
|
||||||
}
|
await HandleInteractionCancelledAsync(playerRef);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
return true;
|
||||||
/// Moves the follower to the interaction point or custom target.
|
|
||||||
/// </summary>
|
|
||||||
private async Task MoveFollowerAsync(PlayerTouchController playerRef = null)
|
|
||||||
{
|
|
||||||
if (FollowerController == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Check for a CharacterMoveToTarget component for Pulver or Both
|
|
||||||
Vector3 targetPosition = transform.position;
|
|
||||||
CharacterMoveToTarget[] moveTargets = GetComponentsInChildren<CharacterMoveToTarget>();
|
|
||||||
foreach (var target in moveTargets)
|
|
||||||
{
|
|
||||||
if (target.characterType == CharacterToInteract.Pulver || target.characterType == CharacterToInteract.Both)
|
|
||||||
{
|
|
||||||
targetPosition = target.GetTargetPosition();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for follower to arrive
|
|
||||||
var tcs = new TaskCompletionSource<bool>();
|
|
||||||
|
|
||||||
void OnFollowerArrivedLocal()
|
|
||||||
{
|
|
||||||
if (FollowerController != null)
|
|
||||||
{
|
|
||||||
FollowerController.OnPickupArrived -= OnFollowerArrivedLocal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell follower to return to player if we have a PlayerTouchController reference
|
|
||||||
if (FollowerController != null && playerRef != null)
|
|
||||||
{
|
|
||||||
FollowerController.ReturnToPlayer(playerRef.transform);
|
|
||||||
}
|
|
||||||
|
|
||||||
tcs.TrySetResult(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
FollowerController.OnPickupArrived += OnFollowerArrivedLocal;
|
|
||||||
FollowerController.GoToPoint(targetPosition);
|
|
||||||
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -99,6 +99,33 @@ namespace Minigames.TrashMaze.Core
|
|||||||
{
|
{
|
||||||
_visionRadius = Mathf.Max(0.1f, radius);
|
_visionRadius = Mathf.Max(0.1f, radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region IInteractingCharacter Override
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PulverController-specific interaction movement.
|
||||||
|
/// Moves Pulver to the interactable using the main character's stop distance.
|
||||||
|
/// No follower logic since Pulver is alone in the maze.
|
||||||
|
/// </summary>
|
||||||
|
public override async System.Threading.Tasks.Task<bool> MoveToInteractableAsync(Interactions.InteractableBase interactable)
|
||||||
|
{
|
||||||
|
// Use the same stop distance as main character for consistency
|
||||||
|
float stopDistance = GameManager.Instance.PlayerStopDistance;
|
||||||
|
|
||||||
|
// Calculate stop position
|
||||||
|
Vector3 stopPoint = Utils.MovementUtilities.CalculateStopPosition(
|
||||||
|
interactable.transform.position,
|
||||||
|
transform.position,
|
||||||
|
stopDistance
|
||||||
|
);
|
||||||
|
|
||||||
|
Logging.Debug($"[PulverController] Moving to interactable {interactable.gameObject.name} at stop distance {stopDistance}");
|
||||||
|
|
||||||
|
// Use MovementUtilities to handle movement
|
||||||
|
return await Utils.MovementUtilities.MoveToPositionAsync(this, stopPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ MonoBehaviour:
|
|||||||
defaultPlayerMovement:
|
defaultPlayerMovement:
|
||||||
moveSpeed: 15
|
moveSpeed: 15
|
||||||
maxAcceleration: 10000
|
maxAcceleration: 10000
|
||||||
stopDistance: 0.1
|
stopDistance: 0.5
|
||||||
useRigidbody: 0
|
useRigidbody: 0
|
||||||
defaultHoldMovementMode: 1
|
defaultHoldMovementMode: 1
|
||||||
trashMazeMovement:
|
trashMazeMovement:
|
||||||
moveSpeed: 15
|
moveSpeed: 15
|
||||||
maxAcceleration: 10000
|
maxAcceleration: 10000
|
||||||
stopDistance: 0.1
|
stopDistance: 0.5
|
||||||
useRigidbody: 0
|
useRigidbody: 0
|
||||||
defaultHoldMovementMode: 1
|
defaultHoldMovementMode: 1
|
||||||
followerMovement:
|
followerMovement:
|
||||||
|
|||||||
Reference in New Issue
Block a user