• 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 /
This question was closed Sep 02, 2015 at 12:55 PM by Rafael-Barbosa for the following reason:

The question is answered, right answer was accepted

avatar image
0
Question by Rafael-Barbosa · Aug 29, 2015 at 04:17 PM · c#cameraitweenitween path

Itween path, how to find the closest point to the player/Vector3

Hey there,

I'm currently trying to create a system where the camera follows the player along a path. Basically I have created a 3D path using Itween where the camera should find the closest point towards the player along that path and stick to it. How could this be done? I was able to make the camera stick to a porcentage of the path but have no idea how to make that porcentage be equal to the closes point towards the player.

I'm currently scripting in C#.

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

2 Replies

  • Sort: 
avatar image
1
Best Answer

Answer by _Gkxd · Aug 29, 2015 at 04:28 PM

This page lists a function called PointOnPath which essentially gives you a parametric equation describing that path.

What you can do using this is sample the path at multiple parts, and keep track of the distance that is the minimum. (This is pseudocode because I don't know how paths are structured in iTween.)

 float minDistance = float.PositiveInfinity;
 float minPercent = 0;
 
 for (float t = 0; t <= 1; t += 0.02f) {
     float dist = Vector3.Distance(playerPosition, PointOnPath(/* path */, t));
     if (dist < minDistance) {
         minDistance = dist;
         minPercent = t;
     }
 }

This will give you an approximation of the closest distance and the percent along the path that corresponds to it. For most purposes, an approximation like this should be good enough.

Comment
Add comment · Show 3 · 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
avatar image Rafael-Barbosa · Aug 30, 2015 at 01:22 AM 0
Share

Hey there, I have tryed what you said and it kind of worked. It does follow the player a bit , but it's very buggy and laggy. It also doesn't work quite well and at curves it doesn't work at all, I guess because of the fact that it 's close to more than one point.

here is the code :

 using UnityEngine;
 using System.Collections;
 
 public class FollowCameraPath : $$anonymous$$onoBehaviour {
 
     public GameObject Path;
     public float PathValue;
     public GameObject Player;
     float minDistance = float.PositiveInfinity;
     float minPercent = 0;
 
     // Use this for initialization
     void Update () {
 
         //iTween.$$anonymous$$oveTo( Path ,iTween.Hash("path" , iTweenPath.GetPath("CameraPath"), "time" , 200 ));
 
         for (float t = 0; t <= 1; t += 0.001f) {
             float dist = Vector3.Distance (Player.transform.position, iTween.PointOnPath (iTweenPath.GetPath("CameraPath" ), t));
             if (dist < minDistance) {
                 minDistance = dist;
                 minPercent = t;
             }
         }
         iTween.PutOnPath(this.gameObject, iTweenPath.GetPath("CameraPath"), minPercent);
     }
 }
 
avatar image _Gkxd · Aug 30, 2015 at 02:21 AM 0
Share

In general, finding a point on a path that is closest to another point not an easy thing to do, especially if the path is arbitrary. For straight lines, you can just solve an equation to get the closest point, but for more complicated paths, there's no easy equation to solve, and there might be multiple points that are the "closest" to a point (like a point in the middle of a circular path). This is why you need to sample points along the path to actually find the minimum. You may be able to use Newton's method as a faster way of finding the closest point, but again, this will only work for certain paths (and it's more complicated to implement).

It may be the implementation of the iTween libraries that are slow too. You can use the profiler in Unity to see which functions take the most time to execute.

It will also help if you describe what the bugs are, ins$$anonymous$$d of just saying that there are bugs, though if the issue is from iTween, I may not be able to help.

avatar image EvilTak · Aug 30, 2015 at 10:27 AM 0
Share

This code lags because you are performing 50 sqrt operations every frame! Look at my answer below for a much much more optimized version.

avatar image
1

Answer by EvilTak · Aug 30, 2015 at 10:26 AM

Modifying @_Gkxd 's answer, you can use a (much much much much) more optimized version of it as follows:

 for (float t = 0; t <= 1; t += 0.005f) {
              float dist = (Player.transform.position - iTween.PointOnPath (iTweenPath.GetPath("CameraPath" ), t)).sqrMagnitude;
              if (dist < minDistance) {
                  minDistance = dist;
                  minPercent = t;
              }
          }

I'm using sqrMagnitude here because we're just comparing distances, and we don't actually need the actual distance so we can avoid the expensive Sqrt operation which @_Gkxd was performing 20 times (you were doing it 1000 times!!!) every frame in his code - of course it'll be laggy! You might have noticed I've also increased the step value in the loop to 0.005, which depending on the length of your path can be increased more. If it is a long path, you don't need a high step value, but if it's a short one, you might want to keep a smaller step.

Comment
Add comment · Show 2 · 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
avatar image Rafael-Barbosa · Aug 30, 2015 at 12:57 PM 0
Share

Didn't quite work, about the laggy part, I didn't meant FPS , I think I didn't quite clarify on that part. The actual camera movement is laggy as it is almost as if it was sticking to some parts of the path . The buggy part is that it doesn't really flow from the start to the end, it in someparts stops and then grabs to a further away part.

avatar image _Gkxd · Aug 30, 2015 at 04:19 PM 1
Share

@Rafael Barbosa
It's pretty difficult to see what the problem could be if you don't show us the path that you're using. Depending on what your path is, the situation that you're describing could be the correct behavior.

@Evil Tak
I wouldn't say that it's that much more optimized. It is faster code, but it's not clear that the reason for the lag is using the square root function. It may be some other bottleneck in the code that causes a slowdown.

Here is some test code that I used.

 public class SqrtTest : $$anonymous$$onoBehaviour {
     void Update () {
         A();
         B();
     }
 
     void A() {
         for (float i = 0; i < 1; i += 0.001f) {
             float a = Vector3.Sqr$$anonymous$$agnitude(Vector3.one * i);
         }
     }
 
     void B() {
         for (float i = 0; i < 1; i += 0.001f) {
             float a = Vector3.Distance(Vector3.zero, Vector3.one * i);
         }
     }
 }

I ran the above code using the deep profiler. Here are the results:
alt text

The second column from the right is the amount of milliseconds that it takes to run that function.

Do note that the deep profiler does use a significant amount of resources. Here is the time of the update function with the deep profiler disabled:
alt text

So running each operation 1000 times per frame only takes 0.3-0.4 milliseconds each frame, which shouldn't have a large impact. It is something to consider when your resources are limited, but it shouldn't be the main problem at this point.

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

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Multiple Cars not working 1 Answer

Camera animation using EasyTouch's swipe and iTween 1 Answer

Distribute terrain in zones 3 Answers

Switching Between (many) different iTween Paths (C#) 0 Answers

iTween, I need a Sharp movement between points on an iTween path 0 Answers

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