Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

SplineMesh, the plugin to create curved content

Discussion in 'Assets and Asset Store' started by methusalah999, Dec 14, 2017.

  1. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    A short video featuring the 1.2 showcase. Hope you like it !

     
  2. Pheck

    Pheck

    Joined:
    Jul 9, 2009
    Posts:
    194
    I have never used the tool before, just saw it and tried it out. fresh install from the store and it was reporting those issues. Ill try a repro for you later and post a screen shot and repro steps.
     
    Last edited: Apr 5, 2019
  3. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    Could you please some details about the error, and the version of Unity you are using? Thanks !
     
  4. NewSystemGames

    NewSystemGames

    Joined:
    May 23, 2017
    Posts:
    299
    Hi, first of all thank u so much for this asset.

    I have 1 small problem, i was playing around making some shapes... and i noticed on the mesh will go up and down in small bits. see the image, those lines.. how can i make it so this will be smooth straight?

     
  5. jRocket

    jRocket

    Joined:
    Jul 12, 2012
    Posts:
    544
    Is there a recommended way to modify the spline at run-time? I mean, modifying the node positions. I tried re-creating the spline every frame but performance was poor.
     
  6. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    I've already spotted this bug in the showcase. Can you confirm that it occurs with the SplineExtrusion component?

    It's an issue with the mesh's normals, but I can't give you a fix right now. I'll look into it soon and come back to you.

    You're right, recreating the spline at each frame is a bad idea ^^

    To edit spline at run time, just set the nodes' properties like
    spline.Nodes[i].Position = newPosition;
    . The event system will ensure that everything updates correctly.

    If you are using an older version of SplineMesh (1.0), please use the method SplineNode.SetPosition and SetRotation instead.
     
    irenya likes this.
  7. NewSystemGames

    NewSystemGames

    Joined:
    May 23, 2017
    Posts:
    299
    I cant confirm (Just started using this) but it appears to be .
     
    Last edited: Apr 22, 2019
  8. NewSystemGames

    NewSystemGames

    Joined:
    May 23, 2017
    Posts:
    299
    I'm having difficult time texturing spline meshes, is there a guide for this?
     
  9. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    I've looked into it and made some tests. I've changed the code so that the 2D shape extruder uses the same logic than the mesh bender. The results are exactly the same and the normal issue is still visible.

    I can't see any issue with normal calculation and i suspect Unity to make some approximations in normals' interpolation. A simple fix is to add vertices on long faces. With more triangles, the problem disappear.

    Texturing the 2D shape extruded face is quite simple :
    - specify U coordinate at each point of the shape, using the inspector view,
    - specify the V scale for the whole generated mesh along the interval.

    Only uv1 channel is available.

    Please telle me if you encounter any specific issue.
     
  10. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    Is this problem solved now?

    I would like to ask about your initial need: create a spline from a set of point. Have you figured out a solution to that?
     
  11. jRocket

    jRocket

    Joined:
    Jul 12, 2012
    Posts:
    544
    What I did to create the spline from an array of points is to set the "direction" of the node to be the next point, so you end up with two points per node. It works well enough. As for changing the spline at run-time, I haven't looked more into it yet.
     
    methusalah999 likes this.
  12. Weidz_

    Weidz_

    Joined:
    Feb 15, 2018
    Posts:
    20
    The hold & drag with ALT to create a new node doesn't seem to work on 2019.1(.0f2) either.
     
  13. tgd-uni

    tgd-uni

    Joined:
    Dec 16, 2018
    Posts:
    9
    You need to SHIFT+ALT
     
  14. NewSystemGames

    NewSystemGames

    Joined:
    May 23, 2017
    Posts:
    299
    that never didn't work for me also, had to change Shirft-ALT to Shift-Caps Lock lol
     
  15. tgd-uni

    tgd-uni

    Joined:
    Dec 16, 2018
    Posts:
    9
    I got a question about the sower example. There is an offset parameter for placing the prefabs along the spline that does not look correct when used with the mesh extrusion. Actually you can see it right in the bridge showcase example where the light poles are hovering in different distances above the extruded mesh depending on the bending of the mesh.
    I do not understand the code well enough to fix this. Still bit confusing to me to reason about tangents and binormals.
    How to get these poles to be placed on the "surface" of the mesh regardless of offset and mesh bending?

    upload_2019-5-9_14-20-55.png
     
  16. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    That won't work anymore on 2019 and I don't know why so far. Unfortunatly I haven't a lot of time at the moment to investigate.

    Help is appreciated via github ! ;)
     
  17. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    It's a bug in ExampleSower. In the code, please use the following instruction:
    Code (CSharp):
    1. // in ExampleSower.cs at line 100, replace this:
    2. Vector3 binormal = sample.tangent;
    3. binormal = Quaternion.LookRotation(Vector3.right, Vector3.up) * binormal;
    4.  
    5. // by this:
    6. var binormal = (Quaternion.LookRotation(sample.tangent, sample.up) * Vector3.right).normalized;
    7.  
    Tell me if it's working. If so, it will be in the next update. Thanks for your report !
     
  18. tgd-uni

    tgd-uni

    Joined:
    Dec 16, 2018
    Posts:
    9
    Yes it works. Thanks for the quick fix!
     
    methusalah999 likes this.
  19. MycroSparks

    MycroSparks

    Joined:
    Mar 15, 2013
    Posts:
    6
    Hey, first of all, thanks for the amazing asset :)

    I've been playing around with it, seeing if it could work in the long run in one of the projects I'm working on, and I've came up at some issues (due to my inexperience for sure)

    - I've made a simple project where I get the t value along the spline based on where the user clicked, and it works pretty good (I'll definetely have to improve the precision once I get deeper, but your asset gives me all the tools i need). The issue I'm having is when i add a node at the position of t = x along the spline, where x is where the user clicked along the spline, the mesh won't update in real time (play mode). What am i doing wrong? I'm using the InsertNode() function of your spline class, and in the scene view the new node places perfectly where i want it, but the mesh doesn't update. I've even tried calling the CreateMeshes() func directly after changing nodes, but still doesn't work.

    - The same type of problem arises when i don't necceserely add/remove nodes, but move them. For example, I've wrote some code that moves the last node of the spline down to where t = lastNodeT - 0.5 (basically placing it between where the previous node and the current one are). Which again, works perfectly in the scene view, the nodes placed right where i wanted it to be, but the mesh doesn't render real time :(

    Id appreciate any type of advice you could give me, since I realize I'm missing something crucial that'll allow me to get a full understanding of the splines behavior. Thanks in advance!

    EDIT:
    I've played around with it a bit more and noticed that if i toggle CurveSpace on and off while in play mode, the mesh updates appropriately. Without doing this, after adding a few nodes between node 0 and 1, a new spline is generated, while the old one doesn't get cleaned up.
     
    Last edited: May 15, 2019
  20. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    Are you using the SplineMeshTiling script as a mesh deformer ? If so, please note that is has a boolean property called "Update in play mode" that is false by default. It's editable in the inspector.

    As stated in this property tooltip, it allows baked meshes to be preserved from edit mode. Can you check that first?
     
  21. MycroSparks

    MycroSparks

    Joined:
    Mar 15, 2013
    Posts:
    6
    Thanks for the quick response!

    Yes, I'm aware of that property, and have it toggled on, I've attached an img of what my gameobject looks like in the inspector :)
    I should elaborate a bit, I also have a function that deletes the last node of the spline, and that one does work the way it's intended, the mesh updates the moment after removing the last node (spline shortens in real time). The issue that I'm experiencing seems to only happen when i insert a node between other nodes (adding a node above the last one also seems to work).

    I can elaborate a bit more on the exact issue. In my app, I've made a spline with 4 nodes in the editor. Now in realtime, when i add a node between nodes 0 and 1, the spline's mesh doesn't update (I'm adding the new node at some t = [0,1] position for these particular nodes, where the user clicks with the mouse, + I move it a bit because having a new node exactly on the spline wouldn't change the mesh at all). In the editor though, I see the spline line get bent differently, and work as intended.
    Now, when i keep adding more nodes at a similar location, at some point the mesh doesn't neccesserily get updated, but adds a new spline mesh that follows the new, user created spline line (with all the added nodes). It doesn't clean up the existing one though.

    Any thoughts on what might be causing this? I'm thinking that maybe when adding new nodes inbetween existing ones, there needs to be more steps then just doing the InsertNode() function, where the SplineNode arguments are the generated sample's position along t for it's position (+ an offset), and the direction being (node 0's direction + node 1's direction) / 2.

    Any tips or thoughts would be greatly appreciated!
     

    Attached Files:

  22. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    I see that you are asking the mesh to repeat on each curve. Repeat mode allows the mesh to be drawn as many time as it can fit in the curve length, meaning that the mesh won't appear at all if it can't fit at least once. This may occur if the resulting curves are not long enough after your node insertion.

    Can you please try the strecth mode? The mesh will be scaled to fit exactly inside each curve. This may not be what you want ultimatly, but it would tell if this is a not-long-enough-curve issue.

    I continue to think about it while you test that.
     
    MycroSparks likes this.
  23. MycroSparks

    MycroSparks

    Joined:
    Mar 15, 2013
    Posts:
    6
    I've given it a test, and the results are still the same as in when repeat mode is chosen sadly :(

    I'll attach a few screenshots of what the spline looks at like in runtime in the hopes it might provide more information about the issue I'm having. Screenshot_2.png is the base of the spline I've made in the editor, and Screenshot_1.png is that same spline after I've added 2 nodes between node 0 and 1 at runtime, through my attached script (as you can see, the mesh doesn't update and twist as it should with the new spline).

    Again, thanks for all the help and replies, I'm very grateful :)
     

    Attached Files:

  24. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    Don't look any further, it's a very simple bug in SplineMeshTiling.cs. In this file, line 53, follow these instructions:

    Code (CSharp):
    1. private void OnEnable() {
    2.     [...]
    3.     spline = GetComponentInParent<Spline>();
    4.  
    5.     // add this single line
    6.     spline.NodeListChanged += (s, e) => toUpdate = true;
    7.  
    8.     toUpdate = true;
    9. }
    10.  
    This script in rather new and it seems I just forgot to wire the spline's NodeListChanged event. This should do the trick.

    Please tell me if it works so I can put it in the next SplineMesh version.
     
    MycroSparks likes this.
  25. MycroSparks

    MycroSparks

    Joined:
    Mar 15, 2013
    Posts:
    6
    I've added the fix, but I'm still having some issues :(

    I've experimented a bit more, and it seems that the spline starts auto-updating in play mode when i tick the "Curve Space" toggle of the SplineMeshTiling script off and on again. However, even after it starts auto-updating after doing so, the mesh between the new node and the next one doesn't get generated for some reason (all the other meshes are generated fine).
    I've attached some screenshots again, in which I'm inserting a new node that's at t = 0.5 (between node 0 and 1) in images Screenshot_2.png, Screenshot_3.png, as well as the image of what it looks like at the start (Screenshot_1.png), and a screenshot from the scene view (Screenshot_4.png). As you can see, in screenshots 1 and 2, the mesh between nodes 1 and 2 doesn't get geenrated :/
     

    Attached Files:

  26. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    Can you please take a look at one of your generated meshes in the inspector during play mode, those with the MeshBender script, and tell me if the mesh filter component is a "combined mesh (root node)" like this one?

    upload_2019-5-16_1-23-45.png

    If so, still in play mode, can you try to delete the "generated" game object, then disable/enable your spline game object. I suspect everything would work fine at this point. It's not a suggested solution of course, but knowing that can help me diagnosing the issue.
     
    MycroSparks likes this.
  27. MycroSparks

    MycroSparks

    Joined:
    Mar 15, 2013
    Posts:
    6
    Apparently my generated segments don't have the same component as the starting ones ( the combined mesh (root node)), but they've got a "Generated by MeshBender" component (I've added a screenshot of the entire generated segments inspector, Screenshot_1.png).

    Also, after deleting one of the generated game objects, and disabling/enabling the spline game object, the result is in Screenshot_2.png, i get where the mesh is supposed to be generated made out with green lines, but the actual mesh isn't updated :/

    EDIT:
    I've toggled the CurveSpace bool off and on again and it got rid of the old spline mesh, updated it, but it's missing mesh between the generated node that wasn't deleted and it's next neighbor (Screenshot_3.png).
     

    Attached Files:

    Last edited: May 16, 2019
  28. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    I've tried to achieve something like you do and I can't see any issue on my side. Please send me your files via private message so we can continue this conversation.
     
  29. MycroSparks

    MycroSparks

    Joined:
    Mar 15, 2013
    Posts:
    6
    I've opened up a conversation and sent you a link to my assets, thanks :)
     
  30. Muskie

    Muskie

    Joined:
    Jan 21, 2017
    Posts:
    27
    How did you do that? I'm starting to use SplineMesh myself, but I can't do anything if I can't make new nodes! :)
     
  31. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    I've added a button to add a node after the selected one, via the inspector. It's on the github repository and I'll push it to the store soon.

    In the meanwhile, go to SplineEditor.cs and follow these instructions:

    Code (CSharp):
    1. public override void OnInspectorGUI() {
    2.     serializedObject.Update();
    3.     // hint
    4.     EditorGUILayout.HelpBox("Hold Alt and drag a node to create a new one.", MessageType.Info);
    5.  
    6.     // ######## add this block
    7.     // add button
    8.     if (selection == null) {
    9.         GUI.enabled = false;
    10.     }
    11.     if (GUILayout.Button("Add node after selected")) {
    12.         Undo.RegisterCompleteObjectUndo(spline, "add spline node");
    13.         SplineNode newNode = new SplineNode(selection.Direction, selection.Direction + selection.Direction - selection.Position);
    14.         var index = spline.nodes.IndexOf(selection);
    15.         if(index == spline.nodes.Count - 1) {
    16.             spline.AddNode(newNode);
    17.         } else {
    18.             spline.InsertNode(index + 1, newNode);
    19.         }
    20.         selection = newNode;
    21.     }
    22.     GUI.enabled = true;
    23.     // ########
    24.  
    25.     // delete button
    26.     if (selection == null || spline.nodes.Count <= 2) {
    27.         GUI.enabled = false;
    28.     }
    29.     if (GUILayout.Button("Delete selected node")) {
    30.         Undo.RegisterCompleteObjectUndo(spline, "delete spline node");
    31.         spline.RemoveNode(selection);
    32.         selection = null;
    33.     }
    34.     GUI.enabled = true;
    35.  
    36.     [...]
    37. }
     
    Sparking02 likes this.
  32. Daxteralex

    Daxteralex

    Joined:
    Jun 18, 2014
    Posts:
    1
    Hi Methusalah999,

    I'm trying to make work the ExampleGrowingRoot on Android but impossible to make these roots growing at runtime.

    Has anyone succeed to make it work ? Or Unity doesn't handle Mesh binding on mobile ? Or simply I'm a totally noob perhaps haha ^^

    Best regards everyone,

    Alex
     
  33. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    I've never tried SplineMesh on other platform than PC, and I don't know of any SplineMesh's user that is working on android so I don't know where to start.

    Have you noticed any error or warning in the console? What is the exact behavior of the growing root in play mode?

    If you try and run the showcase on android, can you see any of the animated examples working? If not, the issue may come from the fact that these scripts are made to update in edit mode, which may mess with something on android platform.
     
  34. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    404
    I'm trying to add nodes but keep the curve smooth between points (incidentally, these are navmeshagent path corners). I can't seem to figure out accurate path directions as I add nodes, resulting in zigzagging when drawn between points.

    Is there an easy way to figure out how to add nodes at runtime whilst keeping normal curvature between the points?
     
  35. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    A node is a position and a direction. You have to find a direction that will end up in a smooth curve, because SplineMesh doesn't decide it for you.

    As an easy and acceptable solution, you can place the direction control point at half the distance between the current node and the next one. Something like that:
    Code (CSharp):
    1. currentNode.Direction = (nextNode.transform.position - currentNode.Position) * 0.5f + currentNode.Position;
    There is an infinity of other ways to do that.
     
  36. Shivam489

    Shivam489

    Joined:
    Aug 19, 2017
    Posts:
    6
    Hey, how to add spline node in runtime at a particular point. I want to have my train follow the track which the user makes in runtime. I am keeping the positions and want to addnode at that positions. I used to pass vector3 position in spline.nodes.position and getting this in the image.
    how to get the right direction between all the points. i had tried targert vector3 - initial vector3 to get direction but didnt worked. this is the result of it as in the image.
     

    Attached Files:

    Last edited: Jun 6, 2019
  37. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    Yeah, a spline node is a position ADN a direction. You have to specify the direction on your own. SplineMesh won't do it for you because there is an infinity of possible directions from a point to another, depending on the curvature you want.

    Can you please read the messages just before yours? we are discussing the exact same subject and i've given an hint about how you can do that.

    Please come back if you need further help.
     
  38. Shivam489

    Shivam489

    Joined:
    Aug 19, 2017
    Posts:
    6
    Thanks for the reply.
    I have already read that. But its obvious to have a curve path directly from previous to current node not zigzag curve. I tried a lot with the directions changing them manually at runtime but was not able to do it right. I also saw that if there are only two points even that the curve it not straight if i set the direction directly to the other point. Its very difficult to do that. any idea to get rid of zigzag pattern.
     
  39. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    I've made a rope this way before. Let me give some more info and see if it helps.

    - the direction vector is not relative to the position. It is in fact a control point expressed in the same local space than the position,
    - in SplineMesh, there is only one control point per curve. The missing control point as seen on a classic cubic bezier curve is the mirror of the control point of the next curve.
    - the control point must be somewhere between the node and the next node. Half the distance is a good place to start.

    On your picture, I can see that your direction is always pointing the same point, which is near the origin. As stated above, I think you might make the mistake of setting the direction relatively to the position. Adding the position to the direction should do the trick and avoid zigzag effect, for a first acceptable implementation.
     
  40. Shivam489

    Shivam489

    Joined:
    Aug 19, 2017
    Posts:
    6
    Thanks methusalah999,
    But I tried adding the position direction. Could you plz. elaborate some more details so that I able to make it. Or if you have that rope script than can you please share it. It would be of great help.
     
  41. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    The following code is in the rope script's update method.

    Points is a list of gameobject representing the positions of the rope's nodes. I use GameObjects only because I need an up vector, since my ropes are often verticals. A list of Vector3 should be enough in most situations.

    Beware : this is a quick and dirty solution ! as the direction is computed from the corresponding node and the next one, without taking into account the previous one. A better code should find some average rotation between the two, and let you choose more or less curvature by multiplying the average distance by some ratio you set.

    Hope it helps !

    Code (CSharp):
    1.         int i = 0;
    2.         foreach (var point in points) {
    3.             var splineNode = spline.nodes[i];
    4.             splineNode.Position = transform.InverseTransformPoint(point.transform.position);
    5.             splineNode.Up = point.transform.up;
    6.  
    7.             if (point != points.Last()) {
    8.                 splineNode.Direction = (transform.InverseTransformPoint(points[i + 1].transform.position) - splineNode.Position) * 0.5f + splineNode.Position;
    9.             } else {
    10.                 var prevN = spline.nodes[i - 1];
    11.                 splineNode.Direction = splineNode.Position + prevN.Direction - prevN.Position;
    12.             }
    13.             i++;
    14.         }
    15.  
     
  42. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    @Shivam489 @Zante

    I've worked on that code because it wouldn't let me sleep.

    Here is a much better version, that takes into account both the next and the previous nodes.

    My ropes have never been so smooth. This piece of code will be present as an example in the next SplineMesh version.

    Have fun !

    Code (CSharp):
    1.     private void UpdateNodes() {
    2.         int i = 0;
    3.         foreach (GameObject wayPoint in wayPoints) {
    4.             var splineNode = spline.nodes[i];
    5.             var pos = wayPoint.transform.position;
    6.  
    7.             // First, we set the node position and up vector.
    8.             splineNode.Position = transform.InverseTransformPoint(pos);
    9.             splineNode.Up = wayPoint.transform.up;
    10.  
    11.             // For the direction, we need to compute a smooth vector.
    12.             // Orientation is obtained by substracting the vectors to the previous and next way points,
    13.             // which give an acceptable tangent in most situations.
    14.             // Then we apply a part of the average magnitude of these two vectors, according to the smoothness we want.
    15.             var dir = Vector3.zero;
    16.             float averageMagnitude = 0;
    17.             if (wayPoint != wayPoints.First()) {
    18.                 var previousPos = wayPoints[i - 1].transform.position;
    19.                 var toPrevious = pos - previousPos;
    20.                 averageMagnitude += toPrevious.magnitude;
    21.                 dir += toPrevious.normalized;
    22.             }
    23.             if (wayPoint != wayPoints.Last()) {
    24.                 var nextPos = wayPoints[i + 1].transform.position;
    25.                 var toNext = pos - nextPos;
    26.                 averageMagnitude += toNext.magnitude;
    27.                 dir -= toNext.normalized;
    28.             }
    29.             averageMagnitude *= 0.5f;
    30.             // This constant should vary between 0 and 0.5, and allows to add more or less smoothness.
    31.             dir = dir.normalized * averageMagnitude * 0.3f;
    32.  
    33.             // In SplineMesh, the node direction is not relative to the node position.
    34.             var controlPoint = dir + pos;
    35.  
    36.             // We only set one direction at each spline node because SplineMesh only support mirrored direction between curves.
    37.             splineNode.Direction = transform.InverseTransformPoint(controlPoint);
    38.             i++;
    39.         }
    40.     }
     
    Last edited: Jun 7, 2019
  43. Shivam489

    Shivam489

    Joined:
    Aug 19, 2017
    Posts:
    6
    Tha
    nk you very much..... You are god for me... thnkx for your fast replies..... :):):):)...
     
  44. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    If you like SplineMesh and my work, please write a review on the asset store. It's gold to me

    Have fun bending things!
     
  45. OneNot

    OneNot

    Joined:
    Jan 26, 2018
    Posts:
    3
    First of all, thank you for offering such a great tool for free!

    I have a few questions if you or anyone here could help me out.
    I'm making a system for building roads (in-game) using SplineMesh.
    Please be gentle it's my first time (working with splines). :)
    This is what I've managed so far:


    I'm essentially moving the end node to cursor raycast hit location and on click inserting a new node.
    I also rotate the end node with Q/E on the keyboard.

    The way the node direction property works is fairly good to manually use in the editor, but moving them in code is confusing to me.
    I've managed to do it more or less, but yeah.

    I'm using the SplineMeshTiling script in Repeat mode.
    I tried using the Stretch To Interval mode, but here's what that looks like:


    Also, when creating new nodes, the curve meshes leave gaps (as you can see in the first video)
    Here's my code:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class RoadBuildTest : MonoBehaviour
    6. {
    7.     public float rotationSpeed = 10f;
    8.     public float RotateBoostMultiplier = 2f;
    9.  
    10.     private SplineMesh.Spline spline;
    11.     private Vector3 localHit;
    12.     private bool boostRotate, started;
    13.     private float ForwardDistanceFromPreviousNode;
    14.     private SplineMesh.SplineNode currentNode, prevNode, startNode;
    15.  
    16.     // Start is called before the first frame update
    17.     void Start()
    18.     {
    19.         spline = GetComponent<SplineMesh.Spline>();
    20.         started = boostRotate = false;
    21.         currentNode = spline.nodes[1];
    22.         startNode = prevNode = spline.nodes[0];
    23.         startNode.DirNodeDistanceToPosNode = currentNode.DirNodeDistanceToPosNode = new Vector3(0f, 0f, 1f);
    24.     }
    25.  
    26.     // Update is called once per frame
    27.     void Update()
    28.     {
    29.         if (Input.GetButtonDown("RotateBoost"))
    30.             boostRotate = true;
    31.         else if (Input.GetButtonUp("RotateBoost"))
    32.             boostRotate = false;
    33.  
    34.         if (Input.GetButton("RotateRight") && started)
    35.         {
    36.             currentNode.DirNodeDistanceToPosNode = (Quaternion.AngleAxis(Time.deltaTime * rotationSpeed *
    37.                 (boostRotate ? RotateBoostMultiplier : 1), Vector3.up) * currentNode.DirNodeDistanceToPosNode).normalized;
    38.         }
    39.         if(Input.GetButton("RotateLeft") && started)
    40.         {
    41.             currentNode.DirNodeDistanceToPosNode = (Quaternion.AngleAxis(Time.deltaTime * -rotationSpeed *
    42.                 (boostRotate ? RotateBoostMultiplier : 1), Vector3.up) * currentNode.DirNodeDistanceToPosNode).normalized;
    43.         }
    44.  
    45.  
    46.  
    47.         Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    48.         RaycastHit hit;
    49.  
    50.         if (Physics.Raycast(ray, out hit, 10000f))
    51.         {
    52.             Debug.DrawRay(hit.point, Vector3.up * 10, Color.red);
    53.             if (!started)
    54.                 started = true;
    55.  
    56.             //translating world point to local space
    57.             localHit = hit.point - spline.transform.position;
    58.  
    59.             //moving second node to mouse location
    60.             currentNode.Position = localHit;
    61.  
    62.  
    63.             // TODO: Still need to figure out what's wrong here (not in use right now)
    64.             //===============================================================================================================
    65.             //calculating distance to new node exclusively in previous piece's forward direction using pythagoras theorem
    66.             //    ./_|   (. = previous piece pos, / = direction vector to new node, _ = the distance we are calculating)
    67.             float c = Vector3.Distance(localHit, prevNode.Position); //distance to new node from previous node (pythagora C)
    68.             float angle = Vector3.Angle(prevNode.Position, localHit); //directional angle from previous node to new node (pythagora A-C angle)
    69.             ForwardDistanceFromPreviousNode = c * Mathf.Cos(angle); //directional length (pythagora A)
    70.             //================================================================================================================
    71.  
    72.  
    73.             //current node
    74.             currentNode.Direction = localHit + currentNode.DirNodeDistanceToPosNode * 3; // (* 3) is temp, want to use (* ForwardDistanceFromPreviousNode / 2)
    75.  
    76.             //previous node
    77.             prevNode.Direction = prevNode.Position + prevNode.DirNodeDistanceToPosNode * 3;
    78.         }
    79.  
    80.  
    81.         //Add new node
    82.         if (Input.GetButtonDown("Fire1"))
    83.         {
    84.             // TODO: Need to figure out a way to have each curve's mesh connect with eachother without gaps
    85.             //Using stretch instead of repeat for the mesh bending would probably help with this as well as making the road generally better, but it doesn't seem to work...
    86.  
    87.             spline.AddNode(new SplineMesh.SplineNode(currentNode.Position, currentNode.Direction)); //adds the node right where the previous one is
    88.             prevNode = currentNode; //setting the current node to be "prevNode"
    89.             currentNode = spline.nodes[spline.nodes.Count - 1]; //updating new node to be "currentNode"
    90.             currentNode.Scale = startNode.Scale; //settings new node scale
    91.             currentNode.DirNodeDistanceToPosNode = prevNode.DirNodeDistanceToPosNode; //setting new nodes direction's relative position the the same as previous one's
    92.         }
    93.     }
    94.  
    95.  
    96. }
    97.  
    Any advice is welcome, but I'm specifically looking for answers for:
    - Why does Stretch mode act like it does and would (if I can get it to work) it be better for my use case?
    - Why are there gaps between the curve meshes and how can I fix it?

    Thanks.
     
  46. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    Hi there !

    Let me give some random info that might be usefull here:

    About Direction vector
    Node's direction vector is in fact a control point, located in the same space than node position. It is not relative to the position. This vector stores two informations:
    - its direction is the tangent of the spline at the the node position
    - its magnitude is the strength of the curvature. A long distance between node and direction means the curve will bend more far.

    The wiki can help understand the bézier curves mechnics. In SplineMesh you will have this:
    P0: node.Position
    P1: node.Direction
    P2: mirror of nextNode.Direction
    P3: nextNode.Position


    About Strecth Mode
    Stretch mode will stretch your mesh to fit in the curve length, while Repeat mode will place as much of your mesh as it fits in the curve length.

    It seems that your mesh doesn't have any vertex between the start en end of the road segment. SplineMesh need vertices to bend things. As your road segment is very short, it will work with Repeat mode because repeating the mesh will create sufficent amount of intermediate vertices to bend. But in stretch mode, you have no vertices to bend between curve start and end, so you obtain a strait line.

    Please look in SplineMesh's showcase assets, the cylinder I use has a lot of vertices for SplineMesh to apply deformation.
    upload_2019-6-14_12-44-53.png

    You need that kind of mesh for your road segment to be bent in stretch mode.

    About gaps
    It's most likely because of the mesh to bend. SplineMesh will find the highest and lowest vertex to determine the scale of your mesh.

    If gaps happen, it may be because there is a vertex outside of your mesh? or the start and end face are not perfectly orthogonal with the bending axis? or you have specified a non-orthogonal rotation in SplineMeshTiling? something like that.

    Please test it with the SplineMesh base cylinder and a 90 degrees rotation in the SplineMeshTiling to simplfy diagnotics.

    If you need more assistance on this last point, please provide a view with the SplineMeshTiling inspector and a closer view of the gap, with Shaded Wireframe activated in Unity.

    Hope it helps
     
  47. OneNot

    OneNot

    Joined:
    Jan 26, 2018
    Posts:
    3
    Thanks a ton!

    Yeah that makes perfect sense! Should have thought of that.
    Everything is working fine after swapping out the mesh for the cylinder. We'll rework the road a bit and try it again with that soon.

    As for the direction vector business, I'll need to study that a bit I guess.
    This is a work project and weekend is fast approaching in a few hours, but I'll probably post an update here early next week with new results.
    Thanks again. :)
     
  48. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    391
    I've created a script to do the auto smoothing of the spline that you all requested lately. It will be available in the next version, among other little things !

    See it on twitter

    SplineSmootherLight.gif
     
    Lars-Steenhoff, Caruos and tgd-uni like this.
  49. Shivam489

    Shivam489

    Joined:
    Aug 19, 2017
    Posts:
    6
    Yes sure mannnnn....!!! You truly deserve it. Will donate to if I earned enough money from my app....!!
     
  50. NewSystemGames

    NewSystemGames

    Joined:
    May 23, 2017
    Posts:
    299
    Is it just me or every time I Create a new node there is a out of bounds error ?

    Also Another Error:
    1- Create Empty GameObject
    2- Add Spline & Spline Extrusion components to it
    3- Press "Add Node" Button
    4- Undo (CNTRL + Z)
    5- Infinite null reference error.

    I'll revert back to the older version for now
     
    Last edited: Jun 24, 2019
unityunity