Search Unity

[WIP] Easy to use and simple spline tool

Discussion in 'Tools In Progress' started by Antony-Blackett, Feb 16, 2020.

  1. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Hi all. I've used almost all the spline tools on the asset store and to be honest they all annoy me for a number of reasons. Some are hard to set up. Some are hard to place and edit points in 3D space. Some just break if you look at them long enough. And the the rest are so complicated or obtuse it takes a rocket scientist to actually use them.

    I've decided to take matters into my own hands and I started building a simple spline tool. The goal of this tool is to:
    • Make spline creation simple and easy
    • Make editing a spline (moving points, adding points, inserting points, deleting points, etc) simple.
    • Build an intuitive interface so that you can easily understand where the spline is in 3D space. (I'm basing this on the Homeworld interface, if you haven't played it, play it!).
    • Build it robust. Working with undo and redo. Making it so that it never breaks and never gets null exceptions even when points are deleted etc.
    • Make it fast! No alloc, no GC at runtime.
    Here's a short video of how it's going. Let me know if this is something you'd like to use and I'll see if I can make it available in future when it's more complete.

     
    Last edited: Jul 27, 2021
  2. VoxelMatt

    VoxelMatt

    Joined:
    Apr 22, 2015
    Posts:
    42
    Nice work!
     
  3. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Wow thanks, handsome stranger.
     
  4. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    More progress on my new spline tool.

    Features demonstrated in this video:
    Bezier curves
    Different control modes for points (point, mirrored, aligned, free)
    Multi point selection with drag select
    Flatten selection
    Move selection

     
    Last edited: Feb 18, 2020
  5. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Adding the usual spline functionality.

    Cube moving at consistent speed
    83726149_546394216244271_1197667874055913472_n.gif

    Credit to VoxelMatt for help on this too.
     
  6. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Playing around with this new spline tool, I built a logo in about 3 minutes. I actually forgot to write the N at first, so I inserted it using the insert feature, I then realised I wrote the N in the wrong place between E and S, doh! Not to worry though, I cut E and S out using shift drag select and ctrl X and then pasted them to the end using ctrl V! I love it when a plan comes together!

    Screen Shot 2020-02-20 at 9.52.08 AM.png
     
    Last edited: Feb 20, 2020
    wetcircuit likes this.
  7. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Focus, simply hit 'F'.

     
  8. VoxelMatt

    VoxelMatt

    Joined:
    Apr 22, 2015
    Posts:
    42
    This is one cool feature I haven't seen in SuperSplines or some of the other spline editors.

    Runtime editing of a spline, and not breaking the position of all the spline objects. (And 100% alloc/GC free)

    EditingWhileMoving.gif
     
    Gekigengar and MPM like this.
  9. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Could this be the greatest spline system ever built?
     
    Gekigengar and John_Leorid like this.
  10. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Another minor but still annoyance with other spline tools fixed. Editing control points now intelligently selects which control point to manipulate based on your input and the spline around it.

     
  11. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Finalising the code interface for my new spline tool:

    Code (CSharp):
    1.  
    2. public interface ISpline
    3. {
    4.     SplineResult GetResultAtT(float splineT);
    5.     SplineResult GetResultAtDistance(float splineDistance);
    6.     SplineResult GetResultAtSegmentT(int segmentIndex, float segmentT);
    7.     SplineResult GetResultAtSegmentDistance(int segmentIndex, float segmentT);
    8.     SplineResult GetResultClosestTo(Vector3 point);
    9.     SplineResult GetResultClosestTo(Ray ray);
    10.     SplineResult GetResultAtWorldDistanceFrom(float startSplineDistance, float worldDistance, float stepSplineDistance);
    11. }
    12.  
    Code (CSharp):
    1.  
    2. public struct SplineResult
    3. {
    4.     public float t; // 0 - 1 along spline
    5.     public float length; // real world length of the spline
    6.     public float distance; // real world distance along spline before wrapping
    7.     public float loopDistance; // real world distance along spline after wrapping
    8.     public bool isLoop; // is the spline looped
    9.     public int lapCount; // number of times looped distance
    10.  
    11.     public Vector3 position => segmentResult.position;
    12.     public Vector3 tangent => segmentResult.tangent;
    13.  
    14.     public bool AtEnd => !isLoop && Mathf.Approximately( t, 1 );
    15.     public bool AtStart => !isLoop && Mathf.Approximately( t, 0 );
    16.  
    17.     public SegmentResult segmentResult;
    18. }
    19.  
    Code (CSharp):
    1.  
    2. public struct SegmentResult
    3. {
    4.     public int index;
    5.     public float t;
    6.     public float distance;
    7.     public float length;
    8.     public Vector3 position;
    9.     public Vector3 tangent;
    10.  
    11.     public bool AtSegmentEnd => Mathf.Approximately( t, 1 );
    12.     public bool AtSegmentStart => Mathf.Approximately( t, 0 );
    13. }
    14.  
    that's it, super simple.
     
    Last edited: Feb 24, 2020
  12. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    I have been working on the interface and making some really nice little tools that allow you to set and edit multiple nodes in the spline at once. Here's an example of setting the X position on 4 nodes at the same time.

     
  13. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Here's my first attempt using my spline tool in production on my new mini golf game.

     
    Gekigengar and teutonicus like this.
  14. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    I have to get onto actually building my game. But that gives me a good opportunity to battle test this new spline tool. You may not see many more updates in the near future but I'll still be chipping away at it and may post updates from time to time.
     
    one_one likes this.
  15. dibdab

    dibdab

    Joined:
    Jul 5, 2011
    Posts:
    976
    it does look like a good spline tool.

    can the nodes be edited in code ?
     
  16. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Yep. SetNode(int index, SplineNode node)
     
  17. Lars-Steenhoff

    Lars-Steenhoff

    Joined:
    Aug 7, 2007
    Posts:
    3,527
    Can you add object placement along the spline? and random object placement.
    And align to terrain? or mesh

    Thanks
     
  18. dibdab

    dibdab

    Joined:
    Jul 5, 2011
    Posts:
    976
    SetNode(int index, SplineNode node)

    so first you create a node (position, type etc) and then you set it for spline?
    am I understanding this right?
     
  19. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    I'll probably add projection onto physics so you can project onto meshes or terrain using that.

    As for moving and placement on the spline, That'll be up to you using the interface provided. Here's an example script of an object placed along a spline at a distance (world distance):

    Code (CSharp):
    1. SplineResult result = spline.GetResultAtDistance( distance );
    2. myGameObject.position = result.position;
    3. myGameObject.rotation = Quaternion.LookRotation( result.tangent, Vector3.up );
    You could place objects randomly by randomising the distance argument passed into GetResultAtDistance()

    to move the object along the spline you would add to the distance variable each update.

    Code (csharp):
    1. distance += speed;
    I over simplified before. There are multiple ways to add and change nodes:

    You can create a new node:
    SplineNode node = new SplineNode( worldPosition, control1, control2 ); // control1 and control2 are relative to worldPosition

    from there you can either update an already existing node using:
    Code (csharp):
    1. spline.SetNode( int index, node );
    you can append or prepend a node to the spline using:
    Code (csharp):
    1. spline.AppendNode( node );
    2. spline.PrependNode( node );
    you can also insert the new node using:

    Code (csharp):
    1. spline.InsertNode( int index, node );
    And finally you can create a new node on the spline without changing the curve of the spline by using:
    Code (csharp):
    1. int newNodeIndex = spline.InsertNode( float distance );
    this will create a new node at that point on the spline and set the controls of the previous and next nodes such that the spline is the exact same shape it was before the node was added.
     
    Last edited: Jul 29, 2020
    dibdab and Lars-Steenhoff like this.
  20. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    So after all that, I see this in the latest unity update...

    Screenshot 2020-03-26 at 9.43.59 AM.png

    I wish there was more details about this new generic spline from unity.
     
  21. dibdab

    dibdab

    Joined:
    Jul 5, 2011
    Posts:
    976
    nevermind. what you got is a well-designed tool
     
  22. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Thanks, I'll keep chipping away at it. I'm using it to make my mini golf game and there are definitely more improvements to workflow that need addressing.
     
  23. gasppol

    gasppol

    Joined:
    Feb 16, 2020
    Posts:
    33
    Antony-Blackett is there any new update on your Spline Tool? Did you make it available anyhow?
     
  24. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Hi. No sorry. I’ve been to busy working on my game to focus on this tool. I have been using it in my game and have found a bunch of things that need fixing for a public release...

    Alternatively i could release it as is on git hud but I’m concerned that’ll distract me from what i need to get done on my game.

    And the news of unity spline coming soon kinda stop my development as well. I wanted to see what their tools will offer. Ideally we can all just use that when it’s made available. The question is when will it be out? No idea....
     
    arpan018 and gasppol like this.
  25. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    I've started some more work on this spline tool as it seems Unity Spline is never coming out and I need more features, now!

    Here's my latest feature, Automatic node tangent controls.


     
    Gekigengar likes this.
  26. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    I'm looking into adding spline normal's as well as other data that can be interpolated along the spline.

    All other spline tools i see add this data to control points. I find this frustrating as you may want a value like a float to blend from 0-1 across some length midway through the spline, if you tie it to control points then the more complicated the spline is the more nodes you need to adjust when adjusting how that float value is to blend across the spline.

    My idea: Spline key frames. Key frames will hold a piece of data and can be placed anywhere along the spline independently of control points. These key frames can then be slid up and down the spline in the editor so a float the blends from 0 - 1 can have two key frames placed along the spline and then that 'Spline Data Track' can be asked what the value is at a position along the spline:

    Something like this:
    Code (csharp):
    1.  
    2. SplineDataTrack<float> splineDataTrack = spline.GetDataTrack<float>( "MyDataTrackName" );
    3. float myInterpolatedValue = splineDataTrack.GetValueAtDistance( distance );
    4.  
    Wish me luck!
     
    angrypenguin likes this.
  27. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    A couple quick videos to show progress on spline keyframes:



     
    Last edited: Jul 14, 2021
  28. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Building a tool to move keyframes around on a spline.

    Here's a demonstration of keyframes defining a normal for the spline through a loop.

     
    Last edited: Jul 15, 2021
    bobadi likes this.
  29. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    I've pretty much finished the spline keyframes system now. I've got a spline keyframe track working with a tool to place, move, remove, and edit keyframe positions. The keyframes magically (keep) their position on the spline even when the spline is edited. All the keys are stored in spline local space so spline scaling, rotating and moving works as you'd expect. The tools also handle it as well so you can easily edit scaled and rotated spline keyframes no trouble.

    All the code is broken up into reusable parts so it's easy to extend a SplineKeyframeTrack and handle whatever data type you like so long as the data is a value type (struct).

    Custom data types are also possible. all you need to do is create your own class that extends SplineKeyframeTrack<T>, implement your own interpolation function, Transform and InverseTransform functions (to handle spline transformations for things like normals) and finally your own Handle to edit the data on the keyframes in the scene view.

    Here's an example use of the system:

    Code (csharp):
    1.  
    2. float distance = 10; // distance in world space along the spline
    3. SplineResult location = spline.GetResultAtDistance( distance );
    4. Vector3 normal = splineNormal.GetValueAtDistance( distance );
    5. Gizmos.DrawLine( location.position, location.position + normal );
    6.  
    The result being that if you have a spline with 100 control points and you need to edit the normals of that spline, you now only have to change a few keyframes across the entire spline rather than having to edit each control point like other spline tools.
     
    Last edited: Jul 17, 2021
  30. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Latest addition. Raw keyframe value editing in scene view.

    RawValueEditing.PNG
     
  31. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    And works with all sorts of types.

    Screen Shot 2021-07-19 at 12.43.18 PM.png
     
  32. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Keyframed Spline Parameters (new name) can now have multiple instances of the same type on a single GameObject and spline.

     
  33. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Hi all.

    I've come a long way in the last couple weeks and I think the tool is starting to mature nicely. However I do need some feedback so if anyone is keen to get their hands on it and tell me what they think I'd be happy to share it through github.
     
  34. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    I've started adding geometry generation.

     
  35. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    I don't know if anyone is even reading this thread, but here's some more progress on geometry generation.



    Demonstration of geometry generated at differing levels of detail around a spline.

    Key features:
    - Spline control points are always sampled.
    - The width of the shape being extruded is always the same no matter the angle at a corner.
     
  36. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    651
    Haven't read it all but it looks quite promising. There are 3 reasons why we stopped using our previous spline tool and replaced every single cable with hand-adjusted prefabs.
    1) GPU Performance - the generated spline had either streched UVs, which was unacceptable or way, way to many polygons. We went with the second one and the sum of cables became the most polygon-consuming objects in our game world.
    2) CPU Performance - splines were generated in OnEnable, disabling/enabling objects is our way to support a seamless world - well the "seams" became pretty noticable thanks to those splines
    3) Editor Performance - after every single recompile, all cables were re-built, pressing play & stop -> cables rebuilt. Tons of Garbage, tons of calculations, it took up to 4 seconds, just regenerating cables after changing a line of code or entering/exiting play mode.

    How about your tool? How do you handle mesh generation, UV stretching and all that stuff?
    How about runtime cables - a shader deforming the vertices instead of CPU, so it is cheap to move those around .. making it possible to attach hingeJoints and rigidbodies to it so one can build a rope with it (or swinging cables).
     
  37. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Hey, yeah all good questions and not all I have answers for at this time, but I'll do my best:


    I'm working on the generator right now with this in mind. As you can see in the latest videos I enable the user to slide a 'sampleDistance' variable and toggle on and off various sample options like, 'sample spline control points', 'sample spline normal keys', 'sample spline color keys' etc... The generator also has a tolerance calculator so you can set the acceptable level tolerance per variable, i.e. Normal tolerance angle, Tangent tolerance angle etc. and the generator will simply skip samples that are within the accepted tolerance, reducing overall geometry.

    I've just started working on a solution to stretched UVs as well. I have a plan for it and hopefully it'll mean less samples will be needed to ensure nice UVs on long tube sections with few samples. I'll post a screenshot when i'm done.

    My goals sound very similar to yours and my solution is to make the generator as accurate as possible with as few samples as possible which should help with performance of generating and rendering while also providing great results.

    Performance was a key consideration. Splines are not generated, they are stored as data on a spline component in local space to the transform. This means moving a spline, enabling and disabling has zero additional overhead to the usually Unity stuff. Sampling splines at runtime has no allocation and so no garbage collection.

    When editing a spline all that happens is control points get added and removed from a list, that's all. So minimal allocation. I might add a reserve size option so that you can ensure no allocation up to a number of spline control points.

    Splines have a couple ways of letting other objects know when they've changed. I haven't tested it much yet but I don't see why you would need to regenerate anything on compile or on play and stop in the editor as the spline data has not changed so as long as everything being generated from the spline is serialised, there should be nothing to do in those cases.



    I answered as best i can above.

    Yeah that sounds like a good solution. There's no reason you couldn't do this. You might need to add some extra data to the verts generated, like add extra uv sets to hold data you can use for your shader. It might need some additional custom code but it wouldn't be hard to do.

    I think you'd need a spline to define where you spawn rope segments, the rope segments would then take care of everything else from there. I'll try make my geometry generator fairly generic so you could feed in some array of points and regenerate the mesh from the simulated rigidbody position yourself.
     
    Last edited: Jul 22, 2021
  38. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    I think this is the best solution in the general case for a tube generator.

    Screen Shot 2021-07-22 at 3.12.55 PM.png Screen Shot 2021-07-22 at 3.14.10 PM.png
     
  39. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    After only a couple days, I have a fairly optimised geometry generator.

    Screen Shot 2021-07-22 at 6.23.39 PM.png
     
  40. greg-harding

    greg-harding

    Joined:
    Apr 11, 2013
    Posts:
    524
    hey Antony! Yep, I saw your thread a while ago :) You restarted work on your tool about a day after we were looking for some spline tools to test out. I had revisited the thread a few weeks ago while looking for tools and assumed that it was on pause/abandoned...

    Keen to check it out sometime!
     
  41. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Cool, I’m thinking of getting it into someone else’s hands sooner rather than later just to see if I’m making a good tool from a users perspective. If you’re keen i can share the code.

    what’s your use case? I’ll let you know if I plan on supporting the features you need.
     
  42. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    UVed corners are getting better!

     

    Attached Files:

    Last edited: Jul 22, 2021
  43. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Rounded corners

    Screen Shot 2021-07-23 at 4.39.57 PM.png
     
  44. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    Nice work. I am not very active at the moment but your work looks very interesting. I also had my struggles with various spline tools in the past…nice to see a fresh approach
     
  45. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Thanks! Yeah, it's cool now it's all coming together!

    Here's come rounded corners that i just got working in 3D!

    Screen Shot 2021-07-23 at 6.11.42 PM.png
     
  46. greg-harding

    greg-harding

    Joined:
    Apr 11, 2013
    Posts:
    524
    I've previously used my own basic code splines or modified stuff from GoKit/ZestKit tweening libraries which are fine for code stuff but don't offer much in the way of editor/scene features, normal/tangent visualisations, mesh/collider generation, etc.

    We've been messing with some splines in prototypes for paths, mesh and collider generation (both in 2d/xy and 3d), and for moving objects around those splines with offsets but respecting the distance travelled properly. It's handy to have good apis and components for positioning stuff based on distance and % and for adding nodes/callbacks when things move past certain points. Being able to build a spline with tools that snap to colliders (or geo) has been really useful as well. Also, we have been using junctions at nodes to split and rejoin multiple splines to create branching and merging paths. We will probably be looking at using splines for things like Cinemachine cameras too. One other thing that has proven useful is being able to freely change the type of spline, ie. switching catmull rom to bezier to nurb etc. depending on the situation, like how well a spline is conforming to some existing geometry or something.

    It looks like you've got plenty of this sort of stuff going already - sweet.
     
  47. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Hi, yeah. I'm planning and have completed some of those things already.

    I'd say the biggest thing I'm not really planning to do at this stage is junctions. I have an idea of a good way to do it, but I personally don't need it so it's way down the list of things to get working. I've also never used junctions in other spline systems so i'm not sure what the sticking points are in terms of usability and how to best implement them for quick iteration of game content. My idea for this is to define a 'Junction' which knows where and in which direction two or more spline join. And then if you need path finding have a Spline Graph object that knows about all of the junctions and therefore has all the information it needs to do path finding etc.

    I've also focused mainly on 3D, so when trying to make a 2D spline on the xy plane the editor is not really designed for that, you can rotate a spline around the x axis and then work on the local x,z grid but that's not an ideal solution long term. I need to build a 2D editing mode where you can set the desired plane the spline sits on.

    I also don't have the ability to swap spline types, I only have bezier implemented at current, but i assume you could just swap the interpolation functions for position and tangent to do this, so shouldn't be a difficult addition.

    As for moving along and having callbacks trigger when pass a point, i think that's up to the user. The spline shouldn't know about these things. It wouldn't be difficult to build a small class that handles this stuff though.
     
  48. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    I've now got nice 3D Rounded, Square, Mitre and Simple corners all working with normal deformation (twisting).

    Here's a twisted spline with Rounded corners. You can set the corner angle threshold so if you'd prefer no generated corners you can do that too. Corners help keep the geometry from intersecting when the spline takes acute angle turns back on itself.

    Screen Shot 2021-07-26 at 2.03.46 PM.png
     
    hippocoder likes this.
  49. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    4 identical splines with tube generators each with a different corner type to illustrate how they work and now they affect UVs and geometry.

    Simple, Mitre, Square, Round

    Screen Shot 2021-07-27 at 9.31.48 AM.png
     
    hippocoder likes this.
  50. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    Custom extrude shapes.

    Screen Shot 2021-07-27 at 12.35.55 PM.png
     
    hippocoder likes this.