- Home /
 
Camera Follow Player using a path
Hi, it is been a while that I don't come here, so I need you help with a question about a code that I trying to implement for the past 2 weeks. I saw a lot of tutorials and tryed a lot of things but I am not a code expert. I have this first code that I learned in this tutorial.
https://www.youtube.com/watch?v=B3LYJINnYtE&t=651s
 public Transform[] nodes;
     private int nodeCount;
     public int nearstnode;
 
 
     // Use this for initialization
     private void Start () {
 
         nodeCount = transform.childCount;
         nodes = new Transform[nodeCount];
 
         for (int i = 0; i < nodeCount - 1; i++) {
             nodes [i] = transform.GetChild (i);
         }
 
     }
     
     // Update is called once per frame
     private void Update () {
         if (nodeCount > 1) {
             for (int i = 0; i < nodeCount - 1; i++) {
                 Debug.DrawLine (nodes[i].position, nodes[i+1].position, Color.green);
             }
         }
     }
 
     public Vector3 ProjectPositionOnRail(Vector3 pos){
         int ClosestNodeIndex = GetClosestNode(pos);
         if (ClosestNodeIndex == 0) {
             return ProjectOnSegment (nodes [0].position, nodes [1].position, pos);
         } else if (ClosestNodeIndex == nodeCount - 1) {
             return ProjectOnSegment (nodes [nodeCount-1].position, nodes [nodeCount-2].position, pos);
         } else {
             Vector3 LeftSeg = ProjectOnSegment (nodes [ClosestNodeIndex - 1].position , nodes [ClosestNodeIndex].position, pos);
             Vector3 RightSeg = ProjectOnSegment (nodes [ClosestNodeIndex + 1].position, nodes [ClosestNodeIndex].position, pos);
             Debug.DrawLine (pos, LeftSeg, Color.red);
             Debug.DrawLine (pos, RightSeg, Color.blue);
 
             if ((pos - LeftSeg).sqrMagnitude <= (pos - RightSeg).sqrMagnitude) {
                 return LeftSeg;
             } else {
                 return RightSeg;
             }
         }
     }
 
     private int GetClosestNode(Vector3 pos){
         int ClosestNodeIndex = -1;
         float ShortestDistance = 0.0f;
         for (int i = 0; i < nodeCount; i++) {
             float sqrDistance = (nodes [i].position - pos).sqrMagnitude;
             if (ShortestDistance == 0.0f || sqrDistance < ShortestDistance) {
                 ShortestDistance = sqrDistance;
                 ClosestNodeIndex = i;
             }
         }
         nearstnode = ClosestNodeIndex;
         return ClosestNodeIndex;
     }
 
     public Vector3 ProjectOnSegment(Vector3 v1, Vector3 v2, Vector3 pos){
         Vector3 v1ToPos = pos - v1;
         Vector3 segDirection = (v2 - v1).normalized;
         float DistanceFromV1 = Vector3.Dot (segDirection, v1ToPos);
         if (DistanceFromV1 < 0.0f) {
             return v1;
         } else if (DistanceFromV1 * DistanceFromV1 > (v2 - v1).sqrMagnitude) {
             return v2;
         } else {
             Vector3 fromV1 = segDirection * DistanceFromV1;
             return v1 + fromV1;
         }
     }
 
               and the code to control the camera along this rail:
 public SCRIPTS_CameraRail Rail;
     public Transform Player;
     public float MoveSpeed = 5.0f;
     public Transform thisTransform;
     public Vector3 LastPosition;
 
     // Use this for initialization
     private void Start () {
         thisTransform = transform;
         LastPosition = thisTransform.position;
 
     }
 
     // Update is called once per frame
     private void Update () {
 
 
     
         LastPosition = Vector3.Lerp (LastPosition, Rail.ProjectPositionOnRail (Player.position), Time.deltaTime * MoveSpeed);
         thisTransform.position = LastPosition;
 
     }
 
               this is a pretty god system but I was trying to make this rail becomes smoother with curves, so I saw this tutorial: https://www.youtube.com/watch?v=Xwj8_z9OrFw&t=548s and tryed to implement the curve calculation in the rail system, the math works pretty fine, but I never figured out how to implement the calculation in the rail system code.
