Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Spline Controller Flickering
#1
I have a Spline where the number of control points could change but the total length will always stay the same.

I'm using absolute positioning for the Spline Controllers, and storing their "Position" in another variable outside of the Spline Controller so when the number of control points changes, I can remap its position exactly where it was.

It seems that when I change the number of control points, Spline.Length takes a moment before the results are accurately reflected and there's a moment of artifacting where some of the Spline Controller Objects are disoriented and all over the spline. Seems to only happen for one frame and then everything goes back to normal.

I've tried changing the Update in to LateUpdate, as well as setting the CacheDensity to 0 and calling Spline.Refresh();

Any help greatly appreciated!
Reply
#2
Hi
Do you have a simple reproduction case you can share with me?
Please consider leaving a review for Curvy. This will help a lot keeping Curvy relevant in the eyes of the Asset Store algorithm.
Reply
#3
I tried to recreate in isolation and wasn't able to. Must be a bug in my code.
Reply
#4
Ok so I was able to recreate it - you can attach this script to an empty game object.

If you look at line 44 "Spline.Add(new Vector3(0, 0, 30 - Spline.Length));" I'm attempting to use the current length of the spline to ensure the length is always 30.

If you change line 44 from 
Code:
Spline.Add(new Vector3(0, 0, 30 - Spline.Length));
to
Code:
Spline.Add(new Vector3(0, 0, 30));

The issue goes away.

Any help much appreciated!



Code:
using FluffyUnderware.Curvy;
using FluffyUnderware.Curvy.Controllers;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SplineTest : MonoBehaviour
{
    // Start is called before the first frame update
    private CurvySpline Spline;
    private List<SplineFollower> Followers = new List<SplineFollower>();
    void Start()
    {
        Spline = gameObject.AddComponent(typeof(CurvySpline)) as CurvySpline;

        // Create Spline Followers\Controllers
        for (int i = 0; i < 6; i++)
        {
            Followers.Add(new SplineFollower(Spline,i * 5));
        }

        Spline.Add(new Vector3(0, 0, 0));
        Spline.Add(new Vector3(0, 0, 30));
    }

    // Update is called once per frame
    void Update()
    {
        Spline.Clear();
        Spline.Add(new Vector3(0, 0, 0));
        // Create first Control point
        Spline.Add(new Vector3(0, 0, 0));

        //Create random number of control points
        int rnd = Random.Range(1, 5);
        for (int i = 1; i < rnd; i++)
        {
            Spline.Add(new Vector3(0, 0, i * 4));
        }

        Debug.LogWarning($"SplineLength: {Spline.Length} LastCPZ: {Spline.LastSegment.transform.position.z}");

        // Create last Control point
        Spline.Add(new Vector3(0, 0, 30 - Spline.Length));

       

        foreach (var item in Followers)
        {
            item.Move(0.1f);
        }
    }

    public class SplineFollower
    {
        public SplineController Controller;
        public float Position;

        public SplineFollower(CurvySpline spline, float position)
        {
            GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            Controller = go.AddComponent(typeof(SplineController)) as SplineController;
            Controller.PositionMode = CurvyPositionMode.WorldUnits;
            Controller.Spline = spline;
            Position = position;
        }

        public void Move(float amount)
        {
            Position += amount;
            Controller.Position = Position;
        }
    }
}
Reply
#5
Hi

Before giving the answer to the problem, you have the following line twice in a row, I believe it is a mistake from you:
Spline.Add(new Vector3(0, 0, 0));

About the issue: you are having a SplineFollower.Position that is increased every frame, and your splines have a maximal length of 30. So after some time, SplineFollower.Position will be bigger than 30. Let's say that a specific frame it is 40, and you spline length is 30. You controller's Clamping is set to Loop, so that means that your 40 will be equivalent to a position of 10. Now next frame, your SplineFollower.Position is 40.1. Let's imagine that your spline length this frame is 20. That means that you position, after looping, will be equivalent to 0.1. That means that your sphere jumped a distance of 9.9 backwards. Next frame it will jump some distance either forward or backward, creating the flickering effect.

