PS_AI_Behavior: make spline StopFollowing a firm, BT-respected stop
StopFollowing() now sets a bManuallyStopped flag (cleared only by an explicit StartFollowing/StartFollowingAtDistance). The FindAndFollowSpline and FollowSpline BT tasks bail while it is set, so the BT no longer auto-resumes a manual stop on the next tick. ResumeFollowing() also respects the flag. PauseFollowing() is unchanged (BT may resume). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,14 @@ EBTNodeResult::Type UPS_AI_Behavior_BTTask_FindAndFollowSpline::ExecuteTask(
|
|||||||
return EBTNodeResult::Failed;
|
return EBTNodeResult::Failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Respect a manual StopFollowing(): do not search for or resume a spline until
|
||||||
|
// the caller explicitly StartFollowing() again. Without this, the task would
|
||||||
|
// resume any CurrentSpline and override the stop on the very next tick.
|
||||||
|
if (Follower->bManuallyStopped)
|
||||||
|
{
|
||||||
|
return EBTNodeResult::Failed;
|
||||||
|
}
|
||||||
|
|
||||||
// Debug: log state on entry
|
// Debug: log state on entry
|
||||||
if (UPS_AI_Behavior_Statics::IsDebugEnabled(AIC->GetPawn()))
|
if (UPS_AI_Behavior_Statics::IsDebugEnabled(AIC->GetPawn()))
|
||||||
{
|
{
|
||||||
@@ -268,6 +276,18 @@ void UPS_AI_Behavior_BTTask_FindAndFollowSpline::TickTask(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Manual StopFollowing() requested mid-approach: cancel the move-to-spline and bail.
|
||||||
|
if (UPS_AI_Behavior_SplineFollowerComponent* StopCheck =
|
||||||
|
AIC->GetPawn()->FindComponentByClass<UPS_AI_Behavior_SplineFollowerComponent>())
|
||||||
|
{
|
||||||
|
if (StopCheck->bManuallyStopped)
|
||||||
|
{
|
||||||
|
AIC->StopMovement();
|
||||||
|
FinishLatentTask(OwnerComp, EBTNodeResult::Failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if we've reached the spline
|
// Check if we've reached the spline
|
||||||
if (AIC->GetMoveStatus() == EPathFollowingStatus::Idle)
|
if (AIC->GetMoveStatus() == EPathFollowingStatus::Idle)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ EBTNodeResult::Type UPS_AI_Behavior_BTTask_FollowSpline::ExecuteTask(
|
|||||||
AIC->GetPawn()->FindComponentByClass<UPS_AI_Behavior_SplineFollowerComponent>();
|
AIC->GetPawn()->FindComponentByClass<UPS_AI_Behavior_SplineFollowerComponent>();
|
||||||
if (!Follower) return EBTNodeResult::Failed;
|
if (!Follower) return EBTNodeResult::Failed;
|
||||||
|
|
||||||
|
// Respect a manual StopFollowing(): refuse to resume until an explicit restart.
|
||||||
|
if (Follower->bManuallyStopped)
|
||||||
|
{
|
||||||
|
return EBTNodeResult::Failed;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Follower->CurrentSpline)
|
if (!Follower->CurrentSpline)
|
||||||
{
|
{
|
||||||
UE_LOG(LogPS_AI_Behavior, Warning, TEXT("[%s] FollowSpline: no current spline set."),
|
UE_LOG(LogPS_AI_Behavior, Warning, TEXT("[%s] FollowSpline: no current spline set."),
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ bool UPS_AI_Behavior_SplineFollowerComponent::StartFollowingAtDistance(
|
|||||||
CurrentDistance = FMath::Clamp(StartDistance, 0.0f, Spline->GetSplineLength());
|
CurrentDistance = FMath::Clamp(StartDistance, 0.0f, Spline->GetSplineLength());
|
||||||
bMovingForward = bForward;
|
bMovingForward = bForward;
|
||||||
bIsFollowing = true;
|
bIsFollowing = true;
|
||||||
|
bManuallyStopped = false; // an explicit Start lifts any previous manual stop
|
||||||
LastHandledJunctionIndex = -1;
|
LastHandledJunctionIndex = -1;
|
||||||
|
|
||||||
UE_LOG(LogPS_AI_Behavior, Warning,
|
UE_LOG(LogPS_AI_Behavior, Warning,
|
||||||
@@ -82,18 +83,23 @@ bool UPS_AI_Behavior_SplineFollowerComponent::StartFollowingAtDistance(
|
|||||||
void UPS_AI_Behavior_SplineFollowerComponent::StopFollowing()
|
void UPS_AI_Behavior_SplineFollowerComponent::StopFollowing()
|
||||||
{
|
{
|
||||||
bIsFollowing = false;
|
bIsFollowing = false;
|
||||||
UE_LOG(LogPS_AI_Behavior, Verbose, TEXT("[%s] Stopped following spline."),
|
// Firm, manual stop: the Behavior Tree spline tasks will refuse to re-start
|
||||||
|
// following until StartFollowing()/StartFollowingAtDistance() is called again.
|
||||||
|
bManuallyStopped = true;
|
||||||
|
UE_LOG(LogPS_AI_Behavior, Log, TEXT("[%s] StopFollowing: manual stop (BT will not auto-resume)."),
|
||||||
GetOwner() ? *GetOwner()->GetName() : TEXT("?"));
|
GetOwner() ? *GetOwner()->GetName() : TEXT("?"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UPS_AI_Behavior_SplineFollowerComponent::PauseFollowing()
|
void UPS_AI_Behavior_SplineFollowerComponent::PauseFollowing()
|
||||||
{
|
{
|
||||||
|
// Pause is NOT a manual stop — the BT is allowed to resume it.
|
||||||
bIsFollowing = false;
|
bIsFollowing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UPS_AI_Behavior_SplineFollowerComponent::ResumeFollowing()
|
void UPS_AI_Behavior_SplineFollowerComponent::ResumeFollowing()
|
||||||
{
|
{
|
||||||
if (CurrentSpline)
|
// Do not resume over a manual stop — only an explicit Start lifts that.
|
||||||
|
if (CurrentSpline && !bManuallyStopped)
|
||||||
{
|
{
|
||||||
bIsFollowing = true;
|
bIsFollowing = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,6 +106,13 @@ public:
|
|||||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated, Category = "Spline Follower|Runtime")
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated, Category = "Spline Follower|Runtime")
|
||||||
bool bIsFollowing = false;
|
bool bIsFollowing = false;
|
||||||
|
|
||||||
|
/** Set by StopFollowing(): a firm, manual stop. While true, the Behavior Tree
|
||||||
|
* spline tasks refuse to (re)start following — only an explicit StartFollowing()
|
||||||
|
* / StartFollowingAtDistance() clears it. This is what distinguishes a deliberate
|
||||||
|
* stop from PauseFollowing() (which the BT is allowed to auto-resume). */
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Spline Follower|Runtime")
|
||||||
|
bool bManuallyStopped = false;
|
||||||
|
|
||||||
// ─── Delegates ──────────────────────────────────────────────────────
|
// ─── Delegates ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
/** Fired when approaching a junction. Use to make custom spline selection. */
|
/** Fired when approaching a junction. Use to make custom spline selection. */
|
||||||
|
|||||||
Reference in New Issue
Block a user