some weeks later I found this tutorial: https://www.youtube.com/watch?v=URqjHIz6pts&t=1594s
and implemented the code:
 public Transform[] nodes;
     private int nodeCount;
 
     // Use this for initialization
     void Start () {
         
         nodeCount = transform.childCount;
         nodes = new Transform[nodeCount];
 
         for (int i = 0; i < nodeCount; i++) {
             nodes [i] = transform.GetChild (i);
         }
         
     }
     
     // Update is called once per frame
     void Update () {
 
     
         
     }
 
     public Vector3 LinearPosition(int seg, float ratio){
         Vector3 p1 = nodes [seg].position;
         Vector3 p2 = nodes [seg + 1].position;
 
         return Vector3.Lerp (p1, p2, ratio);
     }
 
 
     public Vector3 CatmullPosition(int seg, float ratio){
 
         Vector3 p1, p2, p3, p4;
 
         if (seg == 0) {
             p1 = nodes [seg].position;
             p2 = p1;
             p3 = nodes [seg + 1].position;
             p4 = nodes [seg + 2].position;
         } else if (seg == nodes.Length - 2) {
             p1 = nodes [seg - 1].position;
             p2 = nodes [seg].position;
             p3 = nodes [seg + 1].position;
             p4 = p3;
         } else {
             p1 = nodes [seg - 1].position;
             p2 = nodes [seg].position;
             p3 = nodes [seg + 1].position;
             p4 = nodes [seg + 2].position;
         }
 
         float t2 = ratio * ratio;
         float t3 = t2 * ratio;
 
         float x = 0.5f * ((2.0f * p2.x)
             + (-p1.x + p3.x) 
             * ratio    + (2.0f * p1.x - 5.0f * p2.x + 4 * p3.x - p4.x)
             * t2 + (-p1.x + 3.0f * p2.x - 3.0f * p3.x + p4.x)
             * t3);
 
         float y = 0.5f * ((2.0f * p2.y)
             + (-p1.y + p3.y)
             * ratio + (2.0f * p1.y - 5.0f * p2.y + 4 * p3.y - p4.y)
             * t2 + (-p1.y + 3.0f * p2.y - 3.0f * p3.y + p4.y)
             * t3);
 
         float z = 0.5f * ((2.0f * p2.z)
             + (-p1.z + p3.z)
             * ratio + (2.0f * p1.z - 5.0f * p2.z + 4 * p3.z - p4.z)
             * t2 + (-p1.z + 3.0f * p2.z - 3.0f * p3.z + p4.z)
             * t3);
 
         return new Vector3 (x, y, z);
     }
 
     public Quaternion Orientation(int seg, float ratio){
 
         Quaternion q1 = nodes [seg].rotation;
         Quaternion q2 = nodes [seg + 1].rotation;
 
         return Quaternion.Lerp (q1, q2, ratio);
     }
 
               and the camera controller:
 public SCRIPTS_CameraRail2 Rail;
     public Transform PlayerTransform;
 
     public int currentSeg;
     private float transition;
     private bool isCompleted;
     public float PlayerToNode1Distance, PlayerToNode2Distance, NodeDistance, d;
     public Vector3 Line, LineStart, LineEnd, Point, Dir;
 
 
     // Update is called once per frame
     void Update () {
         if (!Rail) {
             return;
         }
         if (!isCompleted) {
             Play ();
         }
     }
 
     private void Play(){
         
 
         transition += Time.deltaTime * 1 /2.5f;
         if (transition > 1) {
             transition = 0;
             currentSeg++;
         }else if(transition < 0){
             transition = 1;
             currentSeg--;
         }
         transform.position = Rail.CatmullPosition (currentSeg, transition);
         transform.rotation = Rail.Orientation (currentSeg, transition);
     }
 
               In this second code I know that I need to change the transition value to move the camera, but dont know how to make this happen based on the player position.
So I have one code that moves based on the players position but have no curves, and a second code that move with curves but dont move based on the players position. how can I make this 2 things in only one code? move based on players position true the rail with curves to make the camera movement smoother.
thanks for any help!
Your answer