The solution: Move should call Controller.Position += amount instead of its current implementation. This is because Controller.Position, unlike SplineFollower.Position, is always in the right range of values.

Let me know if you are struggling with the suggested solution.
If and when you feel like it, please leave a review for the asset, that helps a lot
Have a nice day
Please consider leaving a review for Curvy. This will help a lot keeping Curvy relevant in the eyes of the Asset Store algorithm.
Reply
#6
Thank you for the help!

I removed the extra CP I accidentally added and am using Controller.Position += amount, it positions all of there spheres in the same place.

But the real problem is Spline.Length isn't 30 - you can see that on line 45 - Debug.LogWarning.

Code:
using FluffyUnderware.Curvy;
using FluffyUnderware.Curvy.Controllers;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class SplineTest : MonoBehaviour
{
    // Start is called before the first frame update
    private CurvySpline Spline;
    private List<SplineFollower> Followers = new List<SplineFollower>();
    void Start()
    {
        Spline = gameObject.AddComponent(typeof(CurvySpline)) as CurvySpline;

        // Create Spline Followers\Controllers
        for (int i = 0; i < 6; i++)
        {
            Followers.Add(new SplineFollower(Spline,i * 5));
        }

        Spline.Add(new Vector3(0, 0, 0));
        Spline.Add(new Vector3(0, 0, 30));
    }

    // Update is called once per frame
    void Update()
    {
        Spline.Clear();

        // Create first Control point
        Spline.Add(new Vector3(0, 0, 0));

        //Create random number of control points
        int rnd = Random.Range(1, 5);
        for (int i = 1; i < rnd; i++)
        {
            Spline.Add(new Vector3(0, 0, i * 4.0f));
        }

        // Create last Control point
        Spline.Add(new Vector3(0, 0, 30 - Spline.Length));

        Debug.LogWarning(Spline.Length);
       

        foreach (var item in Followers)
        {
            item.Move(0.1f);
        }
    }

    public class SplineFollower
    {
        public SplineController Controller;
        public float Position;

        public SplineFollower(CurvySpline spline, float position)
        {
            GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            Controller = go.AddComponent(typeof(SplineController)) as SplineController;
            Controller.PositionMode = CurvyPositionMode.WorldUnits;
            Controller.Spline = spline;
            Position = position;
        }

        public void Move(float amount)
        {
            //Position += amount;
            Controller.Position += amount;
        }
    }
}
Reply
#7
(09-02-2021, 11:03 PM)blabz2007 Wrote: But the real problem is Spline.Length isn't 30 - you can see that on line 45 - Debug.LogWarning.
That's normal: all your CPs have 0 coordinates on x and y. So the only relevant coordinate is Z. Your first CP has a Z of 0. Also your setup gives for each CP a Z coordinate bigger than its previous one. So under all those circumstances, the length of your spline is the Z coordinate of your last CP, which is 30 - Z coordinate of the previous CP.

Here is a variation of your code that does maintain the length of the spline to 30

Code:
int rnd = Random.Range(1, 5);
        float lastUsedZ = 0;
        for (int i = 1; i < rnd; i++)
        {
            lastUsedZ = lastUsedZ + i * 4.0f;
            Spline.Add(new Vector3(0, 0, lastUsedZ));
        }

        // Create last Control point
        Spline.Add(new Vector3(0, 0, lastUsedZ + 30 - Spline.Length));

If your spline has always the same length, then the problem I explained in my previous post is no more.
Please consider leaving a review for Curvy. This will help a lot keeping Curvy relevant in the eyes of the Asset Store algorithm.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Curvy Line Renderer for UI Spline? gekido 1 1 8 hours ago
Last Post: _Aka_
  Get position of all control points for a spline gekido 1 2 8 hours ago
Last Post: _Aka_
Bug Changing spline connection in inspector causes splines to revert to defaults lacota 3 6 03-18-2024, 07:55 PM
Last Post: _Aka_
  GO can't fit end of the spline GameDeveloperek4123 3 13 03-04-2024, 11:06 AM
Last Post: _Aka_

Forum Jump: