- Added InteractionTimelineAction component for timeline-driven interactions - Implemented custom editor for timeline event mapping - Updated interaction event flow to support timeline actions - Enhanced character move target configuration - Improved inspector UI for interactable components - Added technical documentation for interaction system - Refactored interaction action base classes for extensibility - Fixed issues with character binding in timelines Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com> Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com> Reviewed-on: #17
276 lines
10 KiB
Markdown
276 lines
10 KiB
Markdown
# Apple Hills Interaction System
|
|
|
|
This document provides a comprehensive overview of the interaction system in Apple Hills, detailing how interactions are structured, configured, and extended with custom actions.
|
|
|
|
## Overview
|
|
|
|
The Apple Hills interaction system allows players to interact with objects in the game world. It supports character movement to interaction points, timed and conditional interactions, and complex behaviors through a component-based architecture. The system is particularly powerful when combined with the Timeline feature for creating cinematic sequences during interactions.
|
|
|
|
## Core Components
|
|
|
|
The interaction system consists of several key components that work together:
|
|
|
|
### Interactable
|
|
|
|
The `Interactable` component is the foundation of the interaction system. It:
|
|
- Handles player input (tapping/clicking)
|
|
- Manages which character(s) should interact (Trafalgar, Pulver, or both)
|
|
- Coordinates character movement to interaction points
|
|
- Dispatches events during the interaction lifecycle
|
|
- Manages one-time interactions and cooldowns
|
|
|
|

|
|
|
|
### CharacterMoveToTarget
|
|
|
|
The `CharacterMoveToTarget` component defines positions where characters should move when interacting:
|
|
- Can be configured for specific characters (Trafalgar, Pulver, or both)
|
|
- Supports position offsets for fine-tuning
|
|
- Provides visual gizmos in the editor for easy positioning
|
|
- Multiple targets can be set up for complex interactions
|
|
|
|

|
|
|
|
### Interaction Actions
|
|
|
|
Actions are components that respond to interaction events and execute custom behavior:
|
|
- Derive from the abstract `InteractionActionBase` class
|
|
- Can be attached to interactable objects
|
|
- Multiple actions can be added to a single interactable
|
|
- Actions can optionally block the interaction flow until completion
|
|
|
|
The inspector for all interaction action components shows the key parameters from InteractionActionBase, with custom configuration options for specific action types:
|
|
|
|

|
|
|
|
### Interaction Requirements
|
|
|
|
Requirements are components that determine whether an interaction can occur:
|
|
- Derive from the abstract `InteractionRequirementBase` class
|
|
- Can prevent interactions based on custom conditions
|
|
- Multiple requirements can be added to a single interactable
|
|
- Used for creating conditional interactions (e.g., requiring an item)
|
|
|
|
## Interaction Event Flow
|
|
|
|
Interactions follow a defined event flow:
|
|
|
|
1. **InteractionStarted**: Triggered when the player initiates an interaction
|
|
2. **PlayerArrived**: Triggered when the player character reaches the interaction point
|
|
3. **InteractingCharacterArrived**: Triggered when the interacting character (often Pulver) reaches the interaction point
|
|
4. **InteractionComplete**: Triggered when the interaction is completed
|
|
5. **InteractionInterrupted**: Triggered if the interaction is interrupted before completion
|
|
|
|
## InteractionActionBase
|
|
|
|
The `InteractionActionBase` is the abstract base class for all interaction actions. It provides the framework for creating custom behaviors that respond to interaction events.
|
|
|
|
### Key Features
|
|
|
|
- **Event Filtering**: Actions can choose which interaction events to respond to
|
|
- **Flow Control**: Actions can optionally pause the interaction flow until completion
|
|
- **Asynchronous Execution**: Actions use `async/await` pattern for time-consuming operations
|
|
- **Character References**: Actions receive references to both player and follower characters
|
|
|
|
### Implementation
|
|
|
|
```csharp
|
|
public abstract class InteractionActionBase : MonoBehaviour
|
|
{
|
|
// Which events this action should respond to
|
|
public List<InteractionEventType> respondToEvents;
|
|
|
|
// Whether to pause the interaction flow during execution
|
|
public bool pauseInteractionFlow;
|
|
|
|
// The main execution method that must be implemented by derived classes
|
|
protected abstract Task<bool> ExecuteAsync(
|
|
InteractionEventType eventType,
|
|
PlayerTouchController player,
|
|
FollowerController follower);
|
|
|
|
// Optional method for adding execution conditions
|
|
protected virtual bool ShouldExecute(
|
|
InteractionEventType eventType,
|
|
PlayerTouchController player,
|
|
FollowerController follower)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
```
|
|
|
|
## InteractionTimelineAction
|
|
|
|
The `InteractionTimelineAction` is a powerful action that plays Unity Timeline sequences during interactions. It enables cinematic sequences, character animations, camera movements, and more.
|
|
|
|
### Key Features
|
|
|
|
- **Multiple Timeline Support**: Can play different timelines for different interaction events
|
|
- **Timeline Sequences**: Can play multiple timelines in sequence for a single event
|
|
- **Character Binding**: Automatically binds player and follower characters to timeline tracks
|
|
- **Flow Control**: Waits for timeline completion before continuing interaction flow
|
|
- **Timeout Safety**: Includes a configurable timeout to prevent interactions from getting stuck
|
|
- **Looping Options**: Supports looping all timelines or just the last timeline in a sequence
|
|
|
|
### Timeline Event Mapping
|
|
|
|
Each mapping connects an interaction event to one or more timeline assets:
|
|
|
|
```csharp
|
|
public class TimelineEventMapping
|
|
{
|
|
// The event that triggers this timeline
|
|
public InteractionEventType eventType;
|
|
|
|
// The timeline assets to play (in sequence)
|
|
public PlayableAsset[] timelines;
|
|
|
|
// Character binding options
|
|
public bool bindPlayerCharacter;
|
|
public bool bindPulverCharacter;
|
|
public string playerTrackName = "Player";
|
|
public string pulverTrackName = "Pulver";
|
|
|
|
// Playback options
|
|
public float timeoutSeconds = 30f;
|
|
public bool loopLast = false;
|
|
public bool loopAll = false;
|
|
}
|
|
```
|
|
|
|
### Custom Editor
|
|
|
|
The `InteractionTimelineAction` includes a custom editor that makes it easy to configure:
|
|
- Quick buttons to add mappings for common events
|
|
- Character binding options
|
|
- Timeline sequence configuration
|
|
- Validation warnings for misconfigured timelines
|
|
|
|

