Easy Chapter Generator
EnglishEspañol

Connect movement without a package dependency

Core defines IPathMovementAdapter and INpcRouteAdapter so an ObjectTransportAction can request movement without referencing a specific path, tween, AI, or waypoint product. The project integration assembly owns the vendor API and can be compiled only when that dependency is present.

This boundary keeps the distributable package global: absence of an optional asset does not remove transport modes or break Core compilation.

Vendor boundary

There is no built-in SWS integration. Connect SWS, another waypoint package, AutoHand, Meta XR, or another VR framework in project-owned adapter or callback code; none of those products is required or redistributed.

Interface responsibilities

InterfaceMethodContext received
IPathMovementAdapterStartMovement(Transform subject, MonoBehaviour pathSource)Subject and project-specific path component
INpcRouteAdapterStartRoute(MonoBehaviour pathSource, bool requireNearbyPlayer, string objectiveId, float speed)Route source, proximity option, optional Objective ID, clamped requested speed

PathMovement discovers the adapter among MonoBehaviours attached to the Subject. NpcRoute uses the explicitly assigned MonoBehaviour and requires it to implement the interface.

Adapter implementation rules

  • Validate subject and path source before calling a vendor API.
  • Define what happens when movement is requested twice: replace, queue, or reject.
  • Keep cancellation and object-disable cleanup in the adapter.
  • Complete an Objective only after the movement system confirms arrival, never merely because routing started.
  • Use the supplied Objective ID only when Complete Current Objective is enabled and the adapter owns that policy.
  • Guard optional vendor types with a separate assembly definition or scripting define.

Integration acceptance matrix

CaseExpected result
Missing path sourceCore warns; adapter is not called
No path adapter on SubjectCore warns with Subject context
NpcAdapter does not implement interfaceCore warns; no route begins
Valid requestExactly one adapter call with assigned references and options
Route interruptedProject adapter applies its documented cancellation policy; no false completion
ArrivalAdapter optionally completes the exact supplied active Objective and checks acceptance

The included compiled example deliberately moves toward pathSource.transform.position; it demonstrates the interface, not pathfinding. Replace its coroutine with project or vendor behavior.

Implement a movement adapter

Where to place it
Attach the adapter to the same movement subject assigned in ObjectTransportAction.
When to call it
PathMovement calls StartMovement with the subject and the configured MonoBehaviour path source.
Behavior
This minimal adapter moves to pathSource.transform and is not a pathfinding solution. Replace its coroutine with the vendor or project movement API.
using System;
using System.Collections;
using System.Collections.Generic;
using OverFuture.ChapterObjectiveSystem.Chapters;
using OverFuture.ChapterObjectiveSystem.Events;
using OverFuture.ChapterObjectiveSystem.Objectives;
using OverFuture.ChapterObjectiveSystem.Persistence;
using OverFuture.ChapterObjectiveSystem.Progression;
using UnityEngine;

public sealed class SimplePathMovementAdapter : MonoBehaviour, IPathMovementAdapter
{
    [SerializeField, Min(0.01f)]
    private float speed = 2f;

    private Coroutine movementRoutine;

    public void StartMovement(Transform subject, MonoBehaviour pathSource)
    {
        if (subject == null || pathSource == null)
        {
            return;
        }

        if (movementRoutine != null)
        {
            StopCoroutine(movementRoutine);
        }

        movementRoutine = StartCoroutine(
            MoveTo(subject, pathSource.transform.position));
    }

    private IEnumerator MoveTo(Transform subject, Vector3 destination)
    {
        while (subject != null &&
               (subject.position - destination).sqrMagnitude > 0.0001f)
        {
            subject.position = Vector3.MoveTowards(
                subject.position,
                destination,
                Mathf.Max(0.01f, speed) * Time.deltaTime);
            yield return null;
        }

        movementRoutine = null;
    }
}