- Home /
How to create a continuous bezier curve path
Hello all. I want to make my gameobject follow either a cubic or quadratic bezier movement. I am using a coroutine using List array to keep track of 3 points and create a new random control Vector3 point and a new random end Vector3 point each time the gameobject reaches its endpoint and becomes the new start point so the object is always a infinite curvature motion. Currently its not behaving in a continuous motion and often jumps back to its start point instead of continuing to its new set of points.
So I did some looking into bezier curves with itween's moveTo() function (http://itween.pixelplacement.com/examples.php#randomPaths) & leantween's move() but didn't have any sample codes. Does anyone know if any of these 2 plugins can perform what I want to achieve? If so, some example code would be greatly appreciated or any other solution would be great. Thanks
Answer by robertbu · Mar 12, 2014 at 07:38 PM
You might be able to put something together using iTween or lean tween, but I if you needs something really accurate you'd be better using spline package rather than a tween package with a bit of spline on the side. Super Splines in the Asset store has come up favorable recommendations on this list a number of times.
Here is a bit of code that demonstrates how it might be done in iTween. iTween does not provide control points, so I use 5 points rather than 3. To use start with an new scene and do:
Create an empty game object, add a LineRenderer component, set the beginning and ending line width to 0.1, add a material if you like:
Create a sphere, size the sphere to 0.4,0.4 0.4.
Add the script below to the sphere, and drag and drop the game object with the line renderer on the 'Lr' variable.
Hit play
pragma strict
var threshold : float = 0.1; var radius = 5.5; var lr : LineRenderer; var speed : float = 2.0;
private var markers : Transform[] = new Transform[4]; private var path : Vector3[] = new Vector3[4]; private var fraction : float = 0.0; private var _speed : float; private var boundary : float = 2.0 / 3.0;
function Start() { for (var i = 0; i < path.Length; i++) { path[i] = Random.insideUnitSphere * radius; var go = GameObject.CreatePrimitive(PrimitiveType.Cube); go.transform.localScale = Vector3(0.2, 0.2, 0.2); go.transform.position = path[i]; markers[i] = go.transform; }
SetLineRenderer(); var l = GetPathLength(); _speed = speed / GetPathLength(); } function Update() { transform.position = iTween.PointOnPath(path, fraction); fraction += Time.deltaTime * _speed; if (fraction > boundary) { path[0] = path[1]; path[1] = transform.position; path[2] = path[3]; path[3] = Random.insideUnitSphere * radius; fraction = 1.0/3.0; _speed = speed / GetPathLength(); SetLineRenderer(); SetMarkers(); } } function SetMarkers() { for (var i = 0; i < markers.Length; i++) markers[i].position = path[i]; } function SetLineRenderer() { lr.SetVertexCount(101); for (var i = 0; i < 101; i++) { var f : float = i / 100.0; lr.SetPosition(i, iTween.PointOnPath(path, f)); } } function GetPathLength() : float { var length = 0.0; for (var i = 1; i < path.Length; i++) { length += Vector3.Distance(path[i-1], path[i]); } return length; }
A good deal of this code deals with putting marking cubes and lines to see the path and nodes and has nothing to do with walking the path. Note I determined empirically that there is a direct map between fraction and vertex position. That is, given five point in the path, point 3 will always be at fraction 0.5, and point 4 will always be at 0.75. This makes this code far easier (given the limited interface in iTween for paths) to write, but it also opens up a problem. That is, given random points of varying distance in the path, the object will travel slower or faster depending on the distance between the control points. I calculate a speed for the whole path, but the right thing to do (if you care), is to set the speed based on the distance in the current path segment.
Oh, and you need to have downloaded iTween (its free).
Thanks for the quick reply. I have 2 questions. Does this method smooth out the endpoints for next bezier curve? Also since I am making the gameobject move nonstop, wouldn't I need to make an object pool if I need to create infinite many primitive cubes?
I'm not sure how to answer your question. First, in thinking about, I only need four points, so the script above was edited for the four points. After the object first reaches the 2nd point, it spends the rest of its life going between points 2 and 3. As it reached the 3rd point, everything is shifted (first point discarded, new point 4) and the object is again at point 2. That means the object never comes near the end point (point 4), so the transition is as smooth as iTween's underlying spline code will make it. There is no abrupt change, but if the new point 4 is back towards point 2, you will get a sharp(er) turn. Since I have no context for your app, I don't know if that is an issue. There are potential fixes if it is, but I need context to make suggestions.
As for the primitive cubes, if you are talking about the ones I'm using for this script, then no, you don't need pooling. Or another way to look at it is that I am already pooling. That is the 'markers' array contains the cubes, and these cubes are realigned/reused each time the shift is made.
Okay thanks for clearing things up Robert. I appreciate it.
Your answer
Follow this Question
Related Questions
Spline off center using iTween 2 Answers
LeanTween: strange sequence of bezier control points 1 Answer
Itween CRSpline to BezQuad 2 Answers
3D Text to follow a path; iTween 0 Answers