• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by alexander11 · Aug 15, 2016 at 07:42 AM · c#unity 5instantiate3dspline

I'm having a few issues with (Catmull)Splines that i need help with.

Hello i am trying to implement 3 things into my spline that i need help with.

(1) As you can see in Pic1 there is a missing cube at the Control Points along the spline. How do i fix the missing cubes on the spline?

-Pic1 alt text


(2) How do i change the Segment count as you can see in Pic2(SEG1)there is 9 yellow dots in between two points. How do i Increase/Decrease the amount of yellow dots?

(3) How do i have the Cubes follow the Tangent points after instantiating them(See Pic2(SEG2) to see what i mean)? -Pic2 alt text

And here is the code so you know what i have done.

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class Catmull : MonoBehaviour {
 
     public List<Transform> controlPointsList = new List<Transform>();
 
     public bool isLooping = true;
 
     public GameObject obj;
     Vector3 p0;
     Vector3 p1;
     Vector3 p2;
     Vector3 p3;
 
     void Start()
     {
         for(int i = 0; i < controlPointsList.Count; i++)
         Object(i);
     }
     void OnDrawGizmos()
     {
         for (int i = 0; i < controlPointsList.Count; i++)
         {
             //Cant draw between the endpoints
             //Neither do we need to draw from the second to the last endpoint
             //...if we are not making a looping line
             if ((i == 0 || i == controlPointsList.Count - 2 || i == controlPointsList.Count - 1) && !isLooping)
             {
                 continue;
             }
 
             DisplayCatmullRomSpline(i);
         }
         Gizmos.color = Color.white;
 
         //Draw a sphere at each control point
         for (int i = 0; i < controlPointsList.Count; i++)
         {
             Gizmos.DrawWireSphere(controlPointsList[i].position, 0.3f);
         }
     }
     Vector3 ReturnCatmullRom(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
     {
         Vector3 a = 0.5f * (2f * p1);
         Vector3 b = 0.5f * (p2 - p0);
         Vector3 c = 0.5f * (2f * p0 - 5f * p1 + 4f * p2 - p3);
         Vector3 d = 0.5f * (-p0 + 3f * p1 - 3f * p2 + p3);
 
         Vector3 pos = a + (b * t) + (c * t * t) + (d * t * t * t);
 
         return pos;
     }
 
     void DisplayCatmullRomSpline(int pos)
     {
         //Clamp to allow looping
         p0 = controlPointsList[ClampListPos(pos - 1)].position;
         p1 = controlPointsList[pos].position;
         p2 = controlPointsList[ClampListPos(pos + 1)].position;
         p3 = controlPointsList[ClampListPos(pos + 2)].position;
 
 
         //Just assign a tmp value to this
         Vector3 lastPos = Vector3.zero;
 
         //t is always between 0 and 1 and determines the resolution of the spline
         //0 is always at p1
         for (float t = 0; t < 1; t += 0.1f)
         {
             //Find the coordinates between the control points with a Catmull-Rom spline
             Vector3 newPos = ReturnCatmullRom(t, p0, p1, p2, p3);
 
             //Cant display anything the first iteration
             if (t == 0)
             {
                 lastPos = newPos;
                 continue;
             }
 
             Gizmos.color = Color.white;
             Gizmos.DrawLine(lastPos, newPos);
 
             Gizmos.color = Color.yellow;
             var tan = ReturnCatmullRomTangent(t, p0, p1, p2, p3);
             Gizmos.DrawLine(newPos, newPos + tan * 3);
             Gizmos.DrawSphere(newPos, 0.3f);
             lastPos = newPos;
         }
 
         //Also draw the last line since it is always less than 1, so we will always miss it
         Gizmos.DrawLine(lastPos, p2);
     }
 
 
     //Clamp the list positions to allow looping
     //start over again when reaching the end or beginning
     int ClampListPos(int pos)
     {
         if (pos < 0)
         {
             pos = controlPointsList.Count - 1;
         }
 
         if (pos > controlPointsList.Count)
         {
             pos = 1;
         }
         else if (pos > controlPointsList.Count - 1)
         {
             pos = 0;
         }
 
         return pos;
     }
     public Vector3 ReturnCatmullRomTangent(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
     {
         Vector3 b = 0.5f * (p2 - p0);
         Vector3 c = (2f * p0 - 5f * p1 + 4f * p2 - p3);
         Vector3 d = 1.5f * (-p0 + 3f * p1 - 3f * p2 + p3);
         Vector3 tangent = b + c * t + d * t * t;
         return tangent.normalized;
     }
     void Object(int pos)
     {
         p0 = controlPointsList[ClampListPos(pos - 1)].position;
         p1 = controlPointsList[pos].position;
         p2 = controlPointsList[ClampListPos(pos + 1)].position;
         p3 = controlPointsList[ClampListPos(pos + 2)].position;
 
         Vector3 lastPos = Vector3.zero;
 
         for (float t = 0; t < 1; t += 0.1f)
         {
 
             Vector3 newPos = ReturnCatmullRom(t, p0, p1, p2, p3);
 
             if (t == 0)
             {
                 lastPos = newPos;
                 continue;
             }
 
 
             var tan = ReturnCatmullRomTangent(t, p0, p1, p2, p3);
             Instantiate(obj, newPos, Quaternion.LookRotation(tan));
             lastPos = newPos;
         }
     }
 }


@Bunny83

capture16.png (31.3 kB)
capture19.png (72.3 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Bunny83 · Aug 15, 2016 at 11:55 AM

First of all i moved this question to the help room. This question is no longer a general Unity question but a specific debugging / general help question. If you have further questions like this you should post them in the Help Room. If you don't know what i'm talking about you might want to have a look at the user guide of this site.

Well this question finally tells me you haven't understood (or even read?) the code you've copied at all. In line "92" of your posted code there's a comment. It specifically draws the last segment.

How many points are generated is controlled by the for loop in line 70 (and line 134). It goes from 0 to 1 at a step size of "0.1". Therefore you get 10 points along one segment.

I'm not sure what you made p0 to p3 member variables of the class. They should be local variables as you don't need / should store them outside of each method.

The way the original code draws the lines is a bit "clumsy". If you want a certain point count it's better to use an int variable that iterates through the point count you want and inside the loop you calculate the required "t" value. Also in the "drawing code" you need two points at the same time to be able to draw a line between them. In your object placement you only need a single point / tangent at a time:

 void PlaceObjectsOnSegment(int pos, int segCount)
 {
     Vector3 p0 = controlPointsList[ClampListPos(pos - 1)].position;
     Vector3 p1 = controlPointsList[pos].position;
     Vector3 p2 = controlPointsList[ClampListPos(pos + 1)].position;
     Vector3 p3 = controlPointsList[ClampListPos(pos + 2)].position;

     for (int i = 0; i < segCount; i++)
     {
         float t = (float)i / segCount;
         Vector3 newPos = ReturnCatmullRom(t, p0, p1, p2, p3);
         var tan = ReturnCatmullRomTangent(t, p0, p1, p2, p3);
         Instantiate(obj, newPos, Quaternion.LookRotation(tan));
     }
 }

The segCount parameter controls how many object you want to place between two control points.

I'm not sure if i got your last question right. If you want the objects once instantiated follow their respective points on the spline when the spline changes, you're getting in trouble with your current approach. First of all at the moment you don't store any references to your instantiated objects. So there's no way to identify a particular instance. You have to create an array where you store the Transforms of each object you create so you can "replace" them. For this it would be easier to have the code in a single method with a nested loop:

 public int objCountPerSeg = 10;
 private Transform[] objects;

 void CreateObjects()
 {
     // calculate the total object count we need
     int objectCount = controlPointsList.Count * objCountPerSeg;
     // create an array that can hold all objects we need.
     objects = new Transform[objectCount];
     for (int i = 0; i < objectCount; i++)
     {
         // Make sure you declared "obj" as "public Transform obj;" at the top.
         objects[i] = Instantiate(obj);
     }
     PlaceObjecsOnSpline();
 }

 void PlaceObjecsOnSpline()
 {
     for (int i = 0; i < controlPointsList.Count; i++)
     {
         Vector3 p0 = controlPointsList[ClampListPos(i - 1)].position;
         Vector3 p1 = controlPointsList[i].position;
         Vector3 p2 = controlPointsList[ClampListPos(i + 1)].position;
         Vector3 p3 = controlPointsList[ClampListPos(i + 2)].position;

         for (int n = 0; n < objCountPerSeg; n++)
         {
             float t = (float)n / objCountPerSeg;
             Vector3 newPos = ReturnCatmullRom(t, p0, p1, p2, p3);
             Vector3 tan = ReturnCatmullRomTangent(t, p0, p1, p2, p3);
             Transform inst = objects[i * objCountPerSeg + n];
             inst.position = newPos;
             inst.rotation = Quaternion.LookRotation(tan);
         }
     }
 }

You would call "CreateObjects()" once in Start to create all the objects and simply call "PlaceObjecsOnSpline()" whenever you want to update their positions.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.



Follow this Question

Answers Answers and Comments

227 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How do i Instantiate sub-Points with in Multiple Points?? 0 Answers

How do i have game object in the middle of a Catmull spline? 0 Answers

How do I Instantiate a prefab at the x axis position of where the UI button was clicked 1 Answer

How do i create Tangents on a spline?? 0 Answers

How do i calculate mesh on a spline?? 0 Answers

  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges