Search Unity

BGCurve (free Bezier Spline Editor) support thread

Discussion in 'Assets and Asset Store' started by BansheeGz, Feb 18, 2017.

  1. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    902
    Hiya,

    Piloting this asset. So far very impressed! However, when I run a build (Unity 2019), Android or PC, I get this error inside the executable:

    A scripted object (script unknown or not yet loaded) has a different serialization layout when loading. (Read 44 bytes but expected 72 bytes)
    Did you #ifdef UNITY_EDITOR a section of your serialized properties in any of your scripts?​

    Googling shows it's caused by [SerializeField] fields inside #if UNITY_EDITOR directives. The only such serialisation I have is inside BGCurve scripts.

    How do I manage this so builds run correctly?
     
  2. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    370
    Hello, sorry, we could not reproduce this issue
    Here is the example project - https://drive.google.com/file/d/1y_ZEaiRXkX_2dPpCUjXiaTYMacCNfqT6/view?usp=sharing which only have one single BGCurve asset
    One curve is loaded as part of the scene, another one is loaded via prefab and yet another one is loaded from Resources folder.
    All three are working fine on Windows and Android.
    All test scenes also work ok
    Unity 2019.4.31
     
  3. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    902
    Cheers. I shouldn't have bothered you so early as I hadn't tried a proper investigation. After the rest of yesterday investigating starting from an empty project and building up with BGC, it seems related to linking to BGCurve within Scriptable Objects, so possibly not anything to do with you. loading the project now, the SO that refers to GBC is missing its script, suggesting an internal build issue with Unity and SO's using Serialised #Editor fields.
     
  4. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    370
    Not a problem at all, thank you for the update!
    We tried to reference a curve from a scriptable object- still no errors
    Anyway, if you think these #ifdef UNITY_EDITOR blocks may cause some issues- please, let me know
     
  5. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    902
    Is it possible to rotate a curve at runtime? Let's say I've defined a 2 point straight line Left to Right, can I rotate that to face bottom right to top left?
     
  6. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    370
    Points/tangents locations are relative to GameObject's transform.
    It means that if you translate/rotate/scale transform- points/tangents are also affected
    Also GameObject's transform position is a pivot point for points/tangents rotation

    For example, this code rotate XY 2D curve 90 degrees around Z axis for 1 second
    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3.  
    4. public class Rotation : MonoBehaviour
    5. {
    6.     //rotating XY 2D curve 90 degrees around Z axis for 1 second
    7.     void Start() => StartCoroutine(Rotate(Quaternion.AngleAxis(90, Vector3.forward), 1));
    8.  
    9.     IEnumerator Rotate(Quaternion to, float transitionPeriod)
    10.     {
    11.         var from = gameObject.transform.rotation;
    12.         var started = Time.time;
    13.         while (true)
    14.         {
    15.             var elapsed = Time.time - started;
    16.             if (elapsed >= transitionPeriod)
    17.             {
    18.                 gameObject.transform.rotation = to;
    19.                 break;
    20.             }
    21.             gameObject.transform.rotation = Quaternion.Lerp(from, to, elapsed / transitionPeriod);
    22.             yield return null;
    23.         }
    24.     }
    25. }
    22.png

    The result
    1.gif
    I use LineRenderer component to visualize the curve in runtime https://www.bansheegz.com/BGCurve/Cc/BGCcVisualizationLineRenderer/
     
    Last edited: Aug 7, 2022
    SoftwareGeezers likes this.
  7. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,090
    I'm planning to optimize library a bit. Any reason why
    BGCurvePoint[] points 
    is an array not a list?
     
  8. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    370
    Yes, I think it can be replaced with List

    We also had some plans to upgrade this library to version 2, not compatible with version 1.x, so we could use Unity 2020 as a minimum version to replace outdated serialization-related code and remove tree-based structure for components but did not have an opportunity to do it
     
  9. tree_arb

    tree_arb

    Joined:
    Dec 30, 2019
    Posts:
    323
    Hi,
    Can the Bezier handles be enabled for runtime? I would like to add points/curved lines at runtime with ability to adjust the Bezier handles same as you can in scene mode
     
  10. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    370
    Hi, yes, points can be added/deleted and points/handles positions can be assigned at runtime
    See Assets\BansheeGz\BGCurve\Examples\BGCurveTestRuntime example scene for implementation details (some other example scenes also have some examples of managing points/handles positions at runtime)
     
    tree_arb likes this.
  11. tree_arb

    tree_arb

    Joined:
    Dec 30, 2019
    Posts:
    323
    I'm looking at that example now. Is there a way to have the handles and Bezier control lines visible in runtime the same as scene view?

    So yes I see how points can be created/assigned with code at runtime but what about exposing the draggable handles to the runtime game mode? In scene view I can see handles and associated lines, also ctrl+click for adding points. very nice.

    I would like to have all that exposed in game mode, is that an option somewhere?

    Or, I can create my own draggable game object, associate that transform to the points control, so yes I see how it can be done, but it seems to already be completed but only in scene view just want to make sure im not missing something.

    amazing tool by the way!
     
  12. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    370
    Interactive handles are drawn with Handles class ( https://docs.unity3d.com/ScriptReference/Handles.html ), which works inside Unity's scene view only.
    There are some assets, which seem to provide support for interactive handles at runtime, for example:
    https://github.com/HiddenMonk/Unity3DRuntimeTransformGizmo
    https://github.com/pshtif/RuntimeTransformHandle
    Search for something like "unity runtime handles" or "unity runtime transform handles"
     
    tree_arb likes this.
  13. tree_arb

    tree_arb

    Joined:
    Dec 30, 2019
    Posts:
    323
    Thank you that explains it then, didn't realize it was using scene view only classes. I should be able to create my own handles like you suggest. Thanks!
     
    BansheeGz likes this.
  14. oggivseerden

    oggivseerden

    Joined:
    Jul 29, 2022
    Posts:
    2
    Hi, I just downloaded and imported your package, and it's great so far!

    I'm making a platforming/parkour movement game, and I'm trying to implement a rail grinding mechanic (like e.g Sonic or Jet Set Radio) using your package. I want to make the player be able to jump on the rail at any point and go from there. How would I go about doing this? I thought about calculating the distance ratio of where the player jumps on, or adding multiple points in between the start and ends, and seeing to which point the player is closest when jumping on and having them start from there, but I don't know how I would go about scripting them.

    I'd also like for the player to go forwards or backwards of the rail depending on how they jump on the rail, but this also has me stumped. I'd have to call the reverse function in a script after detemening the orientations of the player and rail somehow, but I have no idea how.

    Right now the player is able to jump on the rail by detecting collision, which then dynamically sets the "object to manipulate" field and the cursor speed equal to the players speed on collision. By using the distance ratio I can see when the player reaches the end, which then resets everything to null or 0, and calls the Jump function from the player movement script. I also temporarily disable the rail collider to avoid immediately snapping back to the rail. This means every time you jump on the rail, no matter where, you start from the beginning.

    Thanks in advance, and for the package!
     
  15. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    370
    Hi,
    I'm not sure if I understood you right, please, correct me if I did not
    I assume, you have a curved rail and a spline along this rail, and you use physics engine (colliders) to detect when a player jumps on the rail
    In this case, once you detected a collision, you can use BGMathCc component's CalcPositionByClosestPoint method to find the closest point on the spline.
    Pass the player's position as an argument, and you get position, distance and tangent as a result
    Code (CSharp):
    1.         BGCcMath math = GetComponent<BGCcMath>();
    2.         var position = math.CalcPositionByClosestPoint(playerPosition, out float distance, out Vector3 tangent);
    1) Use the distance as an initial distance
    Distance identifies how far the object from point # 0 if you move along the spline.
    DistanceRatio can be calculated by dividing the distance by spline's length (the value is always in [0,1] range)
    If you use BGTrsCc component for moving a player along the spline, pass the distance to BGTrsCc Distance property
    2) Use the spline's tangent and player's velocity to identify moving direction
    Calculate a dot product of these 2 vectors- if it's less than zero, you need to move in reverse direction, from initial point to the spline's start (point # 0)
    If you use BGTrsCc component for moving, you can assign negative speed to move the object backwards

    I'm not sure if this guide will work well, please let me know if you have any issue
     
  16. oggivseerden

    oggivseerden

    Joined:
    Jul 29, 2022
    Posts:
    2
    Thanks for your reply. You understood my question perfectly fine and your solution for the first problem works perfectly. However, using Vector3.Dot with the tangent and player velocity, (for which I used the rigidbody's velocity, don't know if that's fine), it always returns 0, both with and without normalising both vectors. Any idea as to why?

    EDIT: Upon further inspection it seems tangent is (0.00, 0.00, 0.00), which is most likely why this happens

    EDIT 2: I was stupid enough to not notice that I didn't set the math fields to "Position and Tangent" instead of just position. It works perfectly now. Thanks!
     
    Last edited: Jan 7, 2023
  17. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    370
    Yes, this "Fields" stuff is pretty confusing
    Thank you for the update
     
  18. Xileron

    Xileron

    Joined:
    Jan 8, 2023
    Posts:
    2
    Hello, thank you for making this package as I've found it extremely useful.

    I'm trying to get a 3D character to move along (or at least use the curve as a reference for its own path) however, I am having trouble figuring out at to how this can be done when using a character controller in conjunction with it. I've tried using translate object as well as connecting it to a cursor, but was unable to control my character with a controller.

    For reference I've seen one other user (Tattoomoosa) able to reproduce this:
    https://forums.tigsource.com/index.php?topic=64819.msg1383531#msg1383531

    He goes into detail about how he did it, but not as much on how he linked his his character up with the curve or in what manner he did so, whether it be with a components, or just simple coding.
     
  19. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    370
    Hello,

    Probably you could use the following trick-
    1) calculate the point (and distance) on the curve, which is closest to your character
    2) If your player is moving forward, then add some small constant to the calculated distance and calculate a position for this distance. If you are moving backwards, then subtract the same constant from the calculated distance and calculate a position.
    3) Use position from step # 2 to calculate movement direction, normalize it, multiply by speed and pass it to character controller SimpleMove method

    This approach will not work if your curve intersects with itself or if some section comes close to another section
    In this case, the code should be modified to keep track of current distance somehow, so the character could not switch to other section accidentally
    Also, if the spline could be closed the code should be modified as well to properly handle it
    The c# code:
    Code (CSharp):
    1. using BansheeGz.BGSpline.Components;
    2. using BansheeGz.BGSpline.Curve;
    3. using UnityEngine;
    4.  
    5. [RequireComponent(typeof(CharacterController))]
    6. public class SplineMovements : MonoBehaviour
    7. {
    8.     public BGCurve curve;
    9.     public float speed = 3f;
    10.     public float delta = .3f;
    11.  
    12.     private BGCcMath math;
    13.     private CharacterController controller;
    14.  
    15.     void Start()
    16.     {
    17.         math = curve.GetComponent<BGCcMath>();
    18.         controller = GetComponent<CharacterController>();
    19.     }
    20.  
    21.     void FixedUpdate()
    22.     {
    23.         var moveForward = Input.GetKey(KeyCode.W);
    24.         var moveBackwards = Input.GetKey(KeyCode.S);
    25.         if (!moveForward && !moveBackwards) return;
    26.         var position = transform.position;
    27.         math.CalcPositionByClosestPoint(position, out var distance);
    28.         var targetPosition = math.CalcPositionByDistance(distance + (moveForward ? delta : -delta));
    29.         var direction = (targetPosition - position).normalized;
    30.      
    31.         //move
    32.         controller.SimpleMove(direction * speed);
    33.  
    34.         //rotate
    35.         if (direction != Vector3.zero) transform.rotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z));
    36.     }
    37.  
    38.     private void OnGUI() => GUI.Label(new Rect(10, 10, 300, 60), "W-forward, S-backwards");
    39. }
    I also attached a package with an example scene.
    Create a new project, import Robot Kyle package ( https://assetstore.unity.com/packages/3d/characters/robots/space-robot-kyle-4696 ) , import the attached package and run Assets\Scenes\SampleScene.unity scene
     

    Attached Files:

  20. Xileron

    Xileron

    Joined:
    Jan 8, 2023
    Posts:
    2
    Thank you for all the help. I found up iterating upon your design by using a vector2 value with input controls to better adjust the controls later down the line. I'm still iterating upon this design even further though as now I am curious if I can make the transitions any smoother. Would it be possible to get the positions of the regular non-control white points?

    Also additionally would how might one go about copying certain point values from a control point. Like for instance if I only wanted to take the x or z value from the position a control point
     
  21. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    370
    Polyline splitter component does exactly this: https://www.bansheegz.com/BGCurve/Cc/BGCcSplitterPolyline/
    Use Positions property to access points array
    Code (CSharp):
    1. using BansheeGz.BGSpline.Components;
    2. using UnityEngine;
    3.  
    4. public class Test : MonoBehaviour
    5. {
    6.     void Start()
    7.     {
    8.         var polylineSplitter = GetComponent<BGCcSplitterPolyline>();
    9.         var positions = polylineSplitter.Positions;
    10.         foreach (var position in positions) print(position);
    11.     }
    12. }
    13.  
    Also, if you already have BGCcSweep2D or BGCcTriangulate2D or BGCcVisualizationLineRenderer components attached, you can use any of these components as well (cause all of them are inherited from BGCcSplitterPolyline component)
    To get control points local coordinates (relative to the point) use point.ControlFirstLocal property for the first control and point.ControlSecondLocal property for the second control
    To get control points world coordinates, use point.ControlFirstWorld property for the first control and point.ControlSecondWorld property for the second control
    Code (CSharp):
    1.  
    2. using BansheeGz.BGSpline.Curve;
    3. using UnityEngine;
    4.  
    5. public class Test : MonoBehaviour
    6. {
    7.     void Start()
    8.     {
    9.         var curve = GetComponent<BGCurve>();
    10.         var point = curve[0];
    11.         //incoming
    12.         Vector3 incomingControlLocal = point.ControlFirstLocal;
    13.         Vector3 incomingControlWorld = point.ControlFirstWorld;
    14.        
    15.         //outcoming
    16.         Vector3 outcomingControlLocal = point.ControlSecondLocal;
    17.         Vector3 outcomingControlWorld = point.ControlSecondWorld;
    18.     }
    19. }
    20.  
    After you received control position, you can access individual axis coordinates (x, y, z) the usual way via Vector3 fields
    Code (CSharp):
    1.  
    2. using BansheeGz.BGSpline.Curve;
    3. using UnityEngine;
    4.  
    5. public class Test : MonoBehaviour
    6. {
    7.     void Start()
    8.     {
    9.         var curve = GetComponent<BGCurve>();
    10.         var point = curve[0];
    11.         Vector3 control = point.ControlFirstLocal;
    12.         float x = control.x;
    13.         float y = control.y;
    14.         float z = control.z;
    15.     }
    16. }
    17.  
     
  22. JinTin39

    JinTin39

    Joined:
    Jan 21, 2023
    Posts:
    1
    Hi,
    I really like your product however I was wondering if there might some way find the granularity of a curve or of points on the curve?
     
  23. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    370
    Hi, do you mean the number of points for spline's approximation?
    You can use BGCcMath component's indexer to access section information and then use Points property to access the list of points and then use Count property to count them
    The result is the amount of all points in provided section (including the last point, shared with next section)
    Code (CSharp):
    1. using BansheeGz.BGSpline.Components;
    2. using UnityEngine;
    3.  
    4. public class Test : MonoBehaviour
    5. {
    6.     void Start()
    7.     {
    8.         var math = GetComponent<BGCcMath>();
    9.         var sectionIndex = 0;
    10.         print(math[sectionIndex].Points.Count);
    11.     }
    12. }
    Each section can have a different number of points unless you use "Base" math type with "Optimize straight lines" off, in this case the amount of points per section will always be "Section Parts" + 1 (31 in the example below)
    183.png
     
  24. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,090
    @BansheeGz have you checked unity's new Splines package? Any differences to BGCurve?
     
    BansheeGz likes this.
  25. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    370
    We've just checked the last version (2.1) and the asset looks amazing
    When it comes to editing spline in SceneView BGCurve is not even close.
    Probably there are some features, that BGCurve has out-of the-box and Splines does not, but they are very specific and do not make too much difference. And Spline asset is meant to be extensible- so adding new features should not be a problem
    In overall Spline asset looks much more superior
    We have added a warning about standard asset to our docs, maybe we will remove BGCurve from the Asset Store as outdated asset (it's still can be downloaded from github)
     
    Kamyker likes this.
  26. stigmamax

    stigmamax

    Joined:
    Jun 30, 2014
    Posts:
    312
    Dommage qu'il n'y ait aucune doc.