Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ConnectedControlPointsSelector Problems
#1
Based on the train example, I was trying to use the ConnectedControlPointsSelector to build out a more robust track switching system. However, I have run into a number of problems and I am not sure if I'm approaching this the right way or not.

Since the tracks will be in a big interconnected network, the direction of splines has become an issue. In the example, the merge and split points of the junctions worked because (I think) they directions of the splines were set ahead of time. In my system, trains can move along splines in either direction, and sometimes different splines connect while pointing in opposite directions. I figured I had to create a custom selector.

This system is supposed to do a few things -
-determine if the tangents of connected splines are close enough that a train could switch on them
 - reject weird angles that dont make sense for train junctions
 - intelligently know if a junction is being approached from a merging or splitting angle and not 'double back' on merging junctions
 - handle if two splines are 'tip to tip' and continue along the new spline even if it is in the opposite direction
-create a list of the valid connected splines at each junction
-for now, go down valid connection 0 with more logic to be added in the future

This current script accomplishes a lot of this, but now I am running into the problem that the train trucks/bogeys when transitioning to a new spline going in the opposite direction just stop (they are set to clamped) because they are still moving "forward" on the new spline in the opposite direction.

I feel like I must be overcomplicating this somehow, so I would like suggestions for how to make the movement behavior consistent as it transitions to new splines, and how maybe I can use built in features to simplify what is becoming a pretty complex script. Any ideas?

Code:
using FluffyUnderware.Curvy;
using FluffyUnderware.Curvy.Controllers;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class SplineSelector : ConnectedControlPointsSelector
{
    public float AngleTolerance = 30f;  // Maximum allowed deviation from 0° or 180°

    public override CurvySplineSegment SelectConnectedControlPoint(
        SplineController caller, CurvyConnection connection, CurvySplineSegment currentControlPoint)
    {
        if (connection.ControlPointsList.Count <= 0)
        {
            Debug.LogError($"[SplineSelector] No connecting points! The train has crashed.");
            return null;
        }

        List<CurvySplineSegment> validSegments = EvaluateJunctions(caller, currentControlPoint, connection);

        if (validSegments.Count <= 0)
        {
            Debug.LogError($"[SplineSelector] No valid connections! The train has crashed.");
            return null;
        }

        return validSegments[0];  // Select the first valid connection (or apply more logic as needed)
    }

    private List<CurvySplineSegment> EvaluateJunctions(
        SplineController caller, CurvySplineSegment currentSegment, CurvyConnection connection)
    {
        List<CurvySplineSegment> validSegments = new List<CurvySplineSegment>();

        foreach (var cp in connection.ControlPointsList)
        {
            if (cp == currentSegment) continue;  // Skip the current segment

            Vector3 currentTangent = GetTangentAtConnection(currentSegment, caller);
            Vector3 targetTangent = GetTangentAtConnection(cp, null);

            float angle = Vector3.Angle(currentTangent, targetTangent);
            bool isValid = IsValidAngle(angle);

            if (isValid)
            {
                bool isEndOfTargetSpline = IsEndOfSpline(cp, currentTangent, targetTangent);
                string junctionType = isEndOfTargetSpline ? "End-to-End or Merging" : "Splitting";

                Debug.Log($"[SplineSelector] Segment: {cp.name}, Angle: {angle} degrees, Junction Type: {junctionType}");
                validSegments.Add(cp);
            }
        }

        return validSegments;
    }

    private Vector3 GetTangentAtConnection(CurvySplineSegment segment, SplineController caller)
    {
        float tf = caller != null ? caller.RelativePosition : segment.TF;
        tf = Mathf.Clamp(tf, 0f, 1f);  // Clamp TF to avoid out-of-bounds errors
        return segment.GetTangentFast(tf, Space.World);  // Get tangent in world space
    }

    private bool IsValidAngle(float angle)
    {
        bool withinZeroTolerance = angle >= 0f && angle <= AngleTolerance;
        bool within180Tolerance = angle >= (180f - AngleTolerance) && angle <= 180f;
        return withinZeroTolerance || within180Tolerance;
    }

    /// <summary>
    /// Determines if the connected segment is at the end of its spline.
    /// </summary>
    private bool IsEndOfSpline(CurvySplineSegment segment, Vector3 currentTangent, Vector3 targetTangent)
    {
        bool targetAtEnd = segment == segment.Spline.ControlPointsList.Last();
        bool targetAtStart = segment == segment.Spline.ControlPointsList.First();

        // Check if the direction of the tangents suggests an end-to-end connection
        bool alignedWithCurrent = Vector3.Dot(currentTangent, targetTangent) > 0;

        if (alignedWithCurrent)
        {
            // If aligned, we expect end-to-end or merging behavior
            return targetAtEnd;
        }
        else
        {
            // If not aligned, we expect splitting behavior
            return targetAtStart;
        }
    }

}
Reply
#2
Hi,

There are some options in the predefined selectors that handle some of your constraints , but they don't handle all of them. Coding your own selector seems necessary.

About the controller stopping, have you tried to update the controller's Direction property inside your selector?

Have a nice day
Please consider leaving a review for Curvy, this helps immensely. Thank you.
Available for freelance work—feel free to reach out.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Information Extending the ConnectedControlPointsSelector, based on Player provided input EverknightDev 1 15 04-03-2023, 10:44 PM
Last Post: _Aka_
  Problems compiling after pulling down project from source control obscurelyme 2 13 02-13-2022, 03:47 PM
Last Post: Marco Schultz
Question How to tell if a spline is straight? / Optimize problems with straight splines MarioBag 3 21 12-27-2021, 05:25 PM
Last Post: _Aka_
  Problems with spline prefab topquarkone 3 436 09-15-2021, 08:47 PM
Last Post: _Aka_

Forum Jump: