> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kinemation.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Warp Providers: Supply Target Points to Motion Warping

> Implement IWarpPointProvider to supply warp target points — WarpInteractionResult API, static and moving obstacle patterns, and custom provider examples.

A **Warp Provider** is a component that knows about a specific interaction in your game — where the target points are, which Motion Warping Asset to use, and whether the interaction is currently valid. When your controller calls `_warpingComponent.Interact(provider)`, the provider runs its detection logic and returns all the data the system needs to begin warping.

## The IWarpPointProvider Interface

All Warp Providers implement the `IWarpPointProvider` interface, which declares a single method — `Interact`. You can implement this interface on any `MonoBehaviour` to create a fully custom provider.

The system also uses a `WarpInteractionResult` struct to package the provider's output:

```csharp theme={null}
public struct WarpInteractionResult
{
    public WarpPoint[] points;            // Target points for each warp phase.
    public MotionWarpingAsset asset;      // Warping asset with phase configuration.
    public bool success;                  // Whether the interaction can be started.

    public bool IsValid()
    {
        return success && points != null && asset != null;
    }
}

public interface IWarpPointProvider
{
    public WarpInteractionResult Interact(GameObject instigator);
}
```

The `IsValid()` helper checks all three conditions: the interaction was found, at least one target point exists, and a warping asset is assigned. The **MotionWarping** component calls `IsValid()` on the result before starting any warping — if it returns `false`, the interaction is silently skipped.

## Supplying Target Points

The way you populate `result.points` depends on whether the obstacle is **moving** or **static**.

### Static obstacles

For obstacles that do not move (walls, fixed ledges, parked vehicles), pass world-space coordinates directly:

```csharp theme={null}
result.points = new[]
{
    new WarpPoint()
    {
        position = _targetPosition,
        rotation = _targetRotation
    }
};
```

### Moving obstacles

For obstacles that move at runtime (moving platforms, vehicles in transit, enemies), you must attach the warp point to the obstacle's transform. Convert the world-space target position into the obstacle's **local space** using `InverseTransformPoint`, and convert the rotation into the obstacle's local space using `Quaternion.Inverse`:

```csharp theme={null}
result.points = new[]
{
    new WarpPoint()
    {
        transform = hit.transform,
        position = hit.transform.InverseTransformPoint(_targetPosition),
        rotation = Quaternion.Inverse(hit.transform.rotation) * _targetRotation
    }
};
```

The Motion Warping system will then track the obstacle's transform at runtime and keep the target point correctly positioned as the obstacle moves.

<Note>
  Always use the local-space conversion when the obstacle can move between the time the interaction starts and the time it ends. Using raw world coordinates on a moving obstacle causes the character to drift away from the target mid-warp.
</Note>

## Using a Warp Provider in Code

The example below shows how to trigger a vault interaction using the built-in `VaultComponent` as the provider. Call `_warpingComponent.Interact(provider)` in response to player input:

```csharp theme={null}
public class YourController : MonoBehaviour
{
    // ...
    private MotionWarping _warpingComponent;
    // ...

    private VaultComponent _vaultComponent;
    // ...

    private void Start()
    {
        // ...
        _warpingComponent = GetComponent<MotionWarping>();
        // ...
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.F))
        {
            _warpingComponent.Interact(_vaultComponent);
        }
    }

    // ...
}
```

### Passing a GameObject instead of a component reference

If you do not have a direct reference to the provider component, you can pass the obstacle's `GameObject` to `Interact`. The system will search for the first component on that object implementing `IWarpPointProvider` and call it automatically:

```csharp theme={null}
_warpingComponent.Interact(gameObject);
```

This is useful for interaction systems that work with generic `GameObject` references (for example, from raycasts or trigger zones) without needing to know the specific provider type.

## Implementing a Custom Warp Provider

To create your own provider, implement `IWarpPointProvider` on a `MonoBehaviour` attached to the obstacle or the character:

```csharp theme={null}
using UnityEngine;

public class ClimbComponent : MonoBehaviour, IWarpPointProvider
{
    [SerializeField] private MotionWarpingAsset _climbAsset;

    private Vector3 _ledgePosition;
    private Quaternion _ledgeRotation;

    public WarpInteractionResult Interact(GameObject instigator)
    {
        WarpInteractionResult result = new WarpInteractionResult();

        // Detect whether there is a climbable ledge in front of the character.
        bool ledgeFound = TryFindLedge(instigator, out _ledgePosition, out _ledgeRotation);

        result.success = ledgeFound;
        result.asset = _climbAsset;

        if (ledgeFound)
        {
            result.points = new[]
            {
                new WarpPoint()
                {
                    position = _ledgePosition,
                    rotation = _ledgeRotation
                }
            };
        }

        return result;
    }

    private bool TryFindLedge(GameObject instigator, out Vector3 pos, out Quaternion rot)
    {
        // Your ledge detection logic here (raycasts, overlap checks, etc.)
        pos = Vector3.zero;
        rot = Quaternion.identity;
        return false;
    }
}
```

<Tip>
  Keep detection logic inside the provider component rather than in the controller. This makes each interaction self-contained and easy to test independently.
</Tip>
