Search Unity

Object following a path

Discussion in 'Editor & General Support' started by skyhawk, Jun 15, 2006.

  1. skyhawk

    skyhawk

    Joined:
    Jun 13, 2005
    Posts:
    49
    scenario: I'm doing a shmup
    problem: I want my camera to follow a set path through a 3D environment

    so how do I draw such a path for it to follow and set my camera and "invisible stopping boundaries" (so you can't fly off screen) to follow it.
     
  2. podperson

    podperson

    Joined:
    Jun 6, 2006
    Posts:
    1,371
    The scripting tutorial shows you how to get cars to drive between waypoints, which is similar to what you want your camera to do.

    If you're doing a "virtua cop" style game you could pretty much animate the camera (or its parent) using the animation timeline (i.e. give the user some kind of mouselook to point the camera) while moving the camera itself along a fixed path at a fixed rate.
     
  3. AaronC

    AaronC

    Joined:
    Mar 6, 2006
    Posts:
    3,552
    Maybe you could set up a bunch of cubes as box colliders with the materials set to none(so they are invisible)down each side of your track? Make em heavy as, with perhaps a bit of bouncy so you get nudged back to the centre of the path?
    I am a bit of a novice, so dont let me make life harder for you
     
  4. jeremyace

    jeremyace

    Joined:
    Oct 12, 2005
    Posts:
    1,661
    Path following isn't really that hard to do. If you look up the Seek and Arrive Steering behaviours (AI code, but simple), you can use those and just maintain an array of "node" positions which you can either generate at runtime, or if you like torture, type them all out by hand.

    You then Seek towards the waypoint until you are within a radius of it, then you move to the next waypoint. At the last waypoint you use the Arrive behaviour (slows down and stops when it gets within the radius).

    By using steering behaviours, you can smooth the motion by setting limits for speed, and more importantly, turning radius.

    HTH,
    -Jeremy
     
  5. thylaxene

    thylaxene

    Joined:
    Oct 10, 2005
    Posts:
    716
    Just as an aside. Does anyone have any good reference sites that have example code for these type of AI behaviours? In pseudo code or generic C would be great. Or recommend any books on the subject?

    cheers.
     
  6. Morgan

    Morgan

    Joined:
    May 21, 2006
    Posts:
    1,223
    Does that work? With "none" I get a black and red object. So for invisible I had to make an empty (black) alpha channel image.
     
  7. AaronC

    AaronC

    Joined:
    Mar 6, 2006
    Posts:
    3,552
    Um yeah I thought so...
    Im not at my unity machine for a few days so will have to check...Am pretty sure...Under the mesh render tab(Sorry I cant help accurately for a few days)
    AC
     
  8. Morgan

    Morgan

    Joined:
    May 21, 2006
    Posts:
    1,223
    OK--chosing "none" from the list didn't work to make an invisible object, but choosing Remove Component at the right side did.

    (In fact, the object is then so invisible you can't even see it when selected, not even in wireframe.)
     
  9. jeremyace

    jeremyace

    Joined:
    Oct 12, 2005
    Posts:
    1,661
    To make any object invisible in the game, remove it's renderer component from the inspector.

    As for the steering behaviour code, here are Seek and Arrive in C#
    Code (csharp):
    1.  
    2. //------------ Seek(GameObject target) ----------------
    3. // Returns a velocity that points to and moves towards
    4. // the target at a constant max speed
    5. //-----------------------------------------------------
    6. public Vector3 Seek(GameObject target){
    7.     Vector3 tempDir = target.transform.position - transform.position;
    8.     steeringVelocity = tempDir.normalized * maxSpeed;
    9.  
    10. return steeringVelocity;
    11. }
    12.  

    Code (csharp):
    1.  
    2. //--------------- Arrive(GameObject target) -----------------
    3. // Moves toward target but will slow down
    4. // (set by deceleration var) as it gets close and will finally
    5. // stop at stopPoint.
    6. //-----------------------------------------------------------
    7. public Vector3 Arrive(GameObject target){
    8.     Vector3 direction = target.transform.position - transform.position;
    9.     float distanceToTarget = Vector3.Distance(transform.position, target.transform.position) - stopPoint;
    10.  
    11.       if (distanceToTarget <= 0.0){
    12.         steeringVelocity = Vector3.zero;
    13.       }
    14.       else {
    15.             float speed = distanceToTarget / deceleration;  // apply deceleration to our speed
    16.            speed = Mathf.Min(speed, maxSpeed);              // make sure our speed doesn't exceed max        
    17.            steeringVelocity = direction.normalized * speed;
    18.           }
    19.  
    20. return steeringVelocity;
    21. }
    22.  
    Now all that code does in calculate and return a velocity vector for that frame (you call them every frame that you want them to compute). I obviously left out some variable declarations, but I figure you are going to convert this to JS anyway.

    Now, to move your object you have two choices. If you object has a rigidbody, you can use this code to move it using the steering behaviour
    Code (csharp):
    1.  
    2. int Locomotion(Vector3 velocity){
    3.     targetRotation = Quaternion.LookRotation(velocity.normalized);
    4.     str = Mathf.Min(rotationSpeed * Time.deltaTime, 1);
    5.     transform.rotation = Quaternion.Slerp (transform.rotation, targetRotation, str);
    6.     rigidbody.velocity = transform.TransformDirection(Vector3.forward) * (velocity.magnitude);
    7.  
    8. return 0;
    9. }
    10.  
    You just call it (in C#) every frame like this:
    Locomotion(Seek(target));

    But, if you dont have a rigidbody attached you obviously cant move it with rigidbody.velocity, so you use this formula to apply velocity on your own:
    Code (csharp):
    1.  
    2. //use this formula to apply velocity
    3. position += velocity * Time.deltaTime;
    4.  
    5. //so the rigidbody line above becomes:
    6. transform.position += (transform.TransformDirection(Vector3.forward) * (velocity.magnitude)) * Time.deltaTime;
    7.  
    The locomotion code will slowly turn towards the next target, therefore providing some smoothing.

    HTH,
    -Jeremy