Search Unity

Official Unity Splines

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

  1. abeltoy

    abeltoy

    Joined:
    Feb 27, 2023
    Posts:
    2
    I am facing two challenges that would seem to be a common use case but are not covered by the library yet. I would really appreciate it if you could look into whether it would be feasible to officially support them.

    I am using splines to build a moving platform. A moving platform references a spline container and can be given a SplinePath, which can be composed of multiple SplineSplices that reference Splines in the container. This path can be changed at runtime. A moving platform also has two SplineData lists: speed and delay. Speed determines the speed of the platform at any point in the spline. Delay is discrete and the data simply expresses how many seconds the platform will wait at the specified index in the spline.

    My first challenge is I would appreciate more support for discrete spline data in the API. I could have made use of the internal GetIndex function to quickly find the next delay in the spline. I ended up implementing a system that keeps track of the previous delay and thus I can simply check if the next delay occurs at some point between the start and end position of movement. I then take the distance to that delay into account in order to accurately take into account the extra time we would need to wait (this part is specific to delay so I wouldn't expect special handling from the library and I understand falls into user space). What I would really appreciate here is a way to efficiently query any (or the first) spline datas that are between two positions in the spline.

    My second challenge is that the spline data is a list that contains a SplineData for each Spline in the container. First, I had to reference some code from LoftRoadBehaviour in the samples to keep the list in sync with the splines in the container. I would appreciate some support for having that be done automatically (by the way, LoftRoadBehaviour has a bug in that it doesn't reorder the spline datas when the splines are reordered).

    The actual challenge, however, is actually converting each spline data to be able to be used in the actual path. I had to implement a method that calculates a new SplineData based on each slice in the path, comparing the length of the actual spline compared to the relative length of the slice with regards to the path and using normalized indices to properly map the SplineData.

    Additionally, and only for speed data (since it's continuous), I also had to add additional data at the start and the end of each slice to interpolate the desired speed according to the actual spline data (e.g. given a spline with 3 knots that sets speed 5 at 0 and speed 10 at 2, and a path from knot 1 to 2, should result in a splinedata of speed 7.5 at 0 and speed 10 at 1).

    I would really appreciate some official support to convert a list of SplineData (as well as a single SplineData referencing a single Spline) to map it to a new SplinePath (the single SplineData implementation would only support 1 Spline in the path). This implementation would optionally allow the user to interpolate the first and last data in the path from the original splines.

    I don't think my use case is that esoteric. Discrete events along a spline seem like a very common feature users may want to see when moving objects along the spline. And being able to map SplineData that's authored in the editor relative to a SplineContainer, to a given path, would also be essential for supporting multiple paths from a single spline container with associated data.
     
  2. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Oops indeed sorry,
    I wrote that without a correct double-check !
    So you'll have to use the localToWorld Matrix of the transform, that will transpose your current local spline and knots in the world domain:
    Code (CSharp):
    1. var nativeSpline = new NativeSpline(splineContainer.Spline, splineConstainer.transform.localToWorldMatrix);
    (I just updated my previous so that other people get the right code directly :p)
     
    M4XXX likes this.
  3. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hey @abeltoy !
    Thanks for reaching out!

    So this can be done by entering the tool add the point to the spline using the tool, and then directly exiting the tool using the ESC key! The newly created spline will be removed but not the point on the existing Spline! (see the gif I joined)

    We should actually document that indeed, this is done on purpose as this might not be the primary use of the tool but that's kinda hidden indeed!
     

    Attached Files:

    JonathanMeaney likes this.
  4. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hey again @abeltoy!
    So here are some answers regarding your second post.

    SplineData are stored in a Enumerator and the [] operator is implemented, so you can easily access to any element of the SplineData using data[2] for instance. You can use the data type
    PathIndexUnit.Knot so that the index of each DataPoint is using Knot indexes on the Spline.

    Then for instance let's say you want to check the next data point in your splineData you'll just have to do:
    Code (CSharp):
    1.  
    2. var nextIndex = mySplineData[nextDataIndex].Index;
    3. // In the case where your index is using for instance PathIndexUnit.Distance for the indexes, you can convert that using this utility :
    4. var nextKnotIndex = spline.ConvertIndexUnit(nextIndex, PathIndexUnit.Distance, PathIndexUnit.Knot);
    5.  

    Regarding this second problem you have, we improved a lot the consistency of data between Splines and SplineData in 2.2.0 by adding SplineData structures directly inside the SplineContainer. However, this new structure is not working with SplineData indeed.
    So, regarding your usecase, which IndexUnit are you using for your SplineData ?
    Keeping the data consistent and convert it between different units does really depend on the usecase. It's not that your usecase is esoteric, it's more that all usecases are :D, each with different requirements !
    Did you get a look to the ConvertPathUnit method in SplineData ? That allows you to change the unit between distance/normalized/knot units and keeps the data at the same position.

    Regarding the addition on DataPoints at the beginning and the end of the Spline, that's also something that greatly depends on the usecase. For instance, if you use a close spline, then you might not want to have a start/end data, but you would prefer to have that consistent when reaching the end of the spline and restarting.

    Finally, regarding the comment you did : "by the way, LoftRoadBehaviour has a bug in that it doesn't reorder the spline datas when the splines are reordered". This is actually not a bug. Reordering knots on a spline are really not a common usecase, so in that case we decided that the reason behind the reordering is too difficult to anticipate regarding the different usecases, so when doing the special reordering on a spline, we leave the user in charge of modifying the splineData to be consistent with the modifications he wants.

    Hope this helps :D
     
    GDevTeam likes this.
  5. neuroGear

    neuroGear

    Joined:
    Nov 25, 2012
    Posts:
    8
    Hey does anyone have this issue with splines where this message gets spammed after play mode for like 10 seconds and while that happens scene view basically freezes?


    Some Mesh cannot contribute to global illumination, because their HideFlags are set to DontSaveInEditor, HideAndDontSave or DontSaveInBuild.


    Currently using 2022.2.12 with URP 14.0.6. As for splines tried updating to latest 2.2.0 and still same issue.
     

    Attached Files:

  6. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hey @neuroGear ,
    Indeed, the instances created by the SplineInstantiate are created with the HideAndDontSave flag so I guess that's the reason of the spam... Could you fill a bug report on this ? That's definitively something we need to fix :D
    Thanks!
     
  7. NolandoFlorida

    NolandoFlorida

    Joined:
    Nov 17, 2018
    Posts:
    6
    maybe it's just me, but the documentation on splines is not very accessible for me? I want to know what functions and variables are available, not how to do specific tasks like animating.
     
    Unifikation likes this.
  8. Unifikation

    Unifikation

    Joined:
    Jan 4, 2023
    Posts:
    1,086
    You know it, we know it. But you need a user to submit a bug report before you'll actually fix it?

    Something is wrong with the system.
     
    eliasmi likes this.
  9. Unifikation

    Unifikation

    Joined:
    Jan 4, 2023
    Posts:
    1,086
    when the company already knows there's a problem, and there's a forum thread about it... I dunno... I'd expect a little rigour, a little care, a little self healing. etc.
     
  10. Unifikation

    Unifikation

    Joined:
    Jan 4, 2023
    Posts:
    1,086
    No need, You started it as a subthread, here, already.
     
  11. Buffles-TE

    Buffles-TE

    Joined:
    Mar 19, 2013
    Posts:
    10
    Got it working in 2021.3 and I wish Extrude allowed you to use a mesh other than cylinders. Though I'm sure others have already requested that. Tool is very useful otherwise.
    I've had no luck trying to modify the script personally so I'll wait to see if future updates both work with 2021 still and add custom meshes to Spline Extrude.

    To avoid Double posting, I'm trying to detect if the player is at the end of a Spline however I'm having a hard time figuring it out. At the very least, I just need to get the closest knot index at a int.
     
    Last edited: Apr 14, 2023
  12. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    We know it now as it has just been reported. A bug ticket is mainly for you users to be able to track the fix and know when it'll be available :)
     
    GDevTeam likes this.
  13. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    This haven't been planed for now, but we can have a look at this. However this will not cover all of the use cases :D Because there are sooo many of them :p

    Depending on how your player is moving along the spline the solution will be different! Are you using the SplineAnimate component ? Or another custom script to move it ?
     
    Buffles-TE likes this.
  14. Buffles-TE

    Buffles-TE

    Joined:
    Mar 19, 2013
    Posts:
    10
    Custom script currently. Trying to use Rigidbody Momentum to move through the spine similar to a rollercoaster. The current idea I'm looking at isn't the best as I'm trying to get the index based on the closest spline to the player and then check to see if it's the last knot in the spline. Gonna take another shot today, programming at 2am is not a good idea.
     
    ThomasLopez likes this.
  15. neuroGear

    neuroGear

    Joined:
    Nov 25, 2012
    Posts:
    8
    So I decided to try to make a repro on empty project and found an interesting behaviour.

    In my current project when instantiating meshes(using Spline Instantiate component) on spline those meshes are hidden and on heavier scenes editor starts lagging for few seconds when play mode is stopped. Removing instantiate component fixes the issue completely. Empty scenes are ok though.

    On new project using same unity version(2022.2.12) and same spline package version(2.1.0) there is no such behaviour. Instantiate component does not hide those meshes, they are visible as child objects of spline and did not see any sort of slow downs.
     
  16. firebird721

    firebird721

    Joined:
    Jun 8, 2022
    Posts:
    101
     
  17. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    For that one you should be using GetComponent<SplineAnimate>().Container, looking at the API in 2.2.0 :


    Code (CSharp):
    1.  
    2. /// <summary>The target container of the splines to follow.</summary>
    3. [Obsolete("Use Container instead.", false)]
    4. public SplineContainer splineContainer => Container;
    5. /// <summary>The target container of the splines to follow.</summary>
    6. public SplineContainer Container
    7.  
     
    firebird721 likes this.
  18. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    If I understand correctly, you are trying to make evaluate the spline with something that is not "attached" to it (or animate on it), which might sounds difficult indeed! Could you animate using the SplineAnimate component for instance and then modify the motion speed (in the component) on-the-fly using a simulated rigibody momentum to compute the updated speed every frame? Might it be simpler that way?
     
    firebird721 likes this.
  19. firebird721

    firebird721

    Joined:
    Jun 8, 2022
    Posts:
    101
     
  20. firebird721

    firebird721

    Joined:
    Jun 8, 2022
    Posts:
    101
    HI
    thx for the replay

    my goal is like this

    i have enemy prefabs which moves by splines animations curves

    this enemy prefabs resides inside waves scriptable objects of WAVES INFO

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Splines;
    [CreateAssetMenu(fileName = "WaveInfo", menuName = "GAME_DATA", order = 0)]
    public class WaveInfo : ScriptableObject
    {
    [Header("what kind of enemies?")]
    public GameObject EnemyShipsPrefab;

    [Header("true if hasnt neen spawned yet")]
    public bool AlreadySpawned = false;

    [Header("points for kiiling one enemy in this wave")]
    public int pointsForKillingMe = 1;

    [Header("BOSS STAGE")] // stop km
    public bool bossStage = true;
    [Header("Wave Speed")]
    public int speed;

    [Header("Waves positioning of the spline")]
    public Transform transform;

    public SplineContainer SplineWavePath;

    [Header("Health Settings")]
    public int totalHealth=8;
    [Header("delay between enemies in the waves")]
    public float delayBetweenEnemies = 1f;

    public class Shooting
    {
    [Range(0, 100)]
    [Tooltip("probability with which the ship of this wave will make a shot")]
    public int shotChance = 80;
    [Tooltip("min and max time from the beginning of the path when the enemy can make a shot")]


    Inside my waves manager i spawn this waves
    i look at the wave info - take the enemy prebafab and pool it
    and then connect it to the right spline as is written in waves info

    i for example can make for red_enemey three waves - each with its own spline - but i need to asssign the spline to the enmey prefab(by the way - this is netcode game so i do it in the server - i think ag least that what shold i do...)


    all in all i THINK I need to go to enemy prefab in runtime and set it to different spline container

    public float shotTimeMin, shotTimeMax;
    }
    }
     
    Last edited: Apr 25, 2023
  21. firebird721

    firebird721

    Joined:
    Jun 8, 2022
    Posts:
    101

    ok - checked it out and it worked great...
    this what i did like you said

    //here is where the magic happens
    IEnumerator SpawnNumberOfTimes(GameObject enemyPrefb, int numberOfObjectsToSpawn, int points, int wavesIndex, SplineContainer splineContainer)
    {
    if (!IsServer)
    yield return new WaitForSeconds(1.5f); ;

    for (int i = 0; i < numberOfObjectsToSpawn; i++)
    {
    // m_theEnemyShipWeAreTryingToSpawn = objectsPool.PullGameObject(position, Random.rotation);
    // print("spawn one more :" + " index: " + i + " name: " + name);
    // boomServerRpc(name);
    // RevisedProjectile enemyPrefab;
    //enemyPrefab = m_networkObjectPool.ShootTheGun_ByPrfab_name(name);

    NetworkObject NETenemyPrefab = NetworkObjectPool.Singleton.GetNetworkObject(enemyPrefb, Vector3.zero, Quaternion.identity, NetworkObjectPool.Kind_of_pools.Enemy);
    NETenemyPrefab.GetComponent<NetworkObject>().Spawn(true);

    NETenemyPrefab.GetComponent<Enemy_data_info>().pnt = points;

    NETenemyPrefab.GetComponent<Enemy_data_info>().waveIndex = wavesIndex;
    NETenemyPrefab.GetComponent<SplineAnimate>().Container = splineContainer;
    yield return new WaitForSeconds(1.5f);
    }

    }


    i have to sayy that it so hard to know after which toturial to folow becuse all is changing so fast - also i am trying to usee chatgpt but he is not updated to0 well...
    at least so good we have you guys!


    thhhanx allot - now alll enemys gooes in differnt dirrectttions like they should

    upload_2023-4-25_3-41-21.png
     
    JonathanMeaney and ThomasLopez like this.
  22. Liviuss

    Liviuss

    Joined:
    Apr 2, 2014
    Posts:
    101
    Hi,

    I have 2 questions/issues.

    1. Is there a way to get the Length between two (t) on the same NativeSpline?

    2. How precise is the function SplineUtility.GetNearestPoint

    I have a scenario with 50 objects placed at a equal distance on spline line with 2 knots:

    a) Extend the spline by adding 1 knot so the last element is always behind the knot

    b) Evaluate all objects and cache data
    Code (CSharp):
    1.  
    2. using NativeSpline NativePath = new NativeSpline(SplineContainer.Spline, SplineContainer.transform.localToWorldMatrix);
    3. foreach(Agent agent in agents){
    4.  SplineUtility.GetNearestPoint(NativePath, agent.transform.position, out float3 pos, out float time);
    5.  agent.transform.position = pos;
    6.  agent.t = time;
    7. }
    8.  
    c) Move all objects in Update
    Code (CSharp):
    1.  
    2. using NativeSpline NativePath = new NativeSpline(SplineContainer.Spline, SplineContainer.transform.localToWorldMatrix);
    3. float speed = 0.1f * Time.deltaTime;
    4.  
    5. foreach(Agent agent in agents){
    6.  var pos = NativePath.EvaluatePosition(agent.t + speed);
    7.  var dir = NativePath.EvaluateTangent(agent.t + speed);
    8.  agent.transform.position = pos;
    9.  agent.transform.LookAt(pos + dir, agent.transform.up);
    10. }
    11.  
    d)Repeat again

    After a while i can see that placement of the points on the spline is irregular due to the t/pos evaluation. The distance between first and last element is getting bigger by each update.
    Is there something i miss?

    Thanks
     
    Last edited: Apr 30, 2023
    firebird721 likes this.
  23. kin4n

    kin4n

    Joined:
    Jan 17, 2023
    Posts:
    9
    Hello, I m trying to pass a different material for various splines to the LoftRoadBehaviour Class, is there a way to do this ?
     
  24. fendercodes

    fendercodes

    Joined:
    Feb 4, 2019
    Posts:
    191
    We've upgraded to 2.2.1 in our Unity 2022.2 project. There's some Debug.Log spam from each of our splines with SplineInstantiate:

    Look rotation viewing vector is zero
    UnityEngine.Splines.SplineInstantiate:OnEnable ()
     
    ThomasLopez likes this.
  25. fendercodes

    fendercodes

    Joined:
    Feb 4, 2019
    Posts:
    191
    Also, we have been getting these errors appearing for loads of our Splines that were created in 2.1.0 before upgrading to 2.2.0.

    IndexOutOfRangeException: Index was outside the bounds of the array.
    UnityEngine.Splines.Spline.GetCurveLength (System.Int32 index) (at ./Library/PackageCache/com.unity.splines@2.2.1/Runtime/Spline.cs:804)
    UnityEngine.Splines.Spline.CacheKnotOperationCurves (System.Int32 index) (at ./Library/PackageCache/com.unity.splines@2.2.1/Runtime/Spline.cs:1023)
    UnityEngine.Splines.Spline.RemoveAt (System.Int32 index) (at ./Library/PackageCache/com.unity.splines@2.2.1/Runtime/Spline.cs:676)
    UnityEditor.Splines.EditorSplineUtility.RemoveKnot (UnityEditor.Splines.SelectableKnot knot) (at ./Library/PackageCache/com.unity.splines@2.2.1/Editor/Utilities/EditorSplineUtility.cs:352)
    UnityEditor.Splines.KnotReorderableList.OnRemove (UnityEditorInternal.ReorderableList _) (at ./Library/PackageCache/com.unity.splines@2.2.1/Editor/GUI/Editors/KnotReorderableList.cs:264)
    UnityEditorInternal.ReorderableList+Defaults.DrawFooter (UnityEngine.Rect rect, UnityEditorInternal.ReorderableList list) (at <88872b21b1e746a7ad699974a2be8304>:0)
    UnityEditorInternal.ReorderableList.DoListFooter (UnityEngine.Rect footerRect) (at <88872b21b1e746a7ad699974a2be8304>:0)
    UnityEditorInternal.ReorderableList.DoList (UnityEngine.Rect rect, UnityEngine.Rect visibleRect) (at <88872b21b1e746a7ad699974a2be8304>:0)
    UnityEditorInternal.ReorderableList.DoList (UnityEngine.Rect rect) (at <88872b21b1e746a7ad699974a2be8304>:0)
    UnityEditor.Splines.SplinePropertyDrawer.OnGUI (UnityEngine.Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label) (at ./Library/PackageCache/com.unity.splines@2.2.1/Editor/GUI/Editors/SplinePropertyDrawer.cs:54)
    UnityEditor.PropertyDrawer.OnGUISafe (UnityEngine.Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label) (at <88872b21b1e746a7ad699974a2be8304>:0)
    UnityEditor.PropertyHandler.OnGUI (UnityEngine.Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label, System.Boolean includeChildren, UnityEngine.Rect visibleArea) (at <88872b21b1e746a7ad699974a2be8304>:0)
    UnityEditor.PropertyHandler.OnGUI (UnityEngine.Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label, System.Boolean includeChildren) (at <88872b21b1e746a7ad699974a2be8304>:0)
    UnityEditor.EditorGUI.PropertyFieldInternal (UnityEngine.Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label, System.Boolean includeChildren) (at <88872b21b1e746a7ad699974a2be8304>:0)
    UnityEditor.EditorGUI.PropertyField (UnityEngine.Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label, System.Boolean includeChildren) (at <88872b21b1e746a7ad699974a2be8304>:0)
    UnityEditor.EditorGUI.PropertyField (UnityEngine.Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label) (at <88872b21b1e746a7ad699974a2be8304>:0)
    UnityEditor.Splines.SplineReorderableList.DrawElement (UnityEngine.Rect position, System.Int32 listIndex, System.Boolean isactive, System.Boolean isfocused) (at ./Library/PackageCache/com.unity.splines@2.2.1/Editor/GUI/Editors/SplineReorderableList.cs:73)
    UnityEditorInternal.ReorderableList.DoListElements (UnityEngine.Rect listRect, UnityEngine.Rect visibleRect) (at <88872b21b1e746a7ad699974a2be8304>:0)
    UnityEditorInternal.ReorderableList.DoLayoutList () (at <88872b21b1e746a7ad699974a2be8304>:0)
    UnityEditor.Splines.SplineContainerEditor.OnInspectorGUI () (at ./Library/PackageCache/com.unity.splines@2.2.1/Editor/Components/SplineContainerEditor.cs:79)
    UnityEditor.UIElements.InspectorElement+<>c__DisplayClass72_0.<CreateInspectorElementUsingIMGUI>b__0 () (at <88872b21b1e746a7ad699974a2be8304>:0)
    UnityEngine.GUIUtility:processEvent(Int32, IntPtr, Boolean&)
     
    ThomasLopez likes this.
  26. ManuelRauber

    ManuelRauber

    Joined:
    Apr 3, 2015
    Posts:
    122
    Same issue here. Had to recreate the splines. :(
     
    ThomasLopez likes this.
  27. vlastan

    vlastan

    Joined:
    Nov 15, 2015
    Posts:
    49
    Hi, i'm experimenting with the spline tool and the game object instantiate component. The big question i have is how can i bake these gameobject into my scene hierarchy, so i can tweak them and bake lightmaps on them. Right now i can't see any of the instantiated objects in my scene hierarchy.
     
    ThomasLopez likes this.
  28. AntonAndev

    AntonAndev

    Joined:
    Aug 13, 2014
    Posts:
    44
    Hi! I create knots from world vectors in a scene, how can I change type of a knot? I need to set it to Auto. By default knot has mode Bezier Broken with zero tangents.


    Code (CSharp):
    1.             var container = pathManager.gameObject.AddComponent<SplineContainer>();
    2.             var spline = container[0];
    3.  
    4.             foreach (var vector in KnotsAsWorldVectors)
    5.             {
    6.                 BezierKnot knot = new BezierKnot(vector);
    7.                 knots.Add(knot);
    8.             }
    9.  
    10.             spline.Knots = knots;
     
  29. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hey @Liviuss,
    So here I am to try answering your questions!
    1- No there is no such method, the way I would go would be to convert your units from t to distance using SplineUtility.ConvertIndexUnit. That would result in something like this:
    var distanceBetween = nativeSpline.ConvertIndexUnit(t2, PathIndexUnit.Distance) - nativeSpline.ConvertIndexUnit(t1, PathIndexUnit.Distance);


    2- Your code looks ok, you can change the resolution used by SplineUtility.GetNearestPoint using the extra parameters 'resolution' and 'iteration' for this method (Follow the link to the doc for more info on these parameters effects):
    public static float GetNearestPoint<T>(T spline, float3 point, out float3 nearest, out float t, int resolution = 4, int iterations = 2)

    But other than that, the agents should be moving from the same distance once they are initialized on the spline. Small optimization, I would change your loop for this:
    Code (CSharp):
    1.  
    2. foreach(Agent agent in agents){
    3. (agent.t = agent.t + speed; ?)
    4. NativePath.Evaluate(agent.t, out var pos, out var dir, out var up);
    5.  agent.transform.position = pos;
    6.  agent.transform.LookAt(pos + dir, agent.transform.up);
    7. }
    8.  
    Calling Evaluate instead of EvaluatePosition + EvaluateTangent is more performant as it reduces pre-computation duplicates.

    Do you have a more complete sample/video where moving agents along splines is not uniform to help us understand the problem ?

    Hope this helps, don't hesitate if you need more info!
     
  30. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hi @kin4n,
    On this point, the LoftRoadBehaviour is (and will remain) a sample Component we provide to demo some use of splines. This is not a officially supported component such as SplineInstantiate, or SplineExtrude. So this component is only working on some specific usecase in the context of our demos, but are not meant to be used for your own productions.

    Long story short, we are not planning to expose the material for that component as this component is too specific. However, as this is a sample, feel free to re-use its code and adapt it to your needs in a better way :)
     
  31. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Thanks for the notification,
    We heard about that too, this is fixed here and will be soon be release in the next version fix!
     
    fendercodes likes this.
  32. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Thanks for the report on that too!
    I'll check if I can repro that here and fix that in this case!
     
  33. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hi @AntonAndev,
    So first of all, you can specify you tangents when building the knots using this constructor:
    public BezierKnot(float3 position, float3 tangentIn, float3 tangentOut, quaternion rotation)

    As for adding the knots, there is multiple Add() function you can use. Regarding your usecase you would want to use either:
    public void Add(BezierKnot item, TangentMode mode)
    or, this one if you want to modify the tension in autosmooth mode:
    public void Add(BezierKnot item, TangentMode mode, float tension)

    I'll encourage you to follow the links to the doc to get more info on the use of each parameter :)
     
  34. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159

    Hi @vlastan, Thanks for the feedback on that!

    For now this is not possible to bake the instantiated objects and there are not visible in the scene view.
    The reason for that it's that it's simply prodedural generation, and every time a slight parameter is changed in the SplineInstantiate, all the instance are generated again. Allowing manual tweak would complicate that as instances could be moved around for instance or modified and changing the SplineInstante Component later would impact that after manual tweaks.

    However, we do understand the limitation you are facing here. One thing that could be done, is that when you are happy with a config, we could add a "Bake" button on the component that would destroy the SplineInstantiate component and make all the created instances visible in the Scene View at that moment. What would that sounds for your case ?
     
  35. Misaki_eKU

    Misaki_eKU

    Joined:
    May 3, 2018
    Posts:
    96
    Has the
    spawn with spline bounds
    script been removed in the latest version?
     
  36. ThomasLopez

    ThomasLopez

    Unity Technologies

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

    Indeed this
    SpawnWithinSplineBounds.cs
    component was part of our previous samples. We recently cleaned this samples to remove duplicates and scripts that were not demoing spline usage. As this sample was mostly focusing on generating prefabs and not using splines, that was part of the cleaning.

    Feel free to create your own code based on our previous samples, however, be aware that as this was a sample, this is not supported code and can have limitation due to the sample case. As I remember itm this was limited to procedural spawning in a 2D area, with limited functionnality when the spline was not closed and other factors.
     
  37. kin4n

    kin4n

    Joined:
    Jan 17, 2023
    Posts:
    9
    Hi Thomas thank you for your reply, I m using SplineAnimate(), but : 1 : I keep getting Look rotation viewing vector is zero after (in the same frame, after a check on SplineAnimate().Normalizedtime >=1, passing a new Container().Spline), and for one frame, passing from a spline to another jumps the GameObject back to it s 0 position on the spline, creating a glitch. I could nt find a way to safe protect the LookAt, any hint ?
     
  38. kin4n

    kin4n

    Joined:
    Jan 17, 2023
    Posts:
    9
    Hello how do you convert a SplineContainer.spline into world matrix ?
     
  39. vlastan

    vlastan

    Joined:
    Nov 15, 2015
    Posts:
    49
    Yes, i think a bake button is certainly needed.
     
  40. NickLudlam2

    NickLudlam2

    Joined:
    Nov 19, 2016
    Posts:
    3
    Hello, is it possible for you to implement the optional JobHandle argument that can be passed to Dispose() in NativeSpline.cs ?
     
  41. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Native spline is the solution you are looking for :)

    For instance:
    var container = GetComponent<SplineContainer>();
    var spline = container.Spline;
    using (var nSpline = new NativeSpline(spline, container.transform.localToWorldMatrix))
    {
    var worldPos = nSpline.Evaluate(0.5f);
    }
     
  42. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    I'll check if there is something on the SplineAnimate that needs to be fixed regarding that.
    On your side you can have a look to check if using quaternion.LookRotationSafe can help you with that?
     
  43. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    That'll be available in the next update (~ end of may, early june) :D
     
  44. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    Hi @NickLudlam2 , the Dispose() method is inherited from IDisposable interface and thus we cannot add any parameter to it, this is directly called by the interface at the end of the scope when the NativeSpline is created in a scope.
    To get a little mode context, why would you need to add a JobHandle here?

    Could you do something like :
    var nativeSpline = new NativeSpline(spline, container.transform.localToWorldMatrix);
    // Setup the data for job #1
    MyJob jobData = new MyJob();
    JobHandle handle = jobData.Schedule();
    handle.Complete();
    // Free the memory allocated by the nativeSpline
    nativeSpline.Dispose();
     
    Last edited: May 24, 2023
  45. NickLudlam2

    NickLudlam2

    Joined:
    Nov 19, 2016
    Posts:
    3
    Ah, I didn't see that it was particular to some Native containers, not all of them. It's a pattern I've got in the habit of using with NativeArrays where I can allocate something before a job chain, schedule them all in a row, passing forward the job handles in each case, and then I clear up any temporary allocations with a `Dispose(jobHandle)` call.

    Right now the pattern you're suggesting isn't super straight forward for me because of this dependency chaining. I will probably go the Persistent allocation route, and have a longer lifecycle. Thanks for the reply!
     
  46. kin4n

    kin4n

    Joined:
    Jan 17, 2023
    Posts:
    9
    mmm thank you for your answer. In order to modify the SplineAnimate script, I would need to copy the package somwhere else and remove the original Spline2 package from the packageManager. Do you think it will destroy all my splines ? And even if not, I would have te relink pretty myuch everything by hand, right ? Or is there a way to modify the script at its native location ?
     
    ThomasLopez likes this.
  47. fxlange

    fxlange

    Joined:
    Dec 20, 2016
    Posts:
    45
    I did some performance tests with non jobified splines would appreciate some feedback on the results.

    The documentation points out that it is cheaper to call the combined Evaluate instead of evaluating pos, tangent and up vector seperately. I can confirm that but at the same time I was surpised to see how much more expensive the up vector portion of Evaluate is.

    100 Evaluate = 3.6ms vs 100 EvaluatePos+EvaluateTangent = 1.1ms (roughly).

    So if you don't need the up vector, it is acually better to not use the combined Evaluate.

    Additionally I wrote a combined pos and tangent evaluation which took only 0.6ms for 100 calls.
    So basically up vector evaluation seems to be 5/6 of the combined evaluation in terms of performance.

    Might be worth mentioning in the docs and maybe offering a combined pos&tangent evaluate.

    (Tested on a m1 macbook air, in the editor).
     
    Last edited: May 27, 2023
    ThomasLopez and JonathanMeaney like this.
  48. soleron

    soleron

    Joined:
    Apr 21, 2013
    Posts:
    580
    Any practical tutorials out there for the most common use cases of splines?

    Not that many on youtube and most of them on the same thing.
     
    Last edited: May 26, 2023
    ThomasLopez likes this.
  49. ManuelRauber

    ManuelRauber

    Joined:
    Apr 3, 2015
    Posts:
    122
    Extensibility of Unity Spline Editor

    I have the following use case:

    I want to add a second button below the "Knot Placement Tool". That is easily possible by:

    Code (CSharp):
    1. [EditorTool("Create Edge", typeof(ISplineContainer), typeof(SplineToolContext))]
    2. sealed class CreateEdgeTool : EditorTool { }
    The idea of the tool is the following: Whenever a knot is selected and I press the button, I want to insert one knot before and one knot after the selected one and specify a specific position, rotation and bezier in/out.

    However, all the interesting stuff that Unity Splines already has in their editor (e.g. SplineTool-Base, SplineSelection, ...) is internal and not accessible from the outside.

    So, either I have to recode a lot of that stuff in order to make my idea work or I don't see any other possibility.
    If there is no other possibility, then I want to raise the question, why all that stuff is made internal instead of public to allow the usage and build tools upon those functions?

    Thanks!
     
    ThomasLopez and GDevTeam like this.
  50. ThomasLopez

    ThomasLopez

    Unity Technologies

    Joined:
    Jun 8, 2020
    Posts:
    159
    I Will check the SplineAnimate on our side as you won't be able to make modification to it. Indeed, if you remove the spline package all the Spline components (SplineContainer included) will be destroyed and so would be your splines as well.