Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Official Unity Splines

Discussion in 'World Building' started by gabrielw_unity, Oct 5, 2022.

  1. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    @Aka_ToolBuddy,

    Thanks for logging that in our bugs! That's gonna be easier to foolow :)
    And yes indeed, if the spline is modified when a knot is linked (if a knot moves for instance due to that new link), we should send an event like
    spline.Changed
    and that's a bug if we don't :)

    Yes indeed! 100% agree with you on that too!
     
  2. freyzorr

    freyzorr

    Joined:
    Jul 26, 2015
    Posts:
    29
    I would love to see and example implementation of this. Is this something you would be willing to share?

    I did some try to use the curvature API to figure out the turning radius at t but didn't get it to work properly.
     
  3. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Oh boy, that was a while ago :eek:
    Not certain I still have this code, but I'll let you know if I do!

     
    freyzorr likes this.
  4. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hey @hafu985!
    Sorry for the long delay since your post.
    Can you give me a little more context when you say "SplineAnimation not ready for use on start. I want to make some configs on start and then invoke Play, but it not working." Do you have an exception?
    Do you have a specific reason to use a
    private IEnumerator Start()
    rather than
    private void Start()
    , because the
    yield return null;
    intruction is delaying the call to
    Activate()
    by a frame here if I'm not mistaken.

    Let me know :)

     
  5. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Thanks again @MirzaBeig for this feedback!
    This is interesting that unsing the animator or animation clip does not work properly, I don't think we tried this, that might be on due to the way animation updates the variables maybe.
    I'll check that out and log that bug!

     
  6. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hi @olivecrow,

    Thanks for the feedbacks and suggestions, really appreciated!

    1. Actually in the last versions of the package we are heading towards this: The <SplineInstantiate> component now have a Bake button to build the instances in the scene and remove the component. For the <SplineExtrude> one, the meshes are already created as assets and are not stored in the scene when using the component in editor. These mesh assets are created in a folder next to the scene, or directly in the Assets folder if the scene has not been saved.
    But indeed that would make sense to have something more homogeneous between our components from an API point of view.

    2. This case seems to be really specific to this usecase and what if you would what to have these instances spawning only on 3 of the 4 faces of your rect column but not on the 4 of them? Although I see a point of using a randomized but fixed offset when generating the instances (for instance generate a tree and randomize the rotation with a multiple of 30). Would that make sense to add a new type after "Exact" and "Random" for "Fixed offset" in that case?
    upload_2023-8-22_14-56-32.png

    3. This is something we actually considered and finally decided we don't want to do. This component is indeed to be simple and don't support all of the usecases. Mainly because there is too many cases and shapes to cover and that this is not the purpose of this API here so we prefer leaving that to the user depending their needs. The code here is provided as an example and can easily be adapted to other shapes :)

    4. Same here than for 3. really good feedback and we already discussed about that, but this is a specific usecase we will not cover in the package but will let users implement as rendering decals is not the purpose of the package here. But all the tools to do that are provided to make this tool as you want it to work! :)

    5. On normals, it would be possible to show them but not to manipulate them. The normal here is always a unit vector which amplitude does not change, and its direction is based on the knot rotation. Regarding the way we are building splines, the tangent is the best way to manipulate the knots, manipulating the normals would not effect the spline. On top of that, the normal vector is 'exposed' to the users on the knots gizmos by showing the line representing the up direction on top of the knot. But it's not possible to manipulate it.

    Hope this helps :D


     
    Last edited: Aug 22, 2023
  7. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hi @batteryyrettab,

    Thanks for the feedbacks! Sorry it took a while to answer, your post is clear but there is a lot in there and trying to see how to answer that the best I can.
    So if I can rephrase your need, you would like to have this usecase :
    - A GameObject is navigating on a spline at a position T (let's say T is between 0 and 1, 0 being at the start of the spline and 1 at the end)
    - If that position T is getting closer to a knot you would like to know if multiple path options are available at that knot (multiple branches).
    - For that ant also to expose the different transition points to the users you would need to easily access the different LinkedKnots if they exist.
    Am I correct until now?

    So first, to be able to link your knots together, you'll have to put the splines in the same SplineContainer. And yes, tools are mostly designed to handle one SplineContainer per GameObject as each container can have a different transform and this also helps for a simpler visualization in the scene.

    Once your knots are linked, and from your position T, you need to determine which knot is the following one first, you can do that in different ways:
    - Convert T between the different Index unit (using SplineUtility.ConvertIndexUnit) to make it as a Knot index (PathIndexUnit.Knot) and then add 1 to it to get the next knot index.
    - Using SplineUtility.Next(spline, currentKnotIndex) that will return the next knot index.

    Once you have the next index, you can check if that knot has LinkedKnots using : container.KnotLinkCollection.GetKnotLinks(knot). This will return to you a list of of all the LinkedKnots associated to that one (that one being included in that list). From there you'll have access to the connected splines and knots as you want.

    This will allow you to dynamically detect the next knot and if there is a connection on that point.

    Regarding you usecase to only retrieve all the linkKnots in a SplineContainer to display that to your user. The loop you coded is correct and is currently the best way currently to have access to these links. The reason this part of the API is private and internal is that this data is easy to break when exposed and we don't want that. However, your usecase is legit and I'll post a report on that so that we can expose an easier way to see this data with read-only access because this is indeed missing here! Thanks for pointing this out.

    Sorry this post is going in different directions, but I wanted to give multiple ways to explore even though you probably already know them and you seem to already explore these.

     
  8. sand_lantern

    sand_lantern

    Joined:
    Sep 15, 2017
    Posts:
    210
    @ThomasLopez I appreciate you getting back to this!
    Thanks for checking up, I'm using LTS so it looks like 2.4.0 hasn't made it to my project yet. I do see in the changelog that that it fixed some upvector math so that may be a fix... Will this be making it's way back in time to those of us who need project stability?

    Sure. I recreated this both Via code (What my script was doing) and in a little test case using the GUI tools. I noticed my generated meshes that relied on the tangent vector would sometimes be nonexistant for sections, and that is what lead my onto this behaviour, specifically if something was dangling straight down.

    This is my specific code that updates a spline from a set of bone configuration objects that move around:

    Code (CSharp):
    1. public static void UpdateLinePath (in int lineSegments, in int subdivisions, Spline spline, IMeshBone[] bones)
    2. {
    3.     float scale = .5f;
    4.     for (int iB = 0; iB < bones.Length; iB++)
    5.     {
    6.         BezierKnot curveKnot;
    7.         float3 dir1, dir2;
    8.         if (iB == 0)
    9.         {
    10.             //First Bone has special logic to avoid index oob
    11.             dir1 = -math.length (bones[iB].Position - bones[iB + 1].Position) * bones[iB].Forward;
    12.             dir2 = bones[iB].Forward;
    13.         } else
    14.         {
    15.             dir1 = normalize (bones[iB - 1].Position - bones[iB].Position);
    16.             dir2 = -dir1;
    17.         }
    18.  
    19.         curveKnot = new BezierKnot (bones[iB].Position, dir1 * scale, dir2 * scale);
    20.  
    21.         spline[iB] = curveKnot;
    22.     }
    23. }
    I'm not exactly sure what my knots tangent mode is in this case, I think it's Bezier, but I could be wrong.

    My original post contains a test script that you should be able to attach to a game object in a fresh project (with the splines package) to see it recreated. Where the lines are red are segments where the upvector is null. If no red lines show up then the bug is fixed.
     
    Last edited: Aug 23, 2023
    ThomasLopez likes this.
  9. MirzaBeig

    MirzaBeig

    Joined:
    Dec 27, 2014
    Posts:
    602
    @ThomasLopez Just saw these, thanks for looking into it!

    While I know I could pass this data myself, I was enjoying the "it's already there" features from Splines and wanted to avoid any additional work if possible. :)

    I can't say without more real use-cases, but it's possible having both normalized and distance UVs is better than a toggle. Other than that, it would be a great feature to have. I also completely understand it can be difficult to foresee what's really a critical feature and something that's maybe better left to the user to implement.

    My reasoning here was that, if there is a built-in extrude feature, it may as well be versatile, and normalized UVs was something I had come to intuitively expect, so IIRC (it's been a couple months) it caught me off guard. :D
     
    ThomasLopez likes this.
  10. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Thanks,
    I think I missed the file in you original thread, sorry for that!
    Splines 2.4.0 should be available in the latest LTS after Unity 2022.3.8f1. If you don't see it, you can add the package by name and specify the 2.4.0 version, that should update it for you!

    I'll have a look at your script and come back to you :D
    Have a good one

     
  11. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    @sand_lantern : I didn't see the script originally because of the sploier alert in your post XD I didn't want to get spoled I guess!

     
  12. RaveOnTheGrave

    RaveOnTheGrave

    Joined:
    Oct 28, 2022
    Posts:
    27
    Does Unity Splines support ECS from DOTS? And if not, is an addition planned, what options do we have at the moment?
     
    ThomasLopez likes this.
  13. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    @RaveOnTheGrave,
    They should support that yes.
    There is a structure in the package, called NativeSpline, that is job-friendly and allows to build all the data needed for evaluating splines in jobs and for ECS/DOTS.

    However, there might be some limitation for some components (instantiate, animate), we didn't test that intensively on that aspect.

     
    RaveOnTheGrave likes this.
  14. RaveOnTheGrave

    RaveOnTheGrave

    Joined:
    Oct 28, 2022
    Posts:
    27
    Is there anywhere an example of using Unity Splines in DOTS?
     
  15. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Ok so @sand_lantern,

    I looked at your code and yes there is a bug as you shouldn't have NaN values here. So I'll fixed that.

    However, in your code you are creating a spline from code but you are not providing any tangents nor rotations to this knots. As you don't have tangents, these knots cannot realistically have an upVector. However, under the hood, we are computing the upVector based on the knot rotation.
    However, another problem comes up here, your knots are on top of each other, meaning that the knot up vector (0,1,0) and the direction of the spline at that location (0,-1,0) are aligned and this is what creates the problem. Just moving one of the knots solves this NaN problem. Have a look at my gif to see how your knots are oriented.

    A better practice would be to align the knot rotation to point to the next knot. For instance, your first 4 knots should rather be:
    Code (CSharp):
    1.             container.Spline.Add (new BezierKnot (new float3 (1f, 0f, 0f), new float3 (0f, 0f, -1f), new float3 (0f, 0f, 1f), Quaternion.LookRotation(new Vector3(0,-10,0))));
    2.             container.Spline.Add (new BezierKnot (new float3 (0f, -10f, 0f), new float3 (0f, 0f, -1f), new float3 (0f, 0f, 1f), Quaternion.LookRotation(new Vector3(0,-25,0))));
    3.             container.Spline.Add (new BezierKnot (new float3 (0f, -25f, 0f), new float3 (0f, 0f, -1f), new float3 (0f, 0f, 1f), Quaternion.LookRotation(new Vector3(-1,-47,0))));
    4.             container.Spline.Add (new BezierKnot (new float3 (-1f, -47f, 0f),new float3 (0f, 0f, -1f), new float3 (0f, 0f, 1f), Quaternion.LookRotation(new Vector3(0,-100,0))));

    We will fix that NaN values problem, but the fix will certainly be to return zero vectors when used like this as 1/ tangents of value zero should not return an up vector value and 2/ aligning a knot up vector and a spline might not be a good practice ;)

    Hope these explanations help!


     

    Attached Files:

    sand_lantern likes this.
  16. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    No sorry, that we haven't done!
     
  17. sand_lantern

    sand_lantern

    Joined:
    Sep 15, 2017
    Posts:
    210
    Thanks for the explanation. I tried something like that at some point, but couldn't figure out what values I was supposed to be feeding in and eventually gave up on it as I had something that works. I will take a look at my code and see if I can do it with better practices per your suggestion.

    I really appreciate you taking the time to answer our questions here.
     
    ThomasLopez likes this.
  18. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Let me know how that goes :)

    Building your splies and knots by code, I would tends to say this:
    - Do not use 0-length tangents
    - Orient (rotate) the knot to point in the direction of the next knot, or on the direction desired for your curve, this rotation should be pointing towards your tangent out
    - If the knot is correctly rotated, the tangent out should be something like (0,0,X), X will define how strong the tangent influences the shape of the curve.
    - If you want to have a continuous spline, the tangent in should be aligned (even mirrored) on the tangent out: (0,0,-X)

    If you try to use the Splines tools in the scene view directly (not by creating splines by code), that might help you to better understand the influence of the knot rotation and the different tangent modes (mirrored, continuous, broken, linear).

    Hope this help :D

     
    sand_lantern likes this.
  19. sand_lantern

    sand_lantern

    Joined:
    Sep 15, 2017
    Posts:
    210
    So, using the rotation input seems to give me something unexpected.
    I get what I'm looking for when setting the knot without a rotation provided like this:
    curveKnot = new BezierKnot (current, inDir, outDir);

    The red is
    outDir
    (calculated by getting the vector from current to next node),
    yellow is
    inDir
    (reflection of outDir with a different magnitude),
    the green line represents the spline evaluated tangent,
    the white is my up vector.

    This is what I'm looking for. upload_2023-8-29_13-45-43.png
    However, when I supply a rotation like this:
    rot = Quaternion.LookRotation (outDir);

    curveKnot = new BezierKnot (current, inDir, outDir, rot);

    What I end up with instead is this
    upload_2023-8-29_13-48-53.png
    Notice specifically that the green tangent vectors are perpendicular to my red/yellow vectors.

    This may be a better general question for the forums, because I suspect what that means is that I'm doing something wrong with my Quaternion.LookRotation(outDir), but it seems like I'm doing the right thing there.

    Converting my code generated spline to a game object with a splinecontainer yields this.
    Notice specifically that the rotation of Knot [0] is (0, 180, 0). However when I print out the rotation value that I'm passing in, it says its (0, 270, 0)
    upload_2023-8-29_13-51-10.png

    I'm pretty happy with the results when not providing a rotation vector, but your suggestion is that it's better if I do that. I am not sure what I could be doing wrong however.

    If you want to see my whole function that generates the spline it's here, though I hopefully explained well enough that you don't need to dig through my mess.
    Code (CSharp):
    1.  
    2.         public static void UpdateLinePath (in int lineSegments, in int subdivisions, in float smoothFactor, Transform transform, Spline spline, ITentailMeshBone[] bones)
    3.         {
    4.             bool init = false;
    5.             if (spline.Count != bones.Length)
    6.             {
    7.                 spline.Clear ();
    8.                 init = true;
    9.             }
    10.             float scale = smoothFactor, prevMag = 0f, nextMag;
    11.             float3 center = transform.position, inDir, outDir, current, next;
    12.             Quaternion rot;
    13.             for (int iB = 0; iB < bones.Length; iB++)
    14.             {
    15.                 BezierKnot curveKnot;
    16.                 current = bonePosition (bones[iB], center);
    17.  
    18.                 if (iB < bones.Length - 1f)
    19.                 {//Other points
    20.                     next = bonePosition (bones[iB + 1], center);
    21.                     nextMag = length (current - next);
    22.                 } else
    23.                 {//Last point
    24.                     next = bonePosition (bones[^1], center);
    25.                     nextMag = prevMag;
    26.                 }
    27.  
    28.                 if (iB == 0)
    29.                 {//First point
    30.                     prevMag = nextMag;
    31.                     //outDir = normalize (next - current);
    32.                     outDir = normalize (bones[iB].Forward);
    33.                     inDir = -outDir;
    34.                 } else if (iB < bones.Length - 1f)
    35.                 {//Other points
    36.                     outDir = normalize (next - current);
    37.                     inDir = -outDir;
    38.                 } else
    39.                 {//Last point
    40.                     outDir = normalize (current - bonePosition (bones[^2], center));
    41.                     inDir = -outDir;
    42.                 }
    43.  
    44.                 rot = Quaternion.LookRotation (outDir);
    45.                 curveKnot = new BezierKnot (current, inDir * scale * prevMag, outDir * scale * nextMag);
    46.  
    47.                 //Debug.DrawRay (curveKnot.Position, curveKnot.TangentIn, Color.yellow, 0f, false);
    48.                 //Debug.DrawRay (curveKnot.Position, curveKnot.TangentOut, Color.red, 0f, false);
    49.  
    50.                 if (init)
    51.                 {
    52.                     //Debug.Log ($"(dir:{outDir:F2}\nr:{rot.eulerAngles:F2}");
    53.                     spline.Add (curveKnot, TangentMode.Continuous);
    54.                     //Debug.Log ($"(p:{curveKnot.Position:F2}, i:{curveKnot.TangentIn:F2}, o:{curveKnot.TangentOut:F2})\nr:{((Quaternion) curveKnot.Rotation).eulerAngles:F2}");
    55.                 } else
    56.                 {
    57.                     spline.SetKnot (iB, curveKnot);
    58.                 }
    59.  
    60.                 prevMag = nextMag;
    61.             }
    62.             spline.SetTangentMode (TangentMode.Continuous);
    63.         }
    64.  
    65.         private static float3 bonePosition (in ITentailMeshBone bone, in float3 center)
    66.         {
    67.             if (bone != null)
    68.             {
    69.                 return (float3) bone.Position - center;
    70.             } else
    71.             {
    72.                 return 0f - center;
    73.             }
    74.         }
    75.  
    76.    public interface ITentailMeshBone
    77.    {
    78.        public float Radius { get; }
    79.  
    80.        public Quaternion Direction { get; }
    81.  
    82.        Vector3 Forward { get; }
    83.        Vector3 Up { get; }
    84.        Vector3 Position { get; }
    85.    }
    86.  
    87.  
     
    Last edited: Aug 29, 2023
  20. enemali

    enemali

    Joined:
    May 29, 2017
    Posts:
    18
    if you want to draw a On a gameObject , if the game object is a parent object in the hierarchy then your spline will snap to the object as desired but if the object is a child or grand child then the origin of the spline will be different and will not snap to the desired child object, you will have to manually move it .
    i wish it can auto snap to any selected object regardless of it being a parent or child object
     
  21. voodooRod

    voodooRod

    Joined:
    Jun 12, 2014
    Posts:
    8
    Thanks Thomas! It will help...I'm using them extensively. :)
     
  22. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,457
    Splines really need to be easier to select in the scene. Right now, you have to select them from the heriarchy, which means if you have systems that generate lots of splines there's virtually no way to name them such that the user actually knows which is which. I have tried various techniques of drawing gizmos along the knots and automatically selecting the spline, but they all have issues, such as:

    - Slowing the editor down a ton
    - Not being able to select game objects after selecting a spline because your in spline mode
    - Note being clear about which spline they belong too (hense drawing them on every knot)

    This needs an official solution, not something hacked on by the user.
     
  23. Dried09

    Dried09

    Joined:
    Jan 2, 2017
    Posts:
    7
    Yes, thank you for pointing me on this!
     
  24. MVS_1981

    MVS_1981

    Joined:
    Sep 10, 2020
    Posts:
    8
    Maybe a stupid question, but I am trying to constrain a rigidBody to a spline and move it along the curvature of the spline by touch control.
    It's probably something simple, but after going down a bezier curve rabbit hole for 3 hours , the mind has turned to mush :)

    Basically I use a raycast to determine if a finger is touching the object and then use the screen delta position to set a bool , which triggers a function in fixed update.
    With this I can basically move the object freely:
    Code (CSharp):
    1. rb.DOMove(new Vector3(rb.position.x + touch.deltaPosition.x * moveSpeed, rb.position.y, rb.position.z + touch.deltaPosition.y * moveSpeed), moveDelay);
    And with this , it snaps to the exact position I want it to be and doesn't take any user input :
    Code (CSharp):
    1. rb.Move(leftPosition, Quaternion.identity);

    Ideally I would like the object to snap to the spline in X & Z (preferably a relative position) and if the finger goes left , that it follows the positive direction of the curve to the end point of the spline direction ...and if the finger moves right that it moves in the negative direction of the spline direction.(See image below)

    upload_2023-9-5_1-55-58.png

    Thanks in advance for thinking along
     
  25. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,111
    @jbooth revealed his upcoming asset MicroVerse Roads today:



    @gabrielw_unity @ThomasLopez maybe you guys could have a blog or a mention about it? MicroVerse showcases the Unity Splines of you guys brilliantly and what you can do with them in various categories. The possibilities are awesome :)
     
  26. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,457
    Or just fix the bugs that you can see me hitting and talking about in that video and make splines selectable in some manner, as right now the whole system is made clunky by all the "ok, select one of the 50 roads in the heriarchy all named RoadXX, switch to spline mode so it's highlighted, oops, wrong spline". I tried a few different techniques, such as drawing my own gizmos over things, etc, and all of them help but we're either incomplete or unperformant in some manner. IMO, this is where the system struggles the most right now- it's just hard to make it feel like part of the tool your building instead of it's own separate thing which you're "dealing with".
     
    ThomasLopez likes this.
  27. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hey @sand_lantern! Me again!

    So using the rotation is the best way to do because otherwise your up vectors won't be correct.

    You are almost there, so you just need to understand in which space you are when using the rotation and the tangents.
    When you only set the knots tangents with no rotations, you'll end up with knots and tangents not pointing in the same direction, like this:
    upload_2023-9-11_10-28-27.png
    This is not really the best situation as your rotations are not aligned with the curve.

    Settings the knot rotation will get you to this result which is a lot more easy to use:
    upload_2023-9-11_10-25-16.png

    So to get there, you need to understand what's happening there to fix your case.
    In the case you only use the tangent you are computing the tangent out (outDir) to point to the next knot. Because you are not rotating the knot this is fine. But as soon as you'll need to o more complexe evaluation that's not gonna be the best for you.

    In the case where you tried to compute the rotations, you were doing :
     var rot = Quaternion.LookRotation(outDir) 

    So because of this, the knot is already pointing towards the next knot!!! :D You can directly express your tangent in this space so, your tangent out (outDir) is aligned to the forward direction :
    upload_2023-9-11_10-35-50.png

    So, the outDir you need now is simply :
    var out = Vector3.forward * scale;

    And your knot will be:
    curveKnot = new BezierKnot (current, -Vector3.forward * scale, Vector3.forward * scale, rot);


    Hope this helps :D

     
    sand_lantern likes this.
  28. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hello @enemali,

    I tried to repro what you are talking about but it seems to work fine for me (if I understood correctly your problem!), please have a look at the gif attached to this post and let me know if that's what you do.

    If this is not working for you can you please provide information on the repro ? (Video/gif, Unity version, spline package version...) and I'll try to figure out what's happening :D

     

    Attached Files:

  29. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Thanks for the feedback @jbooth.

    So the thing is that GameObject and spline knots cannot be handle in the same selection system because GameObjects are Objects in the Unity system, knots are not, they are only positions and not unity objects. That's the reason the spline context is there.

    If you want to easily change between GameObject and Spline context that's really easy and does not require to move the mouse every time it's needed. You can just configure the Cycle Tool Modes and Enter GameObject Mode in the shortcut manager! Actually pressing the ESC key while in the spline context will return to the GameObject context :)
    You'll only have to press one key to move to GameObject context and triggering the other shortcut will return to the last context you used (Splines!)

    I'm also surprised regarding the selection, gizmos in GameObject context already support splines selection, so I'm not certain I understand what you want here... Feel free to detail that a little more for us to see if that's feasible :)
    But keep in mind that Splines/Knots/Tangents are not objects but sub-elements of components :)

     
    Last edited: Sep 11, 2023
  30. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hello @MVS_1981,

    Did you had a look at our utility functions ? The
    GetNearestPoint
    might be your friend!
    You can use the user input to cast a ray in the scene and get the nearest point on the spline, then just move in the positive/negative direction depending where the object is itself on the spline. Would that work?

    Check this documentation for the utility mehod :)


     
  31. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,111
    This is like at work when people say the word "only" :D Nobody even knows that the key could / should be pressed ;)

    But all in all the splines have come a long way and it's getting where it's good usage. I really suggest you guys take a look at MicroVerse / MicroVerse Splines / MicroVerse Roads to see what's being created with your work. It's real world use cases created by an Industry Professional. I'm super impressed by the way this has gone so far :)
     
    ThomasLopez likes this.
  32. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,457
    The problem is that it's pixel accurate, and on a retna display in a 3d scene it makes it very hard to actually use scene selection- so much so that I didn't even know it worked at all until I tested in a blank scene. Even if you get it exactly on the right pixel, you still might select several other objects before the spline due to sorting so end up having to click several times to run through the list of selectables returned. In the video below, you can see how it doesn't return the spline before several other obejcts, and even when the cursor seems like it should select it often doesn't.



    Since I have a visual representation of the road, the ideal case would be that I could use it to represent the spline (IE: if this mesh is selected, it will select the parent spline object). I believe there's hooks in unity to do stuff like that, but the meshes get hidden to not clutter up the heriarchy, so they are not selectable either.

    Other posibilities would be a way to increase the line width on an individual spline so they cover more area than 1 pixel width on a 4k display, the ability to make knots always visible and pass through to spline mode (prototyped above, but too slow for large scenes with lots of splines), etc..

    Right now it all just feels super finicky to use, with lots of miss-clicks and mode changing, when it's possible to have a representation which doesn't require any of that stuff (as many custom coded spline systems have).
     
    ThomasLopez likes this.
  33. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    @jbooth,

    Just went through your entire video. So first, really amazing job here! Really neat solution to build roads indeed!

    So, I noticed at 9"04 you have a bug when creating a new knot using the draw spline tool. I tried to repro that on my side (using Unity 2021.3.30 and Splines 2.4.0) but I was not able to have this bug....
    Does it happen to you with a simple simple (when your components are not added)? Are you doing something custom on your side when a knot is added ? If you could have a simple repro case for me that would be great andI would be able to fix it :) Indeed, that's annoying!

    Finally at 25min I can see you are looking for the spline in the hierarchy, you can just select it in the scene using the gizmos :) (Plus use what I said in the other thread : ESC key + custom short cuts to easily switch between contexts :) )
    Like in the gif attached here!

    Hope this helps

     

    Attached Files:

  34. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Cross post XD
    Ok I see you trouble I'll try to see what can be done about that!
    The first option (selecting the mesh is selecting the spline) does not seem a good one as this is really a specific usecase here, and even more specific because the SplineContainer and the Mesh filter are not on the same object (or the road mesh component is hidden?), which makes it even more unique here.

    However, gizmos should be selectable, and that's not only for splines, that's a larger problem I guess in Unity if you are not able to select these because well, that's the purpose of gizmos right? XD
    I'll have a look at that!
    Thanks for the feedback

     
  35. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,457
    See above - it works, but as scene complexity grows becomes harder and harder to use in practice.

    As for the error, the actual error itself is from a null ref in UpdateCachePosition, which likely should be handed on your end.

    Code (CSharp):
    1. if(startIndex + n < (s_SplineCacheTable[spline]).Length)
    2.  
    3. //s_SplineCachedTable[spline] is null, even though the key exists..
    That said, I do a lot of processing when splines change - including removing the roll from the existing spline keyframes to prevent unwanted roll on the splines. But nothing that adds or removes keyframes, or should null out whatever your caching here. I'll try to round down what might be triggering it..

    EDIT: Actually I do not process the keyframes themselves, instead I process the data in the jobs and leave the roll on the spline, so it's not editing the spline at all.
     
    Last edited: Sep 11, 2023
    Rowlan and ThomasLopez like this.
  36. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,457
    It's definately a custom use case, but not an uncommon one for a spline system. You have several mesh generation systems in your examples, for instance, all of which share this same issue. And while I think "making splines easier to select" is a perfectly fine and general way to solve it, this kind of highlights what I was talking about a while back in that we don't really care about splines, but rather what we are creating with them, be that a road, river, or whatever. Unity already has the [SelectionBase] attribute, which while I'm not advocating that as a solution, shows that this is not a unique problem to splines either, but rather common in systems which generate heriarchies of objects.

    Anyway, this is why I was spending a bunch of time trying to get splines to draw knots all the time and having selection bring you right into editing that spline - because that's kind of what the user wants, to edit the knots of their road, not of a spline which controls the road. I personally feel the more splines can be made to feel natve to your tool set, the more likely we'll have other solutions build on them. And for me, that was the whole gamble with not writing my own- easy interop with other people's stuff.
     
  37. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,457
    Ok, I think I found what is triggering the issue and a workaround that works for my case, but likely still something you want to protect against. I have a function which calls SetKnot, which is triggered when a spline changes. Changing that to SetKnotNoNotify will prevent the issue. However, currently that function is called in several places, so wants to use the notification version in one of them (I can work around that).

    So what I think is happening is that when the system gets triggered from a spline change, it calls SetKnot, causing the internal cache to be changed, which causes this function to null ref. It does seem like the caller shouldn't have to worry about this though- like SetKnotNoNotifiation should be an optimization to not do extra work, not something the user should have to correctly use to make sure all knot updates are done before notifying, right?
     
    ThomasLopez likes this.
  38. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    @jbooth,
    Using SetKnot is totally fine indeed, and that definitively should be working!
    I think I found a fix for this, this should be ok in the next update! Thanks for the explanations on your problem, as this was not possible to repro on our side, that was more complicated to find a fix :D ! You'll let me know!
     
  39. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    So, one think we did was to make all of the Spline tools public so that they can be directly triggered by users code!
    So that's something that can be directly done if you need it in your package.

    However, that's a little more than just this, it's getting a little more complex in case of multi-select and if multiple objects have multiple contexts. :)


     
  40. TMC_FumiyaMatsune

    TMC_FumiyaMatsune

    Joined:
    Aug 30, 2023
    Posts:
    11
    Thanks for providing great assets.
    It is a great asset that many people will need in the future. Is there one feature that would be nice if you were using this asset?
    We are considering a mechanism that allows users to freely change the route of the spline even in the game scene during game playback.
    Is there such a feature in this asset? Could you please let me know if there is?
     
  41. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,111
    Example use case of Unity's Splines using MicroVerse Roads



    Starts around 04:55 in case the link doesn't forward you directly to it ;)

    This is how fast Unity can actually be :D
     
    Lurking-Ninja likes this.
  42. TMC_FumiyaMatsune

    TMC_FumiyaMatsune

    Joined:
    Aug 30, 2023
    Posts:
    11
    Thank you for the video.
    I was really looking forward to working with this asset. I'm sorry.  I didn't communicate myself well.
    Is it possible to edit splines within the game scene while the game is playing?
    Or is it possible to display the spline editing object displayed on the editor screen in the game scene?
    Since I am an amateur, there are many things I don't understand、、、
    I would be grateful if you could tell me if you have any examples.
     
  43. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    @TMC_FumiyaMatsune,

    A little clarification on this. So you have the Scene view made to design and interact with your 3d elements and design your game, and the Game view, to run your game and test your game play.
    So, while the game is playing, you can modify elements in the Scene view to directly see the impact of these change in the Game view and test them straight away (however these changes won't be changed when you'll leave the playmode).

    In case you want to display the splines or interact with these at runtime (during your game), you'll have to design that. This is not done now, totally feaisible, but will depend on you game and gameplay :)

    Hope this helps!

     
  44. TMC_FumiyaMatsune

    TMC_FumiyaMatsune

    Joined:
    Aug 30, 2023
    Posts:
    11
    Thank you for your careful explanation.
    The lack of examples means that I will be the first challenger! We will proceed with various studies.
    In that case, we would appreciate it if you could contact us again.
     
  45. nicmarxp

    nicmarxp

    Joined:
    Dec 3, 2017
    Posts:
    405
    Sorry if this was already mentioned in the thread, but is there any way to add colliders to the spline, so it can be used for example to build a 3D road that is not flat? The tool looks great, but without colliders it's not as useful in my opinion.

    I noticed this in the asset BG Spline which supports both 2D and 3D colliders.
     
  46. PaulMDev

    PaulMDev

    Joined:
    Feb 19, 2019
    Posts:
    69
    I think you can just use the mesh generated by the spline to put it in a mesh collider.
     
    ThomasLopez likes this.
  47. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hey @voodooRod,

    So I got a fix for the allocation problem.
    Meanwhile I figured out that this allocation problem would exist with these 2 functions:
    Code (CSharp):
    1. SplineContainer.EvaluatePosition(float t)
    and
    Code (CSharp):
    1. SplineContainer.EvaluatePosition(int splineIndex, float t)
    .

    However, while waiting for the fix, you can use this one to avoir allocation:
    Code (CSharp):
    1. SplineContainer.EvaluatePosition<T>(T spline, float t)
    Doing
    Code (CSharp):
    1. myContainer.EvaluatePosition(myContainer.spline[0],t);
    Hope this helps!


     
  48. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hi @nicmarxp, there is nothing done for that right now, but this can easily added to the spline package here.
    Indeed, the colliders you would need would depend on the use case you have (roads, pipes...) and how you want to fit them to the spline (on top of it, centered on the spline...).

    My guess, if I understand your needs better, is that you would want more to build you mesh using spline and then use mesh colliders on the resulting mesh. But the way to define colliders from a spline are greatly defined by your specific case! We are mostly provided the API here to do such tools, but we are not doing all of them :)

     
    nicmarxp likes this.
  49. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,111
    The spline knot reduction method is awesome. Is it at its fastest yet or could it be optimized? MicroVerse Roads could definitely handle the mesh, it's just the knot reduction of the Unity Splines that takes a bit. Would be nice to have this in realtime with roads instead of proxy:


    But it's fast enough I guess with the proxy line :D The Unity Splines are shaping up nicely :)
     
    Last edited: Sep 24, 2023
    ThomasLopez and Weendie-Games like this.
  50. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,111
    Yeah, well, that road painting escalated quickly in painting entire biomes with Unity Splines :D

     
    Lars-Steenhoff and ThomasLopez like this.