Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice

Official Unity Splines

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

  1. pojoih

    pojoih

    Joined:
    Mar 30, 2013
    Posts:
    226
    I have a suggestion for the API: I really miss a way to detect when a SplineAnimate Loops. My current solution does not really work good so an Event like
    SplineAnimate.looppointReached
    would be nice.

    Code (CSharp):
    1.  
    2. private void OnSplineUpdate(Vector3 arg1, Quaternion arg2) {
    3.     var time = Spline.normalizedTime;
    4.     if (time > 0.99f || time < 0.01f)
    5.         particleSystem.Stop();
    6.     else
    7.         particleSystem.Play();
    8. }
    This code gives me not the best results, eg. for following ParticleSystems getting worse with emission- and frame rate (same goes for Trails, Lines, etc.)
    :
    Animation.gif
     
    ThomasLopez and Red_Dragon69 like this.
  2. sameng

    sameng

    Joined:
    Oct 1, 2014
    Posts:
    184
    You could make it more reliable this way:

    Code (CSharp):
    1.  
    2. float time_prev;
    3.  
    4. private void OnSplineUpdate(Vector3 arg1, Quaternion arg2) {
    5.     var time = Spline.normalizedTime;
    6.     if (time_prev > time){
    7.         Debug.Log("Loop detected!");
    8.     }
    9.     time_prev = time;
    10. }
    11.  
    Note that this would break if you make the spline animate in reverse.
    But you'd just have to switch the line from (time_prev > time) to (time_prev < time)
     
    pojoih likes this.
  3. MihailLuhov

    MihailLuhov

    Joined:
    Aug 10, 2020
    Posts:
    6
    Hello, it's now been a couple of days I've been using the Splines package and the one thing I haven't figured out is what's the best way to transition a SplineAnimate object from one Spline to another during Runtime. If I just switch the SplineAnimate's SplineContainer to the new one, there are a few frames where jitter is present due to the switch.

    Can you suggest a better approach to make it smoother? I've tried linking the knots of the previous Spline with the new one but it still isn't quite working.
     
    ThomasLopez and SirResnick like this.
  4. tday_magicfuel

    tday_magicfuel

    Joined:
    Apr 10, 2018
    Posts:
    21
    The SplineAnimate component is convenient in how it handles a bunch of common spline related animation tasks. But it would be useful to make those parameters belong to the *spline* and not the game object animating.

    For example--a spline defines the animation path for a character going up a ladder. We want the animated object to align to the ladder. The SplineAnimate component has to be on what is animating--you wouldn't want to add a different SplineAnimate component to the character for every spline use case.

    This can be somewhat worked around by using an invisible game object that animates to the spline and then reparenting the character you wish to animate. It would be even better though if this was supported by making the game object that animates parameterizable in SplineAnimate.

    Apologies if this exists and I've just missed it!
     
  5. Red_Dragon69

    Red_Dragon69

    Joined:
    Sep 7, 2015
    Posts:
    114
    Is there a way to gradually change the speed of the AnimateSpline component? Setting the MaxSpeed (or speed) results in complete recalculation of the way the object moves along the spline.
     
  6. ThomasLopez

    ThomasLopez

    Unity Technologies

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

    Sorry for the delay.
    This is not a bug if I remember correctly, this features should have been moved to the context menu of the scene view for 2023.2 and later.
    Just right click in the scene view when a pline element is selected and you should see these features (reverse, join, link/unlink) in a menu directly.

    Hope this helps!

     
  7. ThomasLopez

    ThomasLopez

    Unity Technologies

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

    The instances should be created automatically in the scene as soon as you add the prefab to the component and the should follow the spline modifications, no need to "Bake" them unless you want to have them and modify them individually.
    This is possible to modify them individually only after baking (otherwise the modifications would be overriden if the spline shape is changed later for instance). But you should only bake when you have your final placement and are ready to modify the instances.

     
  8. RDeluxe

    RDeluxe

    Joined:
    Sep 29, 2013
    Posts:
    117
    Hey there!

    Sorry to bother, but how can I upgrade my Spline Package? UPM shows only the 2.3.0 version, on Unity 2022.3.7f1.
     
  9. Red_Dragon69

    Red_Dragon69

    Joined:
    Sep 7, 2015
    Posts:
    114
    Try to manually change the version number in the package.json. Had the same troubles with 2022.3.7, upgrading Unity to a newer version helped too.
     
    ThomasLopez likes this.
  10. ThomasLopez

    ThomasLopez

    Unity Technologies

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

    This is by design, the spline gameObject is placed at the first knot position.
    But indeed, it should be done differently so that you don't have this transform change that is override :) Thanks, I'll log that!

     
  11. ThomasLopez

    ThomasLopez

    Unity Technologies

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

    Indeed that shortcut was not present yet in 2021!

     
  12. ThomasLopez

    ThomasLopez

    Unity Technologies

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

    Do you have more repro regarding this?
    That's the first time I hear about that one :O
    Thanks!


     
  13. ThomasLopez

    ThomasLopez

    Unity Technologies

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

    This is not possible in that component. You would have to create your own component for that I think. Or maybe the ease-in and out are enough for your case?

     
  14. ThomasLopez

    ThomasLopez

    Unity Technologies

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

    Indeed, this is not existing for now, but could be a good event indeed.
    Thanks for the feedback.

     
  15. ThomasLopez

    ThomasLopez

    Unity Technologies

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

    Thanks for that feedback :)
    First question will be: Do you need different splines for that ?
    But then, if you do and have them in the same SplineContainer, then my answer is : SplinePath will be your friend :)
    A SplinePath is a special kind of Spline, it has to be defined by code this is a list of SplineSlice (which is either a full spline or a part of a spline). Look at the SplinePath sample for more usecases and information!

    If your splaines are in different containers, then there is no existing solution for that in the package itself, you'll have to make your own but that's totally feasible :)


     
  16. asiertroiti

    asiertroiti

    Joined:
    Jan 28, 2021
    Posts:
    17
    If I had an object made by me (like a rail for example) could I add it as a mesh to the spline?
    And I have a small problem with the package, when importing, the materials themselves appear purple and I have to manually change the shader to standard, why is that?
     

    Attached Files:

  17. Red_Dragon69

    Red_Dragon69

    Joined:
    Sep 7, 2015
    Posts:
    114
    Hello @ThomasLopez,
    thank you for the answer. I created my own SplineFollower and just in case anyone is interested, this is my code. Maybe not the best way to do it, but works for me :)

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Splines;
    3.  
    4. public class SplineFollower : MonoBehaviour {
    5.  
    6.     [SerializeField] private float speed = 0;
    7.     [SerializeField] private SplineContainer container;
    8.  
    9.     private float currentOffset;
    10.     private float splineLength;
    11.  
    12.     private void Start() {
    13.         splineLength = container.Splines[0].GetLength();
    14.     }
    15.  
    16.     private void Update() {
    17.         currentOffset = (currentOffset + ((speed * Time.deltaTime) / splineLength)) % 1f;  
    18.  
    19.         transform.position = container.Splines[0].EvaluatePosition(currentOffset);;
    20.  
    21.         var direction = container.Splines[0].EvaluateTangent(currentOffset);
    22.         var up = container.Splines[0].EvaluateUpVector(currentOffset);
    23.         transform.rotation = Quaternion.LookRotation(direction, up);;
    24.     }
    25. }
     
  18. Touhma_Slater

    Touhma_Slater

    Joined:
    Nov 19, 2014
    Posts:
    24
    I'm currently working on a project with ECS.
    Once we do create our Splines we can then convert them to NativeSpline for usage in a Parralel Job.

    Unfortunately we can't directly same the NativeSpline in a component & then query it from the Job because of the native arrays in them. It's giving us this error :
    NativeSplineComponentData_RW_ComponentTypeHandle can not be accessed. Nested native containers are illegal in jobs.

    My question is double :
    Is there a plan to have a Utility function to be able to save the data of a spline on an entity ( imagine we want to same the sata in a save file & then reconstruct the splines from that data )

    And If not, I need to implement that so what would be the correct way of doing it ?
     
  19. designmatic

    designmatic

    Joined:
    Aug 21, 2017
    Posts:
    9
    Hi @ThomasLopez,

    Thank you and the entire team behind it for the splines package.

    Could you please expose world position coordinates of each knot in the spline container. Either via a toggle between object and world space like VFX Graph does it or have it in the table view as "World Position".

    We heavily rely on correct world positions of start and end points of a spline in our game. Having only object related positions makes working on it hard as we also put splines under other game objects in the scene. These objects are offset in the scene and are not positioned at (0,0,0) coordinates.

    I hope I made it clear why exposing world position coordinates would improve the usability of the splines package for its users and hope you can update the package with this small feature request.

    Thank you for your time and consideration.
     
  20. TheCircadian

    TheCircadian

    Joined:
    Jul 30, 2016
    Posts:
    16
    I have tried to do this so many different ways. I'll just include the code to help. Basically I create a new Spline for every day of the year. I create a new Spline, and the Extruder for it as well. It generates 366 splines (this is a leap year), and They are all created, but there's a button in the Inspector saying "Create Mesh Asset". I also get this error:

    SplineExtrude.createMeshInstance is disabled, but there is no valid mesh assigned. Please create or assign a writable mesh asset.
    UnityEngine.Splines.SplineExtrude:Start () (at ./Library/PackageCache/com.unity.splines@2.5.2/Runtime/SplineExtrude.cs:190)​

    Is there a straightforward way to create a spline entirely from code? If it's ISpline or NativeSpline I'm fine with that. Just want to get something working. :)

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Splines;
    5. using Unity.PolySpatial;
    6. using System;
    7.  
    8. public class Z1_DayLineCreator : MonoBehaviour
    9. {
    10.     public GameObject DayLine;
    11.     private Sundial sundial;
    12.     int daysThisYear = 365;
    13.     // Start is called before the first frame update
    14.     void Start()
    15.     {
    16.         sundial = GameObject.Find("Sundial").GetComponent<Sundial>();
    17.         int month = 0;
    18.         int dayOfMonth = 0;
    19.         if (sundial.leapYear)
    20.         {
    21.             daysThisYear = 366;
    22.             sundial.monthLength[1] = 29;
    23.         }
    24.         for (int i = 0; i <= daysThisYear; i++)
    25.         {
    26.             Vector3 sunPoint = new Vector3(0, -1.8f + 3.6f * (float)i / daysThisYear,0);
    27.  
    28.             float dayAngle = (float)i * 360f / daysThisYear;
    29.             Vector3 dayPoint = new Vector3(
    30.                 1.8f * Mathf.Sin(dayAngle * Mathf.PI / 180),
    31.                 -1.8f + 3.6f * (float)i / (float)daysThisYear,
    32.                 -1.8f * Mathf.Cos(dayAngle * Mathf.PI / 180)
    33.                 );
    34.  
    35.             GameObject Z1_DayLine = new GameObject(dayAngle.ToString());
    36.             Z1_DayLine.transform.parent = transform;
    37.             Z1_DayLine.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
    38.             SplineContainer splineContainer = Z1_DayLine.AddComponent<SplineContainer>();
    39.             splineContainer.Spline.Add(new BezierKnot(sunPoint));
    40.             splineContainer.Spline.Add(new BezierKnot(dayPoint));
    41.  
    42.  
    43.             // Add things so each line has its own mesh, and doesn't reposition the last one
    44.             //MeshRenderer dayMesh = Z1_DayLine.AddComponent<MeshRenderer>();
    45.             //dayMesh.material = Resources.Load<Material>("Materials/lineMaterial");
    46.             SplineExtrude line = Z1_DayLine.AddComponent<SplineExtrude>();
    47.             line.Container = splineContainer;
    48.             line.SegmentsPerUnit = 2;
    49.             line.Sides = 3;
    50.             line.Rebuild();
    51.             line.RebuildFrequency = 1;
    52.  
    53.  
    54.             float radius = 0.002f;
    55.             if (dayOfMonth % sundial.monthLength[month] == 0)
    56.             {
    57.                 dayOfMonth = 0;
    58.                 radius = 0.005f;
    59.                 month++;
    60.             }
    61.             line.Radius = radius;
    62.             dayOfMonth++;
    63.             Mesh extrudedMesh = new Mesh();
    64.             SplineMesh.Extrude(splineContainer.Spline, extrudedMesh, 0.001f, 2, 2);
    65.             MeshFilter meshFilter = Z1_DayLine.AddComponent<MeshFilter>();
    66.             //meshFilter.mesh = extrudedMesh;
    67.             //lineMesh = extrudedMesh;
    68.             //splineContainer.Spline.Spl
    69.             //SplineExtrude splex = new SplineExtrude(splineContainer);
    70.             //SplineExtrude splex = Z1_DayLine.AddComponent<SplineExtrude>();
    71.             //splex.Spline = splineContainer;
    72.             //Z1_DayLine.AddComponent<MeshFilter>().mesh = extrudedMesh;
    73.             print(i + " : " + month + " : " + dayOfMonth);
    74.             Z1_DayLine.AddComponent<VisionOSHoverEffect>();
    75.             dayOfMonth++;
    76.  
    77.  
    78.  
    79.             Z1_DayLine.AddComponent<VisionOSHoverEffect>();
    80.         }
    81.     }
    82. }
     
  21. tomkail_betterup

    tomkail_betterup

    Joined:
    Nov 17, 2021
    Posts:
    106
    Hi! Exploring the package and so far Splines seems excellent, thanks for putting it together!

    Reporting a bug on latest - in the Instantiate Component demo, using undo after adding points to a spline container causes a bunch of IndexOutOfRangeException. The error comes from SplineInstantiate/SplineContainer, so I don't think it's specific to the demo, appears to me that the scripts simply don't handle Undo very well.

    (Would have reported via the bug reporter but that thing is so time consuming to use. The repro is simple. Sorry!)
     
    WorksInDev likes this.
  22. cadmonkey33

    cadmonkey33

    Joined:
    Jun 14, 2018
    Posts:
    9
    Last edited: Feb 26, 2024
  23. cadmonkey33

    cadmonkey33

    Joined:
    Jun 14, 2018
    Posts:
    9
    Hello @ThomasLopez ,
    Is it possible to override or disable the spline tool context for my object type?

    I've created my own context and tools that have certain restrictions, eg. no linking, some knots are locked etc.
    The problem is that the default SplineToolContext is always available for ANY type that implements ISplineContainer. Apart from the fact that there are now two contexts available for my object type (annoying), there is also no way to stop users manipulating the spline in a way I don't want them to!

    I considered not implementing ISplineContainer, but it is so intrinsically linked to everything else (via SplineInfo) that it would basically require reimplementing a good chunk of the splines api.

    This could be avoided if I can make my tool context override SplineToolContext for my object type.

    Thanks.
     
  24. FireToast

    FireToast

    Joined:
    Apr 27, 2020
    Posts:
    1
    I think an option to select one or more custom easing points would be a very useful addition to the SplineAnimate component. For instance, if I wanted the animated object to slow down as it reaches the halfway point and speed up as it passes halfway. Currently I've had to make my own spline traversal script and add it there, which is a shame because the rest of the functionality of SplineAnimate is perfect for what I need.
     
  25. ieatunicorns22

    ieatunicorns22

    Joined:
    Jan 29, 2021
    Posts:
    1
    Hiya everyone! This has been a very thoroughly interesting thread to read through, and I'm very glad to see @ThomasLopez being so active and helpful! I do have a question of my own, and forgive me if it's something that may not be that clear, so I can explain more in detail if needed.
    Essentially, I'm having trouble with evaluating the direction of the spline at t = 0, when the first knot is set to Linear tangent mode. It simply returns as Vector3.zero, instead of the actual direction that the spline is moving towards. I should note as well, that it may not necessarily be at t = 0, but this is simply the place that it's causing the most issues for me. I checked through the Scripting API of the Splines package, and read in the page for TangentMode that for linear knots, "Tangents are not used. A linear spline is a series of knots connected by a path with no curvature." Now, that wouldn't be much of an issue if the 'tangent' didn't seem interchangeable for 'direction' of a spline. Is there something that I'm missing? Is there some other method I should be using to get the direction of a spline when it is comprised entirely of linear knots? Is this unintended behavior?
    Any help is greatly appreciated, and I look forward to this package being further improved over time.
     
  26. chemicalcrux

    chemicalcrux

    Joined:
    Mar 16, 2017
    Posts:
    720
    Is there a reason that SplineContainer has the [ExecuteInEditMode] attribute instead of the [ExecuteAlways] attribute? Unity warns me about entering play mode with a prefab open because of this.

    It doesn't look like it does anything evil that'd cause problems when editing a prefab, but I don't know much about the intricacies!
     
  27. lloydhuang

    lloydhuang

    Joined:
    Feb 2, 2019
    Posts:
    12
    Hello, I have been looking for a spline system, which can make a snake or dragon move along this spline, and, most importantly, its bones can also follow the movement in editor mode. this is very useful for artist, but I can't find anything like this at the store.(theres one in the store, but only working in runtime mode, hence it is very very very hard to control the bone animation and bone pose)
     
  28. kap10cartoon

    kap10cartoon

    Joined:
    Apr 23, 2019
    Posts:
    1
    spline animate has very inconsistent behavior. Observe the linked clip:


    It seems like the animate function breaks down when you add more than one to a given spline.
     
  29. chase_unity38

    chase_unity38

    Joined:
    Jan 5, 2022
    Posts:
    8
    this error spams during Start for all SplineAnimate components, even if PlayOnAwake is unchecked. I wish it wouldn't, it's a lot of extra noise if you're trying to set up splines dynamically.

    in my case, I'm assigning SplineContainers to SplineAnimate components dynamically at runtime.


    SplineAnimate does not have a valid SplineContainer set.
    UnityEngine.Splines.SplineAnimate:Start () (at ./Library/PackageCache/com.unity.splines@2.5.2/Runtime/SplineAnimate.cs:360)
     
  30. anilcool

    anilcool

    Joined:
    Mar 8, 2020
    Posts:
    7
    I want to make a cube that jumps and rolls along the Spline path when the Space key is pressed.
    Not sure if I should rigidbody force or translation.
    Right now I can make either Spline movement work correctly or jumping, not both.
     
    Last edited: Apr 2, 2024
  31. Red_Dragon69

    Red_Dragon69

    Joined:
    Sep 7, 2015
    Posts:
    114
    I implemented smth similar a while ago using a spline follower with a joint and a rigidbody on the other side. The idea is that the rigidbody follows the spline follower with the joint (spring joint as far as i remember) and jumps by adding a force when pressing space bar. Couldn't find the code, sry.