Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Is there a smarter way to do this?
#1
So I have this 'running' experience going, and I basically have path splits.  The runner can choose left/right, and then they'll jump to the appropriate spline.  I've managed to essentially reverse engineer the code from the train example, but I wonder if this is a bit ridiculous:

The previous node contains metadata that has the text of the new path, Right=Lost Lake, Left=Thick Forest, and also a direct game object reference the first control point of the said paths.

So put this meta data script on the node before the turn:
Code:
public class metaTurnInfo : CurvyMetadataBase, ICurvyMetadata
{

   public string leftDiscription;
   public CurvySplineSegment left;
   public string rightDiscription;
   public CurvySplineSegment right;

}

Then on Control Point End do this:

Code:
   double connectionDistance;
   public void OnCPEnd (CurvySplineMoveEventArgs e)
   {

       mData = e.ControlPoint.PreviousControlPoint.GetMetadata<metaTurnInfo>();

       //THIS IS JUST DEBUG STUFF, TELLS ME THE NAMES OF THE PATH CHOICES
       String s = ""; 
       if (mData)
       {
           for (int i = 0; i < e.ControlPoint.Connection.OtherControlPoints(e.ControlPoint).Count; i++)
           {
               if (e.ControlPoint.Connection.OtherControlPoints(e.ControlPoint)[i] == mData.left)
               { s = e.ControlPoint.Connection.OtherControlPoints(e.ControlPoint)[i].ToString() + " is LEFT"; }
               else
               { s = e.ControlPoint.Connection.OtherControlPoints(e.ControlPoint)[i].ToString(); }
               console(s);
           }
       } else
       {
           console("No mData");
           for (int i = 0; i < e.ControlPoint.Connection.OtherControlPoints(e.ControlPoint).Count; i++)
           {
               s = e.ControlPoint.Connection.OtherControlPoints(e.ControlPoint)[i].ToString();
               console(s);

           }
       }

       //THIS is part of the UI, but if the user fails to choose a direction when it comes time to change paths, it'll default to the direction the player is looking, 0=left, 1=right
       if (turnDirection == -1) turnDirection = lookDirection;
       int d = 0;
       //MDATA only will exist if there's a choice to make, if not it will just connect to the next path
       if (mData) 
       {
           console("mData");
           for (int i = 0; i < e.ControlPoint.Connection.OtherControlPoints(e.ControlPoint).Count; i++)
           {
               if (turnDirection == 0)
                   if (e.ControlPoint.Connection.OtherControlPoints(e.ControlPoint)[i] == mData.left) d = i;
               if (turnDirection == 1)
                   if (e.ControlPoint.Connection.OtherControlPoints(e.ControlPoint)[i] == mData.right) d = i;

               console(i + "   " + d);
           }
           
       } else
       {
           console("No mData");
           for (int i = 0; i < e.ControlPoint.Connection.OtherControlPoints(e.ControlPoint).Count; i++)
           {
               if (e.ControlPoint.Connection.OtherControlPoints(e.ControlPoint)[i].FollowUp == null) d = i;
           }
       }

       e.Follow(e.ControlPoint.Connection.OtherControlPoints(e.ControlPoint)[d]);
       SplineController controller = (SplineController)e.Sender;
       controller.Spline = e.Spline;
       controller.RelativePosition = e.TF;

       isTurning = false;
       turnDirection = -1;
       TurnHUD.SetActive(false);

   }

So, if you'll notice, my code is relying on matching what's in the metadata to what's in the connection point.  If you look at my screenshot, it's confusing to me to just say use connection 1 or connection 2, because that seems to randomly change depending on (I think) the order in which I've created my paths.  Purple is the path I'm on "Deep Canyon", and the Red is the paths I can choose.  

So this works, just fine.. but I feels like it should be easier.  Hopefully my code isn't too hard to read, I'm still getting better at C#


Attached Files Thumbnail(s)
   
Reply
#2
Hi,
You can do what you are looking for in a simpler way. I attached a zip with an example of the simpler way. Here are some explanations:
Instead of having a MetaData at the end of each path, referencing the following paths' first CP (Control Point), I prefer having a simpler MetaData at the beginning of each path.

Code:
public class BranchInfo : CurvyMetadataBase, ICurvyMetadata
{
    public string Description;
    public int Direction;
}

And here is the code doing the switch
Code:
    public void OnCPEnd(CurvySplineMoveEventArgs e)
    {
        // we need a SplineController as well as a connection to work with
        if (e.Sender is SplineController && e.ControlPoint.Connection)
        {
            CurvySplineSegment controlPointToFollow = null;
            foreach (CurvySplineSegment controlPoint in e.ControlPoint.Connection.ControlPoints)
            {
                BranchInfo branchInfo = controlPoint.GetMetadata<BranchInfo>();
                if (branchInfo && branchInfo.Direction == direction)
                {
                    controlPointToFollow = controlPoint;
                    break;
                }
            }

            e.Follow(controlPointToFollow); // Follow the new spline
            // Set the controller to use the new spline
            SplineController controller = (SplineController)e.Sender;
            controller.Spline = e.Spline;
            controller.RelativePosition = e.TF;
        }
    }

I see the following advantages in this way of doing:
  * Faster to edit and modify the levels: with this way, you skip the need to reference the first CPof each path in metaTurnInfo. This makes it faster to add paths, or to change the order of existing paths.
  * Can handle more than two directions: without changing the path switching code, you can handle multiple paths just by modifying the code that defines the value of the direction. For example you can add a 3rd path with a value of 2  for the case where the player doesn't choose left or right.
  * More efficient code: calling the OtherControlPoints function creates a new list each time, which will make the garbage collector run more often, which is bad for frame rate.

I hope that you will find your work simpler with these changes.
If my suggestion doesn't tackle some of the complexity you found, please let me know.


Attached Files
.zip   Paths.zip (Size: 6.48 KB / Downloads: 0)
Please consider leaving a review for Curvy. This will help a lot keeping Curvy relevant in the eyes of the Asset Store algorithm.
Reply
#3
Wow. I can't believe you wrote this all out for me! You're awesome! Haven't had a chance to jump onto my machine yet but reading the code it makes sense so far.

I feel like so much of curvys potential is hidden in the api. I'm weird but sometimes I love to just spend an afternoon reading what each method is supposed to do. Curvy actually has a pretty good document on this although it could certainly improve with a few simple examples here and there.

I'll let you know how it goes implementing this!
Reply
#4
Thanks a lot Smile

Yes, the API is what unleashes the power of Curvy. Make sure to work on the latest Curvy version (your other thread had a screenshot that seemed to me to be taken from an old version), because the last and future releases will improve the API.
Please consider leaving a review for Curvy. This will help a lot keeping Curvy relevant in the eyes of the Asset Store algorithm.
Reply


Forum Jump: