Scripting
Movement and Route Adapters
Connect project-owned movement packages through IPathMovementAdapter or INpcRouteAdapter without a direct product dependency.
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.
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
| Interface | Method | Context received |
|---|---|---|
| IPathMovementAdapter | StartMovement(Transform subject, MonoBehaviour pathSource) | Subject and project-specific path component |
| INpcRouteAdapter | StartRoute(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
| Case | Expected result |
|---|---|
| Missing path source | Core warns; adapter is not called |
| No path adapter on Subject | Core warns with Subject context |
| NpcAdapter does not implement interface | Core warns; no route begins |
| Valid request | Exactly one adapter call with assigned references and options |
| Route interrupted | Project adapter applies its documented cancellation policy; no false completion |
| Arrival | Adapter 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;
}
}