|
|
|
|
### Implementation Pattern
|
|
|
|
For a cinematic interaction with timelines:
|
|
|
|
1. Add an `Interactable` component to your object
|
|
2. Add an `InteractionTimelineAction` component to the same object
|
|
3. Set up character move targets if needed
|
|
4. Create timeline assets for each interaction phase
|
|
5. Configure the timeline mappings in the inspector
|
|
6. Test the interaction in play mode
|
|
|
|
### Timeline Configuration
|
|
|
|
When setting up a timeline for interaction, you'll need to create a Timeline asset and configure it in Unity's Timeline editor:
|
|
|
|

|
|
|
|
## Working with the Interactable Editor
|
|
|
|
The `Interactable` component includes a custom editor that enhances the workflow:
|
|
|
|
### Character Move Target Creation
|
|
|
|
The editor provides buttons to easily create character move targets:
|
|
- "Add Trafalgar Target" - Creates a move target for the player character
|
|
- "Add Pulver Target" - Creates a move target for the follower character
|
|
- "Add Both Characters Target" - Creates a move target for both characters
|
|
|
|

|
|
|
|
### Target Visualization
|
|
|
|
The editor displays the number of targets for each character type and warns about potential conflicts:
|
|
```
|
|
Trafalgar Targets: 1, Pulver Targets: 1, Both Targets: 0
|
|
```
|
|
|
|
If multiple conflicting targets are detected, a warning is displayed to help prevent unexpected behavior.
|
|
|
|
## Best Practices
|
|
|
|
### Target Positioning
|
|
|
|
- Place character targets with appropriate spacing to prevent characters from overlapping
|
|
- Consider the character's facing direction (targets automatically make characters face the interactable)
|
|
- Use the position offset for fine-tuning without moving the actual target GameObject
|
|
|
|

|
|
|
|
### Timeline Design
|
|
|
|
- Keep timelines modular and focused on specific actions
|
|
- Use signals to trigger game events from timelines
|
|
- Consider using director notification tracks for advanced timeline integration
|
|
- Test timelines with actual characters to ensure animations blend correctly
|
|
|
|
### Action Combinations
|
|
|
|
- Combine multiple actions for complex behaviors (e.g., dialogue + timeline)
|
|
- Order actions in the Inspector to control execution priority
|
|
- Use the `pauseInteractionFlow` option strategically to control sequence flow
|
|
|
|
## Technical Reference
|
|
|
|
### InteractionEventType
|
|
|
|
```csharp
|
|
public enum InteractionEventType
|
|
{
|
|
InteractionStarted, // When interaction is first triggered
|
|
PlayerArrived, // When player arrives at interaction point
|
|
InteractingCharacterArrived, // When interacting character arrives
|
|
InteractionComplete, // When interaction is successfully completed
|
|
InteractionInterrupted // When interaction is interrupted
|
|
}
|
|
```
|
|
|
|
### CharacterToInteract
|
|
|
|
```csharp
|
|
public enum CharacterToInteract
|
|
{
|
|
None, // No character interactions
|
|
Trafalgar, // Player character only
|
|
Pulver, // Follower character only
|
|
Both // Both characters
|
|
}
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
- **Characters not moving to targets**: Ensure targets have the correct CharacterToInteract type set
|
|
- **Timeline not playing**: Check that the PlayableDirector has a reference to the timeline asset
|
|
- **Characters not appearing in timeline**: Verify the track names match the binding configuration
|
|
- **Interaction getting stuck**: Make sure timelines have a reasonable timeout value set
|
|
- **Multiple timelines playing simultaneously**: Check that the event mappings are correctly configured
|
|
|
|
|
|
## Setup Example
|
|
|
|
Here's how a typical interaction setup might look in the Inspector:
|
|
|
|
1. Interactable component with appropriate settings
|
|
2. Character move targets positioned in the scene
|
|
3. InteractionTimelineAction component configured with timeline mappings
|
|
4. PlayableDirector component referencing timeline assets
|
|
|
|
## Advanced Topics
|
|
|
|
### Timeline Integration with Dialogue
|
|
|
|
Timeline actions can be synchronized with dialogue using:
|
|
- Animation tracks to trigger dialogue displays
|
|
- Signal tracks to advance dialogue
|
|
- Custom markers to synchronize dialogue with character animations
|
|
|
|
### Interaction Sequences
|
|
|
|
Complex interaction sequences can be created by:
|
|
- Using multiple interactables in sequence
|
|
- Enabling/disabling interactables based on game state
|
|
- Using timelines to guide the player through sequential interactions
|