Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only. On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live. Read our full announcement for more information and let us know if you have any questions.

WOW Camera Movement

Discussion in 'Scripting' started by matrix211v1, Jan 20, 2009.

  1. sandolkakos

    sandolkakos

    Joined:
    Jun 3, 2009
    Posts:
    286
    Already heppened flickerings with me too, but now dont have more problems.
    Look my Configurations:




    Script used:
    Code (csharp):
    1.  
    2. // WowCamera.cs
    3. // by Synthetique - [url]http://forum.unity3d.com/viewtopic.php?p=278801#278801[/url]
    4.  
    5. using UnityEngine;
    6. using System.Collections;
    7.  
    8. public class WowCamera : MonoBehaviour
    9. {
    10.     public Transform target;
    11.    
    12.     public float targetHeight = 1.7f;
    13.     public float distance = 5.0f;
    14.     public float offsetFromWall = 0.1f;
    15.  
    16.     public float maxDistance = 20;
    17.     public float minDistance = .6f;
    18.     public float speedDistance = 5;
    19.  
    20.     public float xSpeed = 200.0f;
    21.     public float ySpeed = 200.0f;
    22.  
    23.     public int yMinLimit = -40;
    24.     public int yMaxLimit = 80;
    25.  
    26.     public int zoomRate = 40;
    27.  
    28.     public float rotationDampening = 3.0f;
    29.     public float zoomDampening = 5.0f;
    30.    
    31.     public LayerMask collisionLayers = -1;
    32.  
    33.     private float xDeg = 0.0f;
    34.     private float yDeg = 0.0f;
    35.     private float currentDistance;
    36.     private float desiredDistance;
    37.     private float correctedDistance;
    38.  
    39.     void Start ()
    40.     {
    41.         Vector3 angles = transform.eulerAngles;
    42.         xDeg = angles.x;
    43.         yDeg = angles.y;
    44.  
    45.         currentDistance = distance;
    46.         desiredDistance = distance;
    47.         correctedDistance = distance;
    48.  
    49.         // Make the rigid body not change rotation
    50.         if (rigidbody)
    51.             rigidbody.freezeRotation = true;
    52.     }
    53.    
    54.     /**
    55.      * Camera logic on LateUpdate to only update after all character movement logic has been handled.
    56.      */
    57.     void LateUpdate ()
    58.     {
    59.         Vector3 vTargetOffset;
    60.        
    61.        // Don't do anything if target is not defined
    62.         if (!target)
    63.             return;
    64.  
    65.         // If either mouse buttons are down, let the mouse govern camera position
    66.         if (GUIUtility.hotControl == 0) {
    67.             if (Input.GetMouseButton(0) || Input.GetMouseButton(1))
    68.             {
    69.                 xDeg += Input.GetAxis ("Mouse X") * xSpeed * 0.02f;
    70.                 yDeg -= Input.GetAxis ("Mouse Y") * ySpeed * 0.02f;
    71.             }
    72.        
    73.         // otherwise, ease behind the target if any of the directional keys are pressed
    74.             else if (Input.GetAxis("Vertical") != 0 || Input.GetAxis("Horizontal") != 0)
    75.             {
    76.                 float targetRotationAngle = target.eulerAngles.y;
    77.                 float currentRotationAngle = transform.eulerAngles.y;
    78.                 xDeg = Mathf.LerpAngle (currentRotationAngle, targetRotationAngle, rotationDampening * Time.deltaTime);
    79.             }
    80.         }
    81.        
    82.  
    83.         // calculate the desired distance
    84.         desiredDistance -= Input.GetAxis ("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs (desiredDistance) * speedDistance;
    85.         desiredDistance = Mathf.Clamp (desiredDistance, minDistance, maxDistance);
    86.  
    87.         yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
    88.        
    89.         // set camera rotation
    90.         Quaternion rotation = Quaternion.Euler(yDeg, xDeg, 0);
    91.         correctedDistance = desiredDistance;
    92.  
    93.         // calculate desired camera position
    94.         vTargetOffset = new Vector3 (0, -targetHeight, 0);
    95.         Vector3 position = target.position - (rotation * Vector3.forward * desiredDistance + vTargetOffset);
    96.  
    97.         // check for collision using the true target's desired registration point as set by user using height
    98.         RaycastHit collisionHit;
    99.         Vector3 trueTargetPosition = new Vector3(target.position.x, target.position.y, target.position.z) - vTargetOffset;
    100.  
    101.         // if there was a collision, correct the camera position and calculate the corrected distance
    102.         bool isCorrected = false;
    103.         if (Physics.Linecast (trueTargetPosition, position, out collisionHit, collisionLayers.value))
    104.         {
    105.             // calculate the distance from the original estimated position to the collision location,
    106.             // subtracting out a safety "offset" distance from the object we hit.  The offset will help
    107.             // keep the camera from being right on top of the surface we hit, which usually shows up as
    108.             // the surface geometry getting partially clipped by the camera's front clipping plane.
    109.             correctedDistance = Vector3.Distance (trueTargetPosition, collisionHit.point) - offsetFromWall;
    110.             isCorrected = true;
    111.         }
    112.  
    113.         // For smoothing, lerp distance only if either distance wasn't corrected, or correctedDistance is more than currentDistance
    114.         currentDistance = !isCorrected || correctedDistance > currentDistance ? Mathf.Lerp (currentDistance, correctedDistance, Time.deltaTime * zoomDampening) : correctedDistance;
    115.  
    116.         // keep within legal limits
    117.         currentDistance = Mathf.Clamp (currentDistance, minDistance, maxDistance);
    118.  
    119.         // recalculate position based on the new currentDistance
    120.         position = target.position - (rotation * Vector3.forward * currentDistance + vTargetOffset);
    121.        
    122.         transform.rotation = rotation;
    123.         transform.position = position;
    124.     }
    125.  
    126.     private static float ClampAngle (float angle, float min, float max)
    127.     {
    128.         if (angle < -360)
    129.             angle += 360;
    130.         if (angle > 360)
    131.             angle -= 360;
    132.         return Mathf.Clamp (angle, min, max);
    133.     }
    134. }
    135.  
    136.  
     
    Deleted User likes this.
  2. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    Thanks for the tip sandolkakos, I had a feeling that it had to do with the pivot point. I will have to try your tip and see if it helps. Thanks again!
     
  3. sandolkakos

    sandolkakos

    Joined:
    Jun 3, 2009
    Posts:
    286
    and dont forgot of Collision Layers.
    Unselect the Player Layer.
     
  4. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    Hey sandolkakos, the issue with my code was definitely the collision layers. So that problem is fixed now, but I have a new one. I am using your code that you provided, and im trying to convert it to javascript but im getting weird behavior issues.

    Whenever the camera is colliding with something, it bounces back and forth every frame, and I cannot figure out what I have done wrong.

    I am assuming a value is not getting set correctly between frames and it keeps trying to reset to the desiredDistance?

    Here is my function, it gets called from the LateUpdate() function:

    Code (csharp):
    1.  
    2. function Start()
    3. {
    4.     var angles = transform.eulerAngles;
    5.     cameraAngleX = angles.y;
    6.     cameraAngleY = angles.x;
    7.  
    8.     // Make the rigid body not change rotation
    9.     if (rigidbody) rigidbody.freezeRotation = true;
    10.    
    11.     // Camera stuff added
    12.     currentDistance = cameraDistance;
    13.     desiredDistance = cameraDistance;
    14.     correctedDistance = cameraDistance;
    15. }
    16.  
    17. // CAMERA VARIABLES
    18. var playerCamera : Transform;
    19. var mask : LayerMask = -1;
    20. private var cameraSmoothing = 5;
    21. private var cameraHeight = 0.7;
    22. private var cameraDistance = 1.5;
    23. private var cameraMaxDistance = 10;
    24. private var cameraMinDistance = 0.5;
    25. private private private var cameraXSpeed = 250.0;
    26. private var cameraYSpeed = 120.0;
    27. private var cameraYMinLimit = -40;
    28. private var cameraYMaxLimit = 80;
    29. private var cameraZoomRate = 40;
    30. private var cameraRotationDampening = 3.0;
    31. private var cameraAngleX = 0.0;
    32. private var cameraAngleY = 0.0;
    33. private var currentDistance = 0.0;
    34. private var desiredDistance = 0.0;
    35. private var correctedDistance = 0.0;
    36. private var cameraSpeedDistance = 2;
    37.  
    38. function CameraCalculation()
    39. {
    40.     // If no camera is selected, don't do camera calculations
    41.     if(!playerCamera)
    42.         return;
    43.    
    44.     // If either mouse buttons are down, let them govern camera position
    45.     if (Input.GetMouseButton(0) || (Input.GetMouseButton(1)))
    46.     {
    47.         cameraAngleX += Input.GetAxis("Mouse X") * cameraXSpeed * 0.02;
    48.         cameraAngleY -= Input.GetAxis("Mouse Y") * cameraYSpeed * 0.02;
    49.     }
    50.    
    51.     // otherwise, ease behind the target if any of the directional keys are pressed
    52.     else if(Input.GetAxis("Vertical") || Input.GetAxis("Horizontal"))
    53.     {
    54.         var targetRotationAngle = transform.eulerAngles.y;
    55.         var currentRotationAngle = playerCamera.eulerAngles.y;
    56.         cameraAngleX = Mathf.LerpAngle(currentRotationAngle, targetRotationAngle, cameraRotationDampening * Time.deltaTime);
    57.     }
    58.  
    59.     desiredDistance -= (Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime) * cameraZoomRate * Mathf.Abs(desiredDistance) * cameraSpeedDistance;
    60.     desiredDistance = Mathf.Clamp(desiredDistance, cameraMinDistance, cameraMaxDistance);
    61.    
    62.     cameraAngleY = ClampAngle(cameraAngleY, cameraYMinLimit, cameraYMaxLimit);
    63.    
    64.     // ROTATE CAMERA:
    65.     var rotation:Quaternion = Quaternion.Euler(cameraAngleY, cameraAngleX, 0);
    66.     correctedDistance = desiredDistance;
    67.    
    68.     // POSITION CAMERA:
    69.     var position = transform.position - (rotation * Vector3.forward * desiredDistance + Vector3(0,-cameraHeight,0));
    70.    
    71.     // IS VIEW BLOCKED?
    72.     var hit : RaycastHit;
    73.     var trueTransformPosition : Vector3 = transform.position - Vector3(0,-cameraHeight,0);
    74.    
    75.     // Cast the line to check:
    76.     var isCorrected : boolean = false;
    77.     if (Physics.Linecast (trueTransformPosition, playerCamera.transform.position, hit, mask))
    78.     {
    79.         // If so, shorten distance so camera is in front of object:
    80.                
    81.         // Finally, reposition the camera
    82.         correctedDistance = Vector3.Distance (trueTransformPosition, hit.point) - 0.28;
    83.         isCorrected = true;
    84.    }
    85.    
    86.     // Smoothing
    87.     currentDistance = !isCorrected || correctedDistance > currentDistance ? Mathf.Lerp (currentDistance, correctedDistance, Time.deltaTime * cameraSmoothing) : correctedDistance;
    88.  
    89.            
    90.     // keep within legal limits
    91.     currentDistance = Mathf.Clamp (currentDistance, cameraMinDistance, cameraMaxDistance);
    92.  
    93.     // recalculate position based on the new currentDistance
    94.     position = transform.position - (rotation * Vector3.forward * currentDistance + Vector3(0,-cameraHeight,0));
    95.  
    96.     // Set the camera values
    97.     playerCamera.transform.rotation = rotation;
    98.     playerCamera.transform.position = position;
    99. }
    Any ideas as to what is causing the jumpiness?
     
  5. sandolkakos

    sandolkakos

    Joined:
    Jun 3, 2009
    Posts:
    286
    sorry Fishypants, but i am still very much beginner and i still cant know how fix this problem :(
     
  6. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    Alright, I figured it out. There error was on this line:

    Code (csharp):
    1. if (Physics.Linecast (trueTransformPosition, playerCamera.transform.position, hit, mask))
    It was checking against the current camera position, and thats not exactly what we want, you want to check against the desired position, or more specifically the "position" variable, which is set on this line:

    Code (csharp):
    1. var position = transform.position - (rotation * Vector3.forward * desiredDistance + Vector3(0,-cameraHeight,0));
    So when I change the code to this:
    Code (csharp):
    1. if (Physics.Linecast (trueTransformPosition, position, hit, mask))
    It works great! Thanks for the help sandolkakos. Once I clean up my code I will post my version of the movement script if anyone is interested.
     
  7. Osbor

    Osbor

    Joined:
    Mar 23, 2010
    Posts:
    120
    oh, you got it working? nice one bro, this is a cool movement system.
     
  8. Cor1312

    Cor1312

    Joined:
    Apr 12, 2010
    Posts:
    34
    Here's the C# port of Vimalakirti's script.

    I had to heavily modify the script for my own use so my sincere apologies if something here is broken.

    Massive props to Vimalakirti. Cheers man.

    Code (csharp):
    1. using UnityEngine;
    2. using System;
    3.  
    4. [RequireComponent(typeof(CharacterController))]
    5. class Controller : MonoBehaviour
    6. {
    7.     //Movement Variables:
    8.     private float jumpSpeed = 9.0f;
    9.     private float gravity = 20.0f;
    10.     private float runSpeed = 5.0f;
    11.     private float walkSpeed = 1.7f;
    12.     private float rotateSpeed = 150.0f;
    13.     private bool grounded = false;
    14.     private Vector3 moveDirection = Vector3.zero;
    15.     private bool isWalking = true;
    16.     private String moveStatus = "idle";
    17.     private float xSpeed = 250.0f;
    18.     private float ySpeed = 120.0f;
    19.     private float yMinLimit = -40.0f;
    20.     private float yMaxLimit = 80.0f;
    21.     private float x = 0.0f;
    22.     private float y = 0.0f;
    23.  
    24.     void Update()
    25.     {
    26.         if (grounded)
    27.         {
    28.             moveDirection = new Vector3((Input.GetMouseButton(1) ? Input.GetAxis("Horizontal") : 0), 0, Input.GetAxis("Vertical"));
    29.  
    30.             // if moving forward and to the side at the same time, compensate for distance
    31.             // TODO: may be better way to do this?
    32.             if (Input.GetMouseButton(1)  Input.GetAxis("Horizontal") != 0  Input.GetAxis("Vertical") != 0)
    33.             {
    34.                 moveDirection *= 0.7f;
    35.             }
    36.  
    37.             moveDirection = transform.TransformDirection(moveDirection);
    38.             moveDirection *= isWalking ? walkSpeed : runSpeed;
    39.  
    40.             if (moveDirection != Vector3.zero)
    41.             {
    42.                 moveStatus = isWalking ? "walking" : "running";
    43.                 if (isWalking)
    44.                 {
    45.                     // invoke WALK animation here
    46.                 }
    47.                 else
    48.                 {
    49.                     // call RUN animation here
    50.                 }
    51.             }
    52.             else
    53.             {
    54.                 // call IDLE animation here
    55.             }
    56.             // Jump!
    57.             if (Input.GetButton("Jump"))
    58.             {
    59.                 // call JUMP animation here
    60.                 moveDirection.y = jumpSpeed;
    61.             }
    62.  
    63.             // Allow turning at anytime. Keep the character facing in the same direction as the Camera if the right mouse button is down.
    64.             if (Input.GetMouseButton(1))
    65.             {
    66.                 transform.rotation = Quaternion.Euler(0, Camera.main.transform.eulerAngles.y, 0);
    67.             }
    68.             else
    69.             {
    70.                 transform.Rotate(0, Input.GetAxis("Horizontal") * rotateSpeed * Time.deltaTime, 0);
    71.             }
    72.  
    73.             // Toggle walking/running with the T key
    74.             if (Input.GetKeyDown("t")) isWalking = !isWalking;
    75.  
    76.             //Apply gravity
    77.             moveDirection.y -= gravity * Time.deltaTime;
    78.             //Move controller
    79.             CharacterController controller = GetComponent<CharacterController>();
    80.             CollisionFlags flags = controller.Move(moveDirection * Time.deltaTime);
    81.             grounded = (flags  CollisionFlags.Below) != 0;
    82.         }
    83.     }
    84. }
    Code (csharp):
    1. using UnityEngine;
    2. using System;
    3.  
    4. [AddComponentMenu("Camera-Control/WoW Camera")]
    5. public class MyCamera : MonoBehaviour
    6. {
    7.     public Transform target;
    8.     public float targetHeight = 2.0f;
    9.     public float distance = 2.8f;
    10.     public float maxDistance = 10.0f;
    11.     public float minDistance = 0.5f;
    12.     public float xSpeed = 250.0f;
    13.     public float ySpeed = 120.0f;
    14.     public float yMinLimit = -40.0f;
    15.     public float yMaxLimit = 80.0f;
    16.     public float zoomRate = 20.0f;
    17.     public float rotationDampening = 3.0f;
    18.     private float x = 0.0f;
    19.     private float y = 0.0f;
    20.     public bool isTalking = false;
    21.  
    22.     void Start()
    23.     {
    24.         Vector3 angles = transform.eulerAngles;
    25.         x = angles.y;
    26.         y = angles.x;
    27.  
    28.         // Make the rigid body not change rotation
    29.         if (rigidbody) rigidbody.freezeRotation = true;
    30.     }
    31.  
    32.     void LateUpdate()
    33.     {
    34.         if (!target) return;
    35.  
    36.         // If either mouse buttons are down, let them govern camera position
    37.         if (Input.GetMouseButton(0) || (Input.GetMouseButton(1)))
    38.         {
    39.             x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
    40.             y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
    41.         }
    42.         // otherwise, ease behind the target if any of the directional keys are pressed
    43.         else if (Input.GetAxis("Vertical") != 0 || Input.GetAxis("Horizontal") != 0)
    44.         {
    45.             float targetRotationAngle = target.eulerAngles.y;
    46.             float currentRotationAngle = transform.eulerAngles.y;
    47.             x = Mathf.LerpAngle(currentRotationAngle, targetRotationAngle, rotationDampening * Time.deltaTime);
    48.         }
    49.  
    50.         distance -= (Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime) * zoomRate * Mathf.Abs(distance);
    51.         distance = Mathf.Clamp(distance, minDistance, maxDistance);
    52.  
    53.         y = ClampAngle(y, yMinLimit, yMaxLimit);
    54.  
    55.         // ROTATE CAMERA:
    56.         Quaternion rotation = Quaternion.Euler(y, x, 0);
    57.         transform.rotation = rotation;
    58.  
    59.         // POSITION CAMERA:
    60.         Vector3 position = target.position - (rotation * Vector3.forward * distance + new Vector3(0, -targetHeight, 0));
    61.         transform.position = position;
    62.  
    63.         // IS VIEW BLOCKED?
    64.         RaycastHit hit = new RaycastHit();
    65.         Vector3 trueTargetPosition = target.transform.position - new Vector3(0, -targetHeight, 0);
    66.         // Cast the line to check:
    67.         if (Physics.Linecast(trueTargetPosition, transform.position, out hit))
    68.         {
    69.             // If so, shorten distance so camera is in front of object:
    70.             float tempDistance = Vector3.Distance(trueTargetPosition, hit.point) - 0.28f;
    71.             // Finally, rePOSITION the CAMERA:
    72.             position = target.position - (rotation * Vector3.forward * tempDistance + new Vector3(0, -targetheight, 0));
    73.             transform.position = position;
    74.         }
    75.     }
    76.  
    77.     static float ClampAngle(float angle, float min, float max)
    78.     {
    79.         if (angle < -360) angle += 360;
    80.         if (angle > 360) angle -= 360;
    81.         return Mathf.Clamp(angle, min, max);
    82.     }
    83. }
     
  9. cilmeron

    cilmeron

    Joined:
    May 6, 2010
    Posts:
    10
    I made a very simple strafing - just add before the end of the Update ( }; ) and you should be good

    Now "strafemod" is a variable of the type float with an initial value of 0.0 and Strafel is your left strafe input while Strafer is your right strafe input. Replace with Input.GetKey("yourkeygoeshere") if you don't want it to be variable input keys (which I prefer because I want players to be able to modify their keyboard settings)

    Code (csharp):
    1. //simple strafing
    2.    //now let's do the quick check if we're walking or running
    3.    //walking goes here
    4.    if(isWalking == true){
    5.    //left strafe button is pressed -> strafe to the left
    6.    if (Input.GetButton("Strafel")){
    7.    strafemod = walkSpeed * Time.deltaTime;
    8.    transform.Translate ((strafemod * -1), 0, 0);
    9.    }
    10. //right strafe button is pressed -> strafe to the right
    11. if (Input.GetButton("Strafer")){
    12.    strafemod = walkSpeed * Time.deltaTime;
    13.    transform.Translate (strafemod, 0, 0);
    14.    }
    15.  
    16.    }
    17.    //running goes here
    18.    else{
    19.    //left strafe button is pressed -> strafe to the left
    20. if (Input.GetButton("Strafel")){
    21.    strafemod = runSpeed * Time.deltaTime;
    22.    transform.Translate ((strafemod * -1), 0, 0);
    23.    }
    24.   //left strafe button is pressed -> strafe to the right
    25. if (Input.GetButton("Strafer")){
    26.    strafemod = runSpeed * Time.deltaTime;
    27.    transform.Translate (strafemod, 0, 0);
    28.    }  
    29.    }
     
  10. jcullen24

    jcullen24

    Joined:
    Feb 27, 2010
    Posts:
    116
    Hey did I get a chance to thank you folks?
    What excellent incredible work!

    Thank you so much!
    Jim Cullen
     
  11. cilmeron

    cilmeron

    Joined:
    May 6, 2010
    Posts:
    10
    Hi again. My strafing script from before had a fundamental flaw unfortunately - due to the nature of transform.Translation you could easily move through walls ;)

    Anyway I've compensated the problem by changing to the characterController.Move method

    Code (csharp):
    1.  
    2.    //simple strafing
    3.    //now let's do the quick check if we're walking or running
    4.    //walking goes here
    5.    if(isWalking == true){
    6.    //left strafe button is pressed -> strafe to the left
    7.    if (Input.GetButton("Strafel")){
    8.   strafemod = new Vector3(1, 0, 0);
    9.    strafemod = transform.TransformDirection(strafemod);
    10.    controller.Move(((strafemod * walkSpeed)*-1) * Time.deltaTime);
    11.    }
    12. //right strafe button is pressed -> strafe to the right
    13. if (Input.GetButton("Strafer")){
    14.   strafemod = new Vector3(1, 0, 0);
    15.    strafemod = transform.TransformDirection(strafemod);
    16.    controller.Move((strafemod * walkSpeed) * Time.deltaTime);
    17.    }
    18.  
    19.    }
    20.    //running goes here
    21.    else{
    22.    //left strafe button is pressed -> strafe to the left
    23. if (Input.GetButton("Strafel")){
    24.    strafemod = new Vector3(1, 0, 0);
    25.    strafemod = transform.TransformDirection(strafemod);
    26.    controller.Move(((strafemod * runSpeed)*-1) * Time.deltaTime);
    27.    }
    28.   //left strafe button is pressed -> strafe to the right
    29. if (Input.GetButton("Strafer")){
    30.    strafemod = new Vector3(1, 0, 0);
    31.    strafemod = transform.TransformDirection(strafemod);
    32.    controller.Move((strafemod * runSpeed) * Time.deltaTime);
    33.    }  
    34.    }
    Ok now these changes also require to change the variable strafemod from a float to Vector3.zero:

    Code (csharp):
    1.  
    2. private var strafemod:Vector3 = Vector3.zero;
    ;) sorry for the inconvenience with the previous script

    EDIT:

    Another wow-style feature of the character movement is the fact that the character will be slower when moving backwards. In order to establish this I've included following variables:


    Code (csharp):
    1.  
    2. private var bmove:boolean = false;
    3. private var bspeed:float = 0.0;
    4.  
    The rest of the code is within our Update function:

    Code (csharp):
    1.  
    2. //let's check if we're moving backwards
    3. if(Input.GetAxis("Vertical") < 0){
    4.    bmove = true;
    5. }
    6. else{
    7.    bmove = false;
    8. }
    9. //now apply the slow to our movement if we're moving backwards
    10. if(isWalking == true){
    11.     if(bmove == true){
    12. //let's check if we're already slower and keep the speed to prevent a loop
    13.          if(bspeed > 0){
    14.             bspeed = bspeed;
    15.          }
    16.          else{
    17. //now we tell our variable how fast 100% is
    18.          bspeed = walkSpeed;
    19. //and now to notch it down to 60%
    20.          walkSpeed = bspeed * 0.6;
    21.          }
    22.      }
    23. //now if we're not moving backwards let's resume 100% speed
    24.      else{
    25.      if(bspeed > 0){
    26.      walkSpeed = bspeed;
    27.      bspeed = 0.0;
    28.      }
    29.    }
    30. }
    31. //now the same in blue for running ;)
    32. else{
    33. if(bmove == true){
    34.          if(bspeed > 0){
    35.             bspeed = bspeed;
    36.          }
    37.          else{
    38.          bspeed = runSpeed;
    39.          runSpeed = bspeed * 0.6;
    40.          }
    41.      }
    42.      else{
    43.      if(bspeed > 0){
    44.      runSpeed = bspeed;
    45.      bspeed = 0.0;
    46.      }
    47.    }
    48. }
    49.  
    50.  
     
  12. straydogstrut

    straydogstrut

    Joined:
    Oct 27, 2009
    Posts:
    16
    Wonderful thread, this has really helped me a lot!

    I didn't need a WoW setup specifically, but a combination of the scripts in this thread and elsewhere have helped me create the camera system I need for my game. Special thanks to matrix211v1, Paintbrush, and Vimalakirti; what you've provided between you is nothing short of amazing. Also big thanks to Fishypants - I was pulling my hair out with the same glitch - but changing to position as you suggested worked like a charm. Thank you.

    Here is my script. Not a WoW-style script but might be useful to someone. Full of comments (which unfortunately makes it look a bit bloated on here, sorry). Camera rotates around the player character using the mouse, and zooms in/out with the scrollwheel. Also repositions itself behind the player when they move and zooms closer when colliding with walls. Place this script on your camera.


    Code (csharp):
    1. // the target for the camera to orbit around
    2. var target : Transform;
    3.  
    4. // initial distance between the camera and the target
    5. var distance = 5.0;
    6. // min and max distance for zooming
    7. var minDistance = 3.0;
    8. var maxDistance = 10.0;
    9. // an offset to stop the camera clipping walls
    10. var offsetFromWall : float = 0.28;
    11.  
    12. // the speed at which the scrollwheel zooms in/out
    13. var zoomRate = 20;
    14.  
    15. // some internal variables to calculate distances
    16. private var currentDistance : float;
    17. private var desiredDistance : float;
    18. private var correctedDistance : float;
    19.  
    20. // speed of camera rotation around the object in both axes and smoothing for rotation
    21. var xSpeed : float = 200.0;
    22. var ySpeed : float = 200.0;
    23. var rotationDampening : float = 3.0;
    24.  
    25. // the min and max rotation limits of the camera in the y-axis (up and over the object) and smoothing for zooming
    26. var yMinLimit : int = 0;
    27. var yMaxLimit : int = 80;
    28. var zoomDampening : float = 5.0;
    29.  
    30. // variables to store the rotation of the camera
    31. private var x  : float = 0.0;
    32. private var y : float = 0.0;
    33.  
    34.  
    35. // adds a menu option to attach this script via the Component Menu
    36. @script AddComponentMenu("Camera-Control/Mouse Orbit")
    37.  
    38.  
    39. function Start () {
    40.     // store the initial rotation of the camera on the x and y axes
    41.     var angles = transform.eulerAngles;
    42.     x = angles.y;
    43.     y = angles.x;
    44.  
    45.     // set zoom distances to the value of the initial distance
    46.     currentDistance = distance;
    47.     desiredDistance = distance;
    48.     correctedDistance = distance;
    49.    
    50.     // Make the rigid body (if there is one) not change rotation
    51.     if (rigidbody) {
    52.         rigidbody.freezeRotation = true;
    53.     }
    54. }
    55.  
    56. // LateUpdate is called every frame after all other updates have happened
    57. //(preferable for camera follows since all objects should have already moved)
    58. function LateUpdate () {
    59.    
    60.     // if a target has been assigned (drag and drop one in the editor)
    61.     if (target) {
    62.         // if there is input on the vertical or horizontal axes (default is arrow keys and wasd)
    63.         if(Input.GetAxis("Vertical") || Input.GetAxis("Horizontal")) {
    64.             // store the current y-axis rotation of the target and the camera
    65.             var targetRotationAngle = target.eulerAngles.y;
    66.             var currentRotationAngle = transform.eulerAngles.y;
    67.             // interpolate between the current y-axis rotation and the target y-axis rotation over time
    68.             // setting the changing value to the x-axis rotation so the camera rotates around behind the PC
    69.             x = Mathf.LerpAngle(currentRotationAngle, targetRotationAngle, rotationDampening * Time.deltaTime);
    70.            
    71.         // if there is no input from the vertical/horizontal axes (we are not moving)
    72.         } else {
    73.             // allow the player to rotate the camera using the mouse by updating the camera's
    74.             // x/y rotation values based on the mouse position
    75.             x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
    76.             y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
    77.  
    78.         }
    79.        
    80.            
    81.         // set the y-axis rotation value based on the result of the ClampAngle function
    82.         y = ClampAngle(y, yMinLimit, yMaxLimit);
    83.        
    84.         // store the camera's rotation
    85.         var rotation = Quaternion.Euler(y, x, 0);
    86.        
    87.        
    88.         // convert input from the scrollwheel into zooming between the min/max distance ranges
    89.         desiredDistance -= Input.GetAxis ("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs (desiredDistance);
    90.         desiredDistance = Mathf.Clamp (desiredDistance, minDistance, maxDistance);
    91.         correctedDistance = desiredDistance;
    92.        
    93.         // store the camer's position
    94.         var position = target.position - (rotation * Vector3.forward * desiredDistance);
    95.        
    96.         // a variable to hold a reference to raycast collision objects
    97.         var hit : RaycastHit;
    98.         // a variable to hold a flag so we know if we have already corrected the camera's position
    99.         var isCorrected : boolean = false;
    100.         // if a ray between the target and the desired position hits something then their must be something blocking the line of sight
    101.         if (Physics.Linecast (target.position, position, hit)) {
    102.                 // shorten the distance between the camera and the target using the distance to the wall
    103.                 // minus an offset to prevent clipping
    104.                 correctedDistance = Vector3.Distance (target.position, hit.point) - offsetFromWall;
    105.                 // we have corrected the camera's position
    106.                 isCorrected = true;
    107.         }
    108.  
    109.         // if we haven't corrected the camera's position or the new distance is greater than the current distance
    110.         if(!isCorrected || correctedDistance > currentDistance){
    111.         // interpolate the distance of the camera from the target between the current distance and the corrected distances
    112.         // (ie. in front of the wall that is blocking our view)
    113.                
    114.             currentDistance = Mathf.Lerp (currentDistance, correctedDistance, Time.deltaTime * zoomDampening);
    115.            
    116.         }
    117.         // set our current distance to this new distance
    118.         currentDistance = correctedDistance;
    119.            
    120.         // clamp this value between the minimum and maximum distance settings
    121.         currentDistance = Mathf.Clamp(currentDistance, minDistance, maxDistance);
    122.  
    123.         // store the new position
    124.         position = target.position - (rotation * Vector3.forward * currentDistance);
    125.    
    126.        
    127.         // set the current rotation and position of the camera to the new values to make it move
    128.         transform.rotation = rotation;
    129.         transform.position = position;
    130.     }
    131. }  
    132.        
    133.  
    134. // keeps the value of the y-axis rotation within 360 degrees (it would cause an error otherwise)
    135. // and within the minimum and maximum limits previously defined
    136. static function ClampAngle (angle : float, min : float, max : float) {
    137.     if (angle < -360)
    138.         angle += 360;
    139.     if (angle > 360)
    140.         angle -= 360;
    141.     return Mathf.Clamp (angle, min, max);
    142. }
     
  13. Deleted User

    Deleted User

    Guest

    @cilmeron

    Could you please post the whole script?

    Thanks
     
  14. cilmeron

    cilmeron

    Joined:
    May 6, 2010
    Posts:
    10
    Here's the complete move script I'm currently using:

    I've also included an if-routine for the case the character is swimming.

    Code (csharp):
    1.  
    2. // Movement Variables:
    3. var jumpSpeed:float = 9.0;
    4. private var gravity:float = 20.0;
    5. static var runSpeed:float = 4.0;
    6. static var swimSpeed:float = 2.0;
    7. static var walkSpeed:float = 1.7;
    8. static var runSpeedsave = 4.0;
    9. static var walkSpeedsave = 1.7;
    10. static var curSpeed:float = 0.0;
    11. private var rotateSpeed:float = 150.0;
    12. private var grounded:boolean = false;
    13. private var moveDirection:Vector3 = Vector3.zero;
    14. static var isWalking:boolean = false;
    15. private var moveStatus:String = "idle";
    16. private var xSpeed = 250.0;
    17. private var ySpeed = 120.0;
    18. private var yMinLimit = -40;
    19. private var yMaxLimit = 80;
    20. private var x = 0.0;
    21. private var y = 0.0;
    22. static var ddistance:float = 0.0;
    23. static var strafemod:Vector3 = Vector3.zero;
    24. static var strafing = false;
    25. static var animationspeed = 1.0;
    26. var hit : RaycastHit;
    27. static var isSwimming = false;
    28. static var bmove = false;
    29. static var bSpeed = 0.0;
    30. //
    31. //UPDATE
    32. //
    33.    
    34. function Update ()
    35. //check if we fell down the world and teleport to a specific location
    36. {
    37. if(transform.position.y < -200)
    38.     {
    39.         transform.position.y = 16.07609;
    40.         transform.position.x = 579.2826;
    41.         transform.position.z = 130.8261;
    42.     }
    43.  
    44. //Move controller
    45. var controller:CharacterController = GetComponent(CharacterController);
    46. var flags = controller.Move(moveDirection * Time.deltaTime);
    47. grounded = (flags  CollisionFlags.Below) != 0; 
    48.  
    49. //check if we're moving backwards
    50.    if(Input.GetAxis("Vertical") < 0){
    51.    bmove = true;
    52.    }
    53.    else{
    54.    bmove = false;
    55.    }
    56. //check if we're swimming
    57. if(isSwimming == true){
    58. swimSpeed = runSpeed/2;
    59.    //reduce speed when moving backwards
    60.      if(bmove == true){
    61.          if(bSpeed > 0){
    62.      bSpeed = bSpeed;
    63.      }
    64.      else{
    65.      bSpeed = swimSpeed;
    66.      swimSpeed = bSpeed * 0.6;
    67.      }
    68.      }
    69.    else{
    70.      if(bSpeed > 0){
    71.      swimSpeed = bSpeed;
    72.      bSpeed = 0.0;
    73.      }
    74.      }
    75.        
    76.       moveDirection = new Vector3((Input.GetMouseButton(1) ? Input.GetAxis("Horizontal") : 0),0,Input.GetAxis("Vertical"));
    77.       if(Input.GetMouseButton(1)  Input.GetAxis("Vertical")  Input.GetAxis("Horizontal")) {
    78.          moveDirection *= .7;
    79.          }
    80.     animationspeed = runSpeed/4;
    81.     moveDirection = transform.TransformDirection(moveDirection);
    82.     moveDirection *= swimSpeed;
    83.        
    84.      moveStatus = "swim_idle";
    85.       if(moveDirection != Vector3.zero) {
    86.         moveStatus = "swimming";
    87. //invoke swim animation here        
    88. }
    89.       else {
    90. //swim idle animation
    91.       }
    92.       // Jump (or rather dive upwards)!
    93.       if(Input.GetButton("Jump"))
    94.       {
    95.          // call JUMP animation here
    96.          moveDirection.y = swimSpeed*1.6;
    97.       }
    98.    
    99.    // Allow turning at anytime. Keep the character facing in the same direction as the Camera if the right mouse button is down.
    100.    if(Input.GetMouseButton(1)) {
    101.       transform.rotation = Quaternion.Euler(Camera.main.transform.eulerAngles.x,Camera.main.transform.eulerAngles.y,0);
    102.    }
    103.    else {
    104.      transform.Rotate(0,Input.GetAxis("Horizontal") * rotateSpeed * Time.deltaTime, 0);
    105.    }
    106.    //simple strafing
    107.    //now let's do the quick check if we're walking or running
    108.    //walking goes here
    109.    //left strafe button is pressed -> strafe to the left
    110.    if (Input.GetButton("Strafel")){
    111.    strafemod = new Vector3(-1, 0, 0);
    112.    strafemod = transform.TransformDirection(strafemod);
    113.    strafemod = swimSpeed * strafemod;
    114.    controller.Move (strafemod * Time.deltaTime);
    115.    }
    116. //right strafe button is pressed -> strafe to the right
    117. if (Input.GetButton("Strafer")){
    118.    strafemod = new Vector3(1, 0, 0);
    119.    strafemod = transform.TransformDirection(strafemod);
    120.    strafemod = swimSpeed * strafemod;
    121.    controller.Move (strafemod * Time.deltaTime);
    122.    }
    123.    }
    124.    else{
    125.  
    126. //check if we're moving
    127.    if(Input.GetAxis("Vertical") != 0 || Input.GetAxis("Horizontal") != 0 || Input.GetButton("Strafel") || Input.GetButton("Strafer")){
    128.    if(isWalking == true){
    129.    curSpeed = walkSpeed;
    130.    }
    131.    else{
    132.    curSpeed = runSpeed;
    133.    }
    134.    }
    135.    else{
    136.    curSpeed = 0.0;
    137.  
    138. //since the backward slowing can have some permanent effects to our runSpeed and walkSpeed (i.e. the speed will stick to 60%) here's some failsave code making use of the run/walk Speedsave variables
    139.      
    140.    if(runSpeed < runSpeedsave){
    141.    runSpeed = runSpeedsave;
    142.    }
    143.    
    144.  
    145.    if(walkSpeed < walkSpeedsave){
    146.    walkSpeed = walkSpeedsave;
    147.    }
    148.    }
    149.  
    150.    
    151.    //reduce speed when moving backwards
    152.    if(isWalking == true){
    153.    
    154.    if(bmove == true){
    155.         if(bSpeed > 0){
    156.         bSpeed = bSpeed;
    157.         }
    158.         else{
    159.         bSpeed = walkSpeed;
    160.         walkSpeed = bSpeed * 0.6;
    161.         }
    162.                             }
    163.    else{
    164.         if(bSpeed > 0){
    165.         walkSpeed = bSpeed;
    166.         bSpeed = 0.0;
    167.         }
    168.     }
    169.     }
    170.    else{
    171.     if(bmove == true){
    172.    if(bSpeed > 0){
    173.    bSpeed = bSpeed;
    174.    }
    175.    else{
    176.    bSpeed = runSpeed;
    177.    runSpeed = bSpeed * 0.6;
    178.    }
    179.    }
    180.    else{
    181.    if(bSpeed > 0){
    182.    runSpeed = bSpeed;
    183.    bSpeed = 0.0;
    184.    }
    185.    }
    186.    }
    187.    
    188.    //check if we're moving - if we're moving track distance and save to ddistance
    189.    if(curSpeed > 0){
    190.    ddistance = ddistance + (curSpeed * Time.deltaTime);
    191.    }
    192.    //
    193.    // Only allow movement and jumps while -----------------  GROUNDED -------------
    194.    
    195.    if(grounded) {
    196.    moveDirection = new Vector3((Input.GetMouseButton(1) ? Input.GetAxis("Horizontal") : 0),0,Input.GetAxis("Vertical"));
    197.       if(Input.GetMouseButton(1)  Input.GetAxis("Vertical")  Input.GetAxis("Horizontal")) {
    198.          moveDirection *= .7;
    199.          }
    200.     animationspeed = runSpeed/4;
    201.     moveDirection = transform.TransformDirection(moveDirection);
    202.       moveDirection *= isWalking ? walkSpeed : runSpeed;
    203.        
    204.       moveStatus = "idle";
    205.       if(moveDirection != Vector3.zero) {
    206.          moveStatus = isWalking ? "walking" : "running";
    207.          if (isWalking){
    208.            // invoke WALK animation here
    209.          } else {
    210.     // call RUN animation here
    211.          }
    212.       } else {
    213.         // call IDLE animation here
    214.       }
    215.       // Jump!
    216.       if(Input.GetButton("Jump"))
    217.       {
    218.          // call JUMP animation here
    219.          moveDirection.y = jumpSpeed;
    220.       }
    221.     }                  
    222.     // END "IS GROUNDED"
    223.    
    224.    // Allow turning at anytime. Keep the character facing in the same direction as the Camera if the right mouse button is down.
    225.    if(Input.GetMouseButton(1)) {
    226.       transform.rotation = Quaternion.Euler(0,Camera.main.transform.eulerAngles.y,0);
    227.    }
    228.    else {
    229.      transform.Rotate(0,Input.GetAxis("Horizontal") * rotateSpeed * Time.deltaTime, 0);
    230.    }
    231.    
    232.    // Toggle walking/running with the walk/run key
    233.    if(Input.GetButtonDown("walk"))
    234.          isWalking = !isWalking;
    235.        
    236.    //Apply gravity
    237.    moveDirection.y -= gravity * Time.deltaTime;
    238.    //Move controller
    239.    //var controller:CharacterController = GetComponent(CharacterController);
    240.    //var flags = controller.Move(moveDirection * Time.deltaTime);
    241.    grounded = (flags  CollisionFlags.Below) != 0;
    242.    
    243.    //simple strafing
    244.    //now let's do the quick check if we're walking or running
    245.    //walking goes here
    246.    if(isWalking == true){
    247.    //left strafe button is pressed -> strafe to the left
    248.    if (Input.GetButton("Strafel")){
    249.    strafemod = new Vector3(-1, 0, 0);
    250.    strafemod = transform.TransformDirection(strafemod);
    251.    strafemod = walkSpeed * strafemod;
    252.    controller.Move (strafemod * Time.deltaTime);
    253.    }
    254. //right strafe button is pressed -> strafe to the right
    255. if (Input.GetButton("Strafer")){
    256.    strafemod = new Vector3(1, 0, 0);
    257.    strafemod = transform.TransformDirection(strafemod);
    258.    strafemod = walkSpeed * strafemod;
    259.    controller.Move (strafemod * Time.deltaTime);
    260.    }
    261.  
    262.    }
    263.    //running goes here
    264.    else{
    265.    //left strafe button is pressed -> strafe to the left
    266. if (Input.GetButton("Strafel")){
    267.    strafemod = new Vector3(-1, 0, 0);
    268.    strafemod = transform.TransformDirection(strafemod);
    269.    strafemod = runSpeed * strafemod;
    270.    controller.Move (strafemod * Time.deltaTime);
    271.    }
    272.   //left strafe button is pressed -> strafe to the right
    273. if (Input.GetButton("Strafer")){
    274.    strafemod = new Vector3(1, 0, 0);
    275.    strafemod = transform.TransformDirection(strafemod);
    276.    strafemod = runSpeed * strafemod;
    277.    controller.Move (strafemod * Time.deltaTime);
    278.    }  
    279.    }
    280.    }
    281.    };
    282.    
    283.    static function ClampAngle (angle : float, min : float, max : float) {
    284.    if (angle < -360)
    285.       angle += 360;
    286.    if (angle > 360)
    287.       angle -= 360;
    288.    return Mathf.Clamp (angle, min, max);
    289. }
    290.  
    291.  
    292. // -------------------------------------------------------------------------------------------------------------
    293. // ----------------------------------------------------------- END UPDATE  --------------------------------
    294. // -------------------------------------------------------------------------------------------------------------
    295.  
    296. @script RequireComponent(CharacterController)
    297.  
    Now to find out if the character is swimming I created some water element (i.e. a cube) with a mesh Collider and isTrigger on. I then applied this script to the "water":

    Code (csharp):
    1.  
    2.      
    3. function OnTriggerEnter  (other : Collider) {
    4. if (other.gameObject.tag == "Player") {
    5. move.isSwimming = true;
    6. }
    7. }
    8.  
    9. function OnTriggerExit  (other : Collider) {
    10. if (other.gameObject.tag == "Player") {
    11. move.isSwimming = false;
    12. }
    13. }
    Oh yeah and my camera script - which is pretty much what has been posted on here already but includes a passive mode when pressing the camera button (has to be defined in the Input settings -> the same goes for walk/strafelel and strafer)

    Code (csharp):
    1.  
    2. var target : Transform;
    3. var targetHeight = 2.0;
    4. var distance = 2.8;
    5. var maxDistance = 10;
    6. var minDistance = 0.5;
    7. var xSpeed = 250.0;
    8. var ySpeed = 120.0;
    9. var yMinLimit = -40;
    10. var yMaxLimit = 80;
    11. static var camactive = true;
    12. var zoomRate = 20;
    13. var rotationDampening = 3.0;
    14. private var x = 0.0;
    15. private var y = 0.0;
    16. static var underwater:boolean = false;
    17. var isTalking:boolean = false;
    18.  
    19. @script AddComponentMenu("Camera-Control/WoW Camera")
    20.  
    21. function Start () {
    22.     var angles = transform.eulerAngles;
    23.     x = angles.y;
    24.     y = angles.x;
    25.  
    26.    // Make the rigid body not change rotation
    27.       if (rigidbody)
    28.       rigidbody.freezeRotation = true;
    29. }
    30.  
    31. function Update() {
    32. if(underwater == true)
    33.    {
    34.       color = Color (56.0, 166.0, 198.0, 122.0);        
    35.       RenderSettings.fogColor = color;
    36.       RenderSettings.fogDensity = 0.1;
    37.    }
    38.    
    39.    
    40.    
    41.    }
    42.  
    43. function LateUpdate () {
    44.    if(!target)
    45.       return;
    46.    
    47.    if (Input.GetButtonDown("Camera")){
    48.     camactive = !camactive;
    49.    }
    50.    // If either mouse buttons are down, let them govern camera position
    51.    
    52.    if(camactive == true){
    53.    if (Input.GetMouseButton(0) || (Input.GetMouseButton(1))){
    54.    x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
    55.    y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
    56.    
    57.    
    58.    // otherwise, ease behind the target if any of the directional keys are pressed
    59.    } else if(Input.GetAxis("Vertical") || Input.GetAxis("Horizontal")) {
    60.       var targetRotationAngle = target.eulerAngles.y;
    61.       var currentRotationAngle = transform.eulerAngles.y;
    62.       x = Mathf.LerpAngle(currentRotationAngle, targetRotationAngle, rotationDampening * Time.deltaTime);
    63.      
    64.     }
    65.     }
    66.     else{
    67.     if (Input.GetMouseButton(0) || (Input.GetMouseButton(1))){
    68.    x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
    69.    y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
    70.    
    71.    
    72.    // otherwise, ease behind the target if any of the directional keys are pressed
    73.    }
    74.    }
    75.    
    76.      
    77.  
    78.    distance -= (Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime) * zoomRate * Mathf.Abs(distance);
    79.    distance = Mathf.Clamp(distance, minDistance, maxDistance);
    80.    
    81.    y = ClampAngle(y, yMinLimit, yMaxLimit);
    82.    
    83.   // ROTATE CAMERA:
    84.    var rotation:Quaternion = Quaternion.Euler(y, x, 0);
    85.    transform.rotation = rotation;
    86.    
    87.    // POSITION CAMERA:
    88.    var position = target.position - (rotation * Vector3.forward * distance + Vector3(0,-targetHeight,0));
    89.    transform.position = position;
    90.    
    91.    // IS VIEW BLOCKED?
    92.     var hit : RaycastHit;
    93.     var trueTargetPosition : Vector3 = target.transform.position - Vector3(0,-targetHeight,0);
    94.    // Cast the line to check:
    95.     if (Physics.Linecast (trueTargetPosition, transform.position, hit)) {
    96.       // If so, shorten distance so camera is in front of object:
    97.       var tempDistance = Vector3.Distance (trueTargetPosition, hit.point) - 0.28;
    98.       // Finally, rePOSITION the CAMERA:
    99.       position = target.position - (rotation * Vector3.forward * tempDistance + Vector3(0,-targetHeight,0));
    100.       transform.position = position;
    101.    }
    102. }
    103.  
    104. static function ClampAngle (angle : float, min : float, max : float) {
    105.    if (angle < -360)
    106.       angle += 360;
    107.    if (angle > 360)
    108.       angle -= 360;
    109.    return Mathf.Clamp (angle, min, max);
    110.    
    111. }
     
  15. Deleted User

    Deleted User

    Guest

    Thank you very much.

    It works perfectly.

    But I get an error message
    NullReferenceException: Object reference not set to an instance of an object
    CharControllerBeta.Update () (at Assets\CharControllerBeta.js:100)

    and Line 255 (Strafel and Strafer).
    Both works fine Ive also createt 2 inputs for them, but the error still exists.

    Another question is: how to change between walk and run?

    Thanks again
     
  16. cilmeron

    cilmeron

    Joined:
    May 6, 2010
    Posts:
    10
    this line is responsible for the change between walking and running:

    Code (csharp):
    1. if(Input.GetButtonDown("walk"))
    2.          isWalking = !isWalking;
    So you have to set up an input for "walk".

    As for the error message - what code do you have on line 100?
     
  17. Deleted User

    Deleted User

    Guest

    On line 100:

    transform.rotation = Quaternion.Euler(0,Camera.main.transform.eulerAngles.y,0);


    on the other line:

    strafemod = transform.TransformDirection(strafemod);

    Both are "NullReferenceException: Object reference not set to an instance of an object"
     
  18. cilmeron

    cilmeron

    Joined:
    May 6, 2010
    Posts:
    10
    Do you mind posting the whole script? The NullReferenceException usually only occurs when an object doesn't have any value which doesn't seem possible from/on the lines you posted oO
     
  19. Deleted User

    Deleted User

    Guest

    Its the same script youve posted above.

    Ive changed nothing^^
     
  20. Tannz0rz

    Tannz0rz

    Joined:
    May 17, 2010
    Posts:
    18
    The code below takes Vima's "camera correction on idle" snippet into consideration, while also providing a fix to the camera "fall-through" where you're able to see beneath terrain. I've not tested it with other 3D objects in presence though. Enjoy.

    Quick edit: I've also rid of the LMB usage to move the camera, it now only uses the RMB.

    Code (csharp):
    1. var target : Transform;
    2. var distance = 10.0;
    3.  
    4. var xSpeed = 250.0;
    5. var ySpeed = 120.0;
    6.  
    7. var yMinLimit = -20;
    8. var yMaxLimit = 80;
    9.  
    10. var zoomRate = 20;
    11.  
    12. private var x = 0.0;
    13. private var y = 0.0;
    14.  
    15. @script AddComponentMenu("Camera-Control/Mouse Orbit")
    16.  
    17. function Start ()
    18. {
    19.     var angles = transform.eulerAngles;
    20.     x = angles.y;
    21.     y = angles.x;
    22.  
    23.     if (rigidbody)
    24.         rigidbody.freezeRotation = true;
    25. }
    26.  
    27. function LateUpdate ()
    28. {
    29.     CameraHandle();
    30. }
    31.  
    32. function CameraHandle()
    33. {
    34.     if(target)
    35.     {
    36.         var hit : RaycastHit;
    37.        
    38.         if (Input.GetMouseButton(1))
    39.         {
    40.             x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
    41.             y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
    42.         }
    43.         else if(Input.GetAxis("Vertical") || Input.GetAxis("Horizontal"))
    44.             x = Mathf.LerpAngle(
    45.                     transform.eulerAngles.y,
    46.                     target.eulerAngles.y,
    47.                     3.0 * Time.deltaTime);
    48.        
    49.         var oy = y;
    50.  
    51.         y = ClampAngle(y, yMinLimit, yMaxLimit);
    52.  
    53.         if(y == yMinLimit  
    54.             oy == yMinLimit)
    55.             distance +=
    56.                 -(Input.GetAxis("Mouse Y") *
    57.                 Time.deltaTime) *
    58.                 10 *
    59.                 Mathf.Abs(distance);
    60.  
    61.         var rotation = Quaternion.Euler(y, x, 0);
    62.         var position =
    63.                 rotation *
    64.                 Vector3(0.0, 1.0, -distance) +
    65.                 target.position;
    66.  
    67.         transform.rotation = rotation;
    68.        
    69.         if(Physics.Raycast(
    70.             Vector3(position.x, position.y - 0.5, position.z),
    71.             transform.forward,
    72.             hit,
    73.             distance)
    74.             hit.rigidbody != target.rigidbody)
    75.             transform.position = Vector3(hit.point.x, hit.point.y + 0.5, hit.point.z);
    76.         else
    77.             transform.position = position;
    78.     }
    79. }
    80.  
    81. static function ClampAngle (angle : float, min : float, max : float)
    82. {
    83.     if (angle < -360)
    84.         angle += 360;
    85.     if (angle > 360)
    86.         angle -= 360;
    87.  
    88.     return Mathf.Clamp (angle, min, max);
    89. }
     
  21. TheMorten

    TheMorten

    Joined:
    Feb 17, 2010
    Posts:
    7
    First off, props to the people of this thread! This is a monument to the Unity Community! :)

    I encountered a problem though... When changing the zoom to depend on mouse movement (both mouse buttons down), the zoom function became really wonky on my computer. Moving the mouse even a hair's breadth in the positive Y direction made me zoom in, while I needed to pull the mouse forcefully towards me if I wanted to zoom out.

    If I pulled the mouse slowly towards me, I got no response at all, which lead me to believe the float value of axis "Mouse Y" was tiny, and didn't achieve sufficient size to affect the "distance" variable. The "distance" variable, of course, needed to be declared as a float ( :p ).

    I've posted my modified code below, it mimics a Homeworld-style control, where the user needs to start camera movement by having the mouse cursor in "open space" (camera screen space with no interfering GUI elements).

    Code (csharp):
    1. //MyCamera.js
    2. //Attach to main camera, drag target object (camera focus) into inspector slot
    3.  
    4. var target : Transform;
    5. var targetHeight = 6.0;
    6. var distance = 15;
    7. var maxDistance = 200;
    8. var minDistance = 5;
    9. var xSpeed = 250.0;
    10. var ySpeed = 120.0;
    11. var yMinLimit = 0;
    12. var yMaxLimit = 80;
    13. var zoomRate = 5;
    14. var rotationDampening = 3.0;
    15. private var x = 0.0;
    16. private var y = 0.0;
    17. var isTalking:boolean = false;
    18.  
    19. var mouseIsDown = false;
    20. var bothMouseDown = false;
    21.  
    22. @script AddComponentMenu("Camera-Control/WoW Camera")
    23.  
    24. function Start () {
    25.     var angles = transform.eulerAngles;
    26.     x = angles.y;
    27.     y = angles.x;
    28.  
    29.     // Make the rigid body not change rotation
    30.     if (rigidbody)
    31.     rigidbody.freezeRotation = true;
    32. }
    33.  
    34. function LateUpdate () {
    35.     if(!target) {
    36.         return;
    37.     }
    38.    
    39.     var cornerX = Screen.width*0.2;
    40.     var cornerY = Screen.height*0.3;
    41.     var rect = Rect (cornerX, cornerY, Screen.width, Screen.height);
    42.    
    43.     if (GUIUtility.hotControl == 0) {
    44.         // If right mouse button is pressed, govern camera position
    45.         if (Input.GetMouseButtonDown(1)  Camera.main.pixelRect.Contains(Input.mousePosition)){
    46.             mouseIsDown = true;
    47.             Screen.lockCursor = true;
    48.         }
    49.        
    50.         //If the mouse button is released anywhere, do not govern camera position
    51.         else if (!Input.GetMouseButton(1)) {
    52.             mouseIsDown = false;
    53.             bothMouseDown = false;
    54.             Screen.lockCursor = false;
    55.         }
    56.        
    57.         //Check if both mouse buttons are down
    58.         if (Input.GetMouseButton(0)  mouseIsDown) {
    59.             bothMouseDown = true;
    60.         } else {
    61.             bothMouseDown = false;
    62.         }
    63.        
    64.         //Govern camera
    65.         if (mouseIsDown  !bothMouseDown) {
    66.             x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
    67.             y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
    68.         } else if (mouseIsDown  bothMouseDown) {
    69.             distance -= (Input.GetAxis("Mouse Y")*Time.deltaTime)*zoomRate*Mathf.Abs(distance);
    70.             distance = Mathf.Clamp(distance, minDistance, maxDistance);
    71.         }
    72.     }
    73.    
    74.     y = ClampAngle(y, yMinLimit, yMaxLimit);
    75.    
    76.     // ROTATE CAMERA:
    77.     var rotation:Quaternion = Quaternion.Euler(y, x, 0);
    78.     transform.rotation = rotation;
    79.    
    80.     // POSITION CAMERA:
    81.     var position = target.position - (rotation * Vector3.forward * distance + Vector3(0,-targetHeight,0));
    82.     transform.position = position;
    83. }
    84.  
    85. static function ClampAngle (angle : float, min : float, max : float) {
    86.     if (angle < -360)
    87.         angle += 360;
    88.     if (angle > 360)
    89.         angle -= 360;
    90.     return Mathf.Clamp (angle, min, max);
    91. }
    (Edit: Corrected spelling)
     
  22. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,498
    Hi. Good thread and thanks really.

    But still need some tweak for real same control with WOW.

    Or for other good 3rd-person control.
     
  23. juniorB

    juniorB

    Joined:
    Apr 20, 2010
    Posts:
    13
    Hey, I tryed the code it work nicely but I have a problem with it and i don't know how to get around it.

    The problem would be that when I get in to tight places with the character the wall comes between me and the character. This feature isn't present in WoW :)

    I have no idea how to make the camera move if there is an object between the character and the camera an how to make it move in the right directin. Does someone have a solution for this problem ?
     
  24. Vimalakirti

    Vimalakirti

    Joined:
    Oct 12, 2009
    Posts:
    755
    Last edited: Feb 25, 2014
  25. juniorB

    juniorB

    Joined:
    Apr 20, 2010
    Posts:
    13
    Thank you and sorry for posting a problem witch was already solved.
     
  26. Gerard

    Gerard

    Joined:
    Jun 1, 2010
    Posts:
    7
    sorry for the bump, im trying to use your camera from page 7 but i get a nullreferenceexception on the line:

    Code (csharp):
    1. transform.rotation = Quaternion.Euler(0,Camera.main.transform.eulerAngles.y,0)
    ;

    i think this has something to do with my camera being named wrong or the camera not being declared earlier on or something?

    Have been messing around with it but can't seem to get it to work, does anyone have an idea?
     
  27. Deleted User

    Deleted User

    Guest

    Try to give you camera the "MainCamera" Tag :)
     
  28. Skatt

    Skatt

    Joined:
    Jun 25, 2010
    Posts:
    42
    Great work guys, saved me tons of time with those trackers, I'll be sure to share some of my code once I write some.
    I changed the line of code that reads:
    Code (csharp):
    1. else if (Input.GetAxis("Vertical") !=0|| Input.GetAxis("Horizontal") !=0)
    to:
    Code (csharp):
    1. else if (Input.GetAxisRaw("Vertical") !=0|| Input.GetAxisRaw("Horizontal") !=0)
    This resolved many issues with positioning, smoothing, etc. actually. I think that the value returned by the raw axis is probably a more appropriate format for what the function was trying to achieve.
    Hope this helps.[/code]
     
  29. Dieneces

    Dieneces

    Joined:
    Aug 1, 2009
    Posts:
    26
    Powerful Threat! Many thanks for all of your hard work, I didn't needed all the features but I learn alot with the code!

    Still, a thing that exists in wow camera and its a MUST to and RPG or MMORPG in my opinion. Is the running pressing both buttons of the mouse (right and left at the same time). Just an idea for all you making the next Final Fantasy or WoW in Unity ;)
     
  30. mercuryplutus

    mercuryplutus

    Joined:
    Jun 27, 2010
    Posts:
    158
    How would I add the ability to move left/right or back/forward after a standing still jump like WOW?
     
  31. mercuryplutus

    mercuryplutus

    Joined:
    Jun 27, 2010
    Posts:
    158
    I added
    Code (csharp):
    1.  
    2. if(!grounded)
    3.     {
    4.         Debug.Log(Input.GetAxis("Horizontal"));
    5.         Debug.Log("Not Grounded");
    6.         moveDirection.x = Input.GetAxis("Horizontal") * airSpeed;
    7.         moveDirection.z = Input.GetAxis("Vertical") * airSpeed;
    8.  
    9.     }
    10.  
    It works except for 1 major problem. The movements are not relative to the player. They are fixed to the world. How do i fix this?
     
  32. mercuryplutus

    mercuryplutus

    Joined:
    Jun 27, 2010
    Posts:
    158
    Code (csharp):
    1.  
    2. moveDirection = new Vector3(horizontal * airSpeed, moveDirection.y, vertical * airSpeed);
    3.        
    4. moveDirection = transform.TransformDirection(moveDirection);  
    5.  
    Did the trick.
     
  33. Ensane

    Ensane

    Joined:
    Jul 13, 2010
    Posts:
    221
    im still having trouble getting the move forward to work when both mouse buttons are held down
     
  34. Skatt

    Skatt

    Joined:
    Jun 25, 2010
    Posts:
    42
    On a laptop both buttons down sends the middle button, otherwise it just:
    Code (csharp):
    1.  
    2. if(Input.GetButtonDown("Fire1")  Input.GetButtonDown("Fire2"))
    3.  
    If that doesn't work use Input.GetButton.
     
  35. matrix211v1

    matrix211v1

    Joined:
    Jan 20, 2009
    Posts:
    193
    Hello All!

    I just wanted to say thanks for making this one of the most popular threads in all of the Unity Forum. I did not realize when I started this almost a year and a half ago that anyone wanted to do what I created....

    It seems that I was wrong.

    I plan on compiling all this information and move a finalized version into the Unity Wiki and hopefully it will even help more people!

    Take care everyone!
     
  36. Tilluss

    Tilluss

    Joined:
    Mar 5, 2010
    Posts:
    34
    I've taken the c# example that was posted a few pages back, converted it to javascript and added in an auto-rotation feature to it.

    Now when a user presses an arrow button the camera will continue to rotate to the back of the target until it gets there rather than only moving towards the back of the character while the button is pressed. If the target hasn't been reached and the mouse position is moved then the rotation is stopped and the control is passed back to the mouse.

    I know it's not much of an addition but i thought i would post the code anyway :)

    Code (csharp):
    1.  
    2.  
    3. var target:Transform;                           // Target to follow
    4. var targetHeight = 1.7;                         // Vertical offset adjustment
    5. var distance = 12.0;                            // Default Distance
    6. var offsetFromWall = 0.1;                       // Bring camera away from any colliding objects
    7. var maxDistance = 20;                       // Maximum zoom Distance
    8. var minDistance = 0.6;                      // Minimum zoom Distance
    9. var xSpeed = 200.0;                             // Orbit speed (Left/Right)
    10. var ySpeed = 200.0;                             // Orbit speed (Up/Down)
    11. var yMinLimit = -80;                            // Looking up limit
    12. var yMaxLimit = 80;                             // Looking down limit
    13. var zoomRate = 40;                          // Zoom Speed
    14. var rotationDampening = 3.0;                // Auto Rotation speed (higher = faster)
    15. var zoomDampening = 5.0;                    // Auto Zoom speed (Higher = faster)
    16. var collisionLayers:LayerMask = -1;     // What the camera will collide with
    17.  
    18. private var xDeg = 0.0;
    19. private var yDeg = 0.0;
    20. private var currentDistance;
    21. private var desiredDistance;
    22. private var correctedDistance;
    23. private var rotateBehind = false;
    24.  
    25. @script AddComponentMenu("Camera-Control/Third Person Camera Orbit (MMORPG Like)")
    26.  
    27. function Start ()
    28. {
    29.     var angles:Vector3 = transform.eulerAngles;
    30.     xDeg = angles.x;
    31.     yDeg = angles.y;
    32.     currentDistance = distance;
    33.     desiredDistance = distance;
    34.     correctedDistance = distance;
    35.    
    36.     // Make the rigid body not change rotation
    37.     if (rigidbody)
    38.         rigidbody.freezeRotation = true;
    39.  }
    40.    
    41. //Only Move camera after everything else has been updated
    42. function LateUpdate ()
    43. {
    44.     // Don't do anything if target is not defined
    45.     if (!target)
    46.         return;
    47.    
    48.     var vTargetOffset:Vector3;
    49.        
    50.      
    51.     // If either mouse buttons are down, let the mouse govern camera position
    52.     if (GUIUtility.hotControl == 0)
    53.     {
    54.         if (Input.GetMouseButton(0) || Input.GetMouseButton(1))
    55.         {
    56.             xDeg += Input.GetAxis ("Mouse X") * xSpeed * 0.02;
    57.             yDeg -= Input.GetAxis ("Mouse Y") * ySpeed * 0.02;
    58.            
    59.             //Interrupt rotating behind if mouse wants to control rotation
    60.             rotateBehind = false;
    61.         }
    62.        
    63.         // otherwise, ease behind the target if any of the directional keys are pressed
    64.         else if (Input.GetAxis("Vertical") != 0 || Input.GetAxis("Horizontal") != 0 || rotateBehind)
    65.         {
    66.             var targetRotationAngle:float = target.eulerAngles.y;
    67.             var currentRotationAngle:float = transform.eulerAngles.y;
    68.             xDeg = Mathf.LerpAngle (currentRotationAngle, targetRotationAngle, rotationDampening * Time.deltaTime);
    69.            
    70.             // Stop rotating behind if not completed
    71.             if (targetRotationAngle == currentRotationAngle)
    72.                 rotateBehind = false;
    73.             else
    74.                 rotateBehind = true;
    75.         }
    76.     }
    77.     yDeg = ClampAngle (yDeg, yMinLimit, yMaxLimit);
    78.  
    79.     // Set camera rotation
    80.     var rotation:Quaternion = Quaternion.Euler (yDeg, xDeg, 0);
    81.  
    82.     // Calculate the desired distance
    83.     desiredDistance -= Input.GetAxis ("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs (desiredDistance);
    84.     desiredDistance = Mathf.Clamp (desiredDistance, minDistance, maxDistance);
    85.     correctedDistance = desiredDistance;
    86.  
    87.     // Calculate desired camera position
    88.     vTargetOffset = Vector3 (0, -targetHeight, 0);
    89.     var position:Vector3 = target.position - (rotation * Vector3.forward * desiredDistance + vTargetOffset);
    90.  
    91.     // Check for collision using the true target's desired registration point as set by user using height
    92.     var collisionHit:RaycastHit;
    93.     var trueTargetPosition:Vector3 = Vector3 (target.position.x, target.position.y + targetHeight, target.position.z);
    94.  
    95.     // If there was a collision, correct the camera position and calculate the corrected distance
    96.     var isCorrected = false;
    97.     if (Physics.Linecast (trueTargetPosition, position, collisionHit, collisionLayers))
    98.     {
    99.         // Calculate the distance from the original estimated position to the collision location,
    100.         // subtracting out a safety "offset" distance from the object we hit.  The offset will help
    101.         // keep the camera from being right on top of the surface we hit, which usually shows up as
    102.         // the surface geometry getting partially clipped by the camera's front clipping plane.
    103.         correctedDistance = Vector3.Distance (trueTargetPosition, collisionHit.point) - offsetFromWall;
    104.         isCorrected = true;
    105.     }
    106.  
    107.     // For smoothing, lerp distance only if either distance wasn't corrected, or correctedDistance is more than currentDistance
    108.     currentDistance = !isCorrected || correctedDistance > currentDistance ? Mathf.Lerp (currentDistance, correctedDistance, Time.deltaTime * zoomDampening) : correctedDistance;
    109.  
    110.     // Keep within limits
    111.     currentDistance = Mathf.Clamp (currentDistance, minDistance, maxDistance);
    112.  
    113.     // Recalculate position based on the new currentDistance
    114.     position = target.position - (rotation * Vector3.forward * currentDistance + vTargetOffset);
    115.    
    116.     //Finally Set rotation and position of camera
    117.     transform.rotation = rotation;
    118.     transform.position = position;
    119. }
    120.  
    121.  
    122. static function ClampAngle (angle : float, min : float, max : float)
    123. {
    124.    if (angle < -360)
    125.       angle += 360;
    126.    if (angle > 360)
    127.       angle -= 360;
    128.    return Mathf.Clamp (angle, min, max);
    129. }
     
  37. burst2flame

    burst2flame

    Joined:
    Dec 28, 2009
    Posts:
    23
    Excellent work so far! Im not a programmer but I noticed something kinda big thats still missing. When you hold down the right mouse button and move, the camera is fine and all, but the character is always facing forward regardless of the direction your walking. Looks really funny if your moving diagonal (or any other direction other than straight forward). Any ideas on how to fix this and actually have the character face the direction he is moving?
     
  38. Skatt

    Skatt

    Joined:
    Jun 25, 2010
    Posts:
    42
    You just need to add rotation to the actual player. Somewhere in here is a movement script that you put on the player object rather than the camera. It does have that code in it. If you can't find it, use Transform.Rotation, you should find plenty of information on how in the Unity documentation.
     
  39. burst2flame

    burst2flame

    Joined:
    Dec 28, 2009
    Posts:
    23
    Awesome thanks!
     
  40. burst2flame

    burst2flame

    Joined:
    Dec 28, 2009
    Posts:
    23
    Did anyone get jianwei.jwtan's version of the controller.cs script to work? When I use the javascipt version on page 7 it works fine, but when I used the C# version the controller script wont work, and I can't move at all. Anyone have any ideas why?
     
  41. Skatt

    Skatt

    Joined:
    Jun 25, 2010
    Posts:
    42
    You're right, it's not working. I don't have any time to look through it right now, but here is a very simple control script you can use as an example to fix it yourself.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class Control : MonoBehaviour {
    6.        
    7.     public float moveSpeed;
    8.     public float strafeSpeed;
    9.     public float turnSpeed;
    10.    
    11.     public float turn;
    12.     public float move;
    13.     public float strafe;
    14.     public int minTurn;
    15.     public int maxTurn;
    16.    
    17.     void Start () {
    18.         moveSpeed = 2.0f;
    19.         strafeSpeed = 1.0f;
    20.         turnSpeed =  50.0f;
    21.    
    22.         turn = 0.0f;
    23.         move = 0.0f;
    24.         strafe = 0.0f;
    25.         minTurn = -80;
    26.         maxTurn = 80;
    27.     }
    28.     // Update is called once per frame
    29.     void Update () {
    30.         turn = (Input.GetAxis("Horizontal")*turnSpeed*Time.deltaTime);
    31.         move = (Input.GetAxis("Vertical")*moveSpeed*Time.deltaTime);
    32.         strafe = (Input.GetAxis("Horizontal2")*strafeSpeed*Time.deltaTime);
    33.         if(Input.GetAxis("Vertical") !=0){
    34.             transform.Translate(Vector3.forward * move);
    35.         }
    36.         if(Input.GetAxis("Horizontal") !=0){
    37.             turn = ObjectHandler.ClampAngle (turn, minTurn, maxTurn);      
    38.             transform.Rotate(Vector3.up*turn);
    39.         }
    40.         if(Input.GetAxis("Horizontal2") !=0){      
    41.             transform.Translate(Vector3.right * strafe);
    42.         }
    43.        
    44.     }
    45. }
    46.  
     
  42. Tilluss

    Tilluss

    Joined:
    Mar 5, 2010
    Posts:
    34
    Or maybe it would be best to keep the camera script and controller script separate to avoid confusion?

    If it was me i would add into you update() event on your character control for turning, moving etc and add in a way to lock your camera to the characters back with a smooth rotation dampening.

    I've modified the script I posted at the top of page 10 to allow a bit more customization in the control of the camera. You can now lock the camera to the rear of the target and remove the mouse control from either axis. These options could be useful to someone :)

    Code (csharp):
    1.  
    2.  
    3. var target:Transform;                           // Target to follow
    4. var targetHeight = 1.7;                         // Vertical offset adjustment
    5. var distance = 12.0;                            // Default Distance
    6. var offsetFromWall = 0.1;                       // Bring camera away from any colliding objects
    7. var maxDistance = 20;                       // Maximum zoom Distance
    8. var minDistance = 0.6;                      // Minimum zoom Distance
    9. var xSpeed = 200.0;                             // Orbit speed (Left/Right)
    10. var ySpeed = 200.0;                             // Orbit speed (Up/Down)
    11. var yMinLimit = -80;                            // Looking up limit
    12. var yMaxLimit = 80;                             // Looking down limit
    13. var zoomRate = 40;                          // Zoom Speed
    14. var rotationDampening = 3.0;                // Auto Rotation speed (higher = faster)
    15. var zoomDampening = 5.0;                    // Auto Zoom speed (Higher = faster)
    16. var collisionLayers:LayerMask = -1;     // What the camera will collide with
    17. var lockToRearOfTarget = false;             // Lock camera to rear of target
    18. var allowMouseInputX = true;                // Allow player to control camera angle on the X axis (Left/Right)
    19. var allowMouseInputY = true;                // Allow player to control camera angle on the Y axis (Up/Down)
    20.  
    21. private var xDeg = 0.0;
    22. private var yDeg = 0.0;
    23. private var currentDistance;
    24. private var desiredDistance;
    25. private var correctedDistance;
    26. private var rotateBehind = false;
    27.  
    28. @script AddComponentMenu("Camera-Control/Third Person Camera Orbit (MMORPG Like)")
    29.  
    30. function Start ()
    31. {
    32.     var angles:Vector3 = transform.eulerAngles;
    33.     xDeg = angles.x;
    34.     yDeg = angles.y;
    35.     currentDistance = distance;
    36.     desiredDistance = distance;
    37.     correctedDistance = distance;
    38.    
    39.     // Make the rigid body not change rotation
    40.     if (rigidbody)
    41.         rigidbody.freezeRotation = true;
    42.        
    43.     if (lockToRearOfTarget)
    44.         rotateBehind = true;
    45.  }
    46.    
    47. //Only Move camera after everything else has been updated
    48. function LateUpdate ()
    49. {
    50.     // Don't do anything if target is not defined
    51.     if (!target)
    52.         return;
    53.    
    54.     var vTargetOffset:Vector3;
    55.        
    56.      
    57.     // If either mouse buttons are down, let the mouse govern camera position
    58.     if (GUIUtility.hotControl == 0)
    59.     {
    60.         if (Input.GetMouseButton(0) || Input.GetMouseButton(1))
    61.         {
    62.             //Check to see if mouse input is allowed on the axis
    63.             if (allowMouseInputX)
    64.                 xDeg += Input.GetAxis ("Mouse X") * xSpeed * 0.02;
    65.             else
    66.                 RotateBehindTarget();
    67.             if (allowMouseInputY)
    68.                 yDeg -= Input.GetAxis ("Mouse Y") * ySpeed * 0.02;
    69.            
    70.             //Interrupt rotating behind if mouse wants to control rotation
    71.             if (!lockToRearOfTarget)
    72.                 rotateBehind = false;
    73.         }
    74.        
    75.         // otherwise, ease behind the target if any of the directional keys are pressed
    76.         else if (Input.GetAxis("Vertical") != 0 || Input.GetAxis("Horizontal") != 0 || rotateBehind)
    77.         {
    78.             RotateBehindTarget();
    79.         }
    80.     }
    81.     yDeg = ClampAngle (yDeg, yMinLimit, yMaxLimit);
    82.  
    83.     // Set camera rotation
    84.     var rotation:Quaternion = Quaternion.Euler (yDeg, xDeg, 0);
    85.  
    86.     // Calculate the desired distance
    87.     desiredDistance -= Input.GetAxis ("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs (desiredDistance);
    88.     desiredDistance = Mathf.Clamp (desiredDistance, minDistance, maxDistance);
    89.     correctedDistance = desiredDistance;
    90.  
    91.     // Calculate desired camera position
    92.     vTargetOffset = Vector3 (0, -targetHeight, 0);
    93.     var position:Vector3 = target.position - (rotation * Vector3.forward * desiredDistance + vTargetOffset);
    94.  
    95.     // Check for collision using the true target's desired registration point as set by user using height
    96.     var collisionHit:RaycastHit;
    97.     var trueTargetPosition:Vector3 = Vector3 (target.position.x, target.position.y + targetHeight, target.position.z);
    98.  
    99.     // If there was a collision, correct the camera position and calculate the corrected distance
    100.     var isCorrected = false;
    101.     if (Physics.Linecast (trueTargetPosition, position, collisionHit, collisionLayers))
    102.     {
    103.         // Calculate the distance from the original estimated position to the collision location,
    104.         // subtracting out a safety "offset" distance from the object we hit.  The offset will help
    105.         // keep the camera from being right on top of the surface we hit, which usually shows up as
    106.         // the surface geometry getting partially clipped by the camera's front clipping plane.
    107.         correctedDistance = Vector3.Distance (trueTargetPosition, collisionHit.point) - offsetFromWall;
    108.         isCorrected = true;
    109.     }
    110.  
    111.     // For smoothing, lerp distance only if either distance wasn't corrected, or correctedDistance is more than currentDistance
    112.     currentDistance = !isCorrected || correctedDistance > currentDistance ? Mathf.Lerp (currentDistance, correctedDistance, Time.deltaTime * zoomDampening) : correctedDistance;
    113.  
    114.     // Keep within limits
    115.     currentDistance = Mathf.Clamp (currentDistance, minDistance, maxDistance);
    116.  
    117.     // Recalculate position based on the new currentDistance
    118.     position = target.position - (rotation * Vector3.forward * currentDistance + vTargetOffset);
    119.    
    120.     //Finally Set rotation and position of camera
    121.     transform.rotation = rotation;
    122.     transform.position = position;
    123. }
    124.  
    125. function RotateBehindTarget()
    126. {
    127.     var targetRotationAngle:float = target.eulerAngles.y;
    128.     var currentRotationAngle:float = transform.eulerAngles.y;
    129.     xDeg = Mathf.LerpAngle (currentRotationAngle, targetRotationAngle, rotationDampening * Time.deltaTime);
    130.    
    131.     // Stop rotating behind if not completed
    132.     if (targetRotationAngle == currentRotationAngle)
    133.     {
    134.         if (!lockToRearOfTarget)
    135.             rotateBehind = false;
    136.     }
    137.     else
    138.         rotateBehind = true;
    139.  
    140. }
    141.  
    142.  
    143. static function ClampAngle (angle : float, min : float, max : float)
    144. {
    145.    if (angle < -360)
    146.       angle += 360;
    147.    if (angle > 360)
    148.       angle -= 360;
    149.    return Mathf.Clamp (angle, min, max);
    150. }
    151.  
     
  43. nevaran

    nevaran

    Joined:
    May 21, 2010
    Posts:
    247
    best wowcamera for now, keep it up :)
     
  44. zergmouse

    zergmouse

    Joined:
    Jun 30, 2010
    Posts:
    216
    Something that would be good to see would be the ability to disable one of the mouse buttons for camera control. My example would be that I want to use the left mouse button to drag select on screen and for that I don’t want the camera to move. So I would want to disable the "move camera on left mouse click" ability. Currently I just go into the code and comment out lines of code untill it works.

    How hard would that be to implement?

    Also a question: I have my player setup like this. Container (with controller script) with two children. Child1 = A graphic and Child2 = a camera. the graphic is an animated avatar and the camera has the camera script on it. How do I play the animations on my avatar from the controller script on the parent game object? So if my walk animation is named "walk" how do I play it when I am walking?

    Code (csharp):
    1.       moveStatus = "idle";
    2.       if(moveDirection != Vector3.zero) {
    3.          moveStatus = isWalking ? "walking" : "running";
    4.          if (isWalking){
    5.            // invoke WALK animation here
    6.          } else {
    7.         // call RUN animation here
    8.          }
    9.       } else {
    10.         // call IDLE animation here
    11.       }
     
  45. Julian-Glenn

    Julian-Glenn

    Joined:
    Jul 23, 2010
    Posts:
    97
    Code (csharp):
    1. // Plays the walk animation - stops all other animations in the same layer
    2. animation.Play ("walk");
    3. // Plays the walk animation - stops all other animations
    4. animation.Play ("walk", PlayMode.StopAll);
    or use crossfade

    Code (csharp):
    1. // Fade the walk cycle in and fade all other animations in the same layer out.
    2. // Complete the fade within 0.2 seconds.
    3. animation.CrossFade("Walk", 0.2);
    4. // Makes a character contains a Run and Idle animation
    5. // fade between them when the player wants to move
    6. function Update ()
    7. {
    8. if (Mathf.Abs(Input.GetAxis("Vertical")) > 0.1)
    9. animation.CrossFade("Run");
    10. else
    11. animation.CrossFade("Idle");
    12. }
     
  46. Tilluss

    Tilluss

    Joined:
    Mar 5, 2010
    Posts:
    34
    If you needed to do it as a permanent change then you can just comment out the "Input.GetMouseButton(0)" as you are doing now. If you want it as more of an option you can just add in another public bool variable and check that it's true or false in the same place where the buttons are checked.
     
  47. CrossFadeR

    CrossFadeR

    Joined:
    Jul 27, 2010
    Posts:
    1
    sorry to revive the post.

    I need some help after reading again and again or try some script's appearing here I created my version of wow camera, but I could not make the player's control.

    if anyone can help me with this.

    I just want control of the character is identical or similar to "WoW" and tested with several e script but not given and the right one, I had to post because I come from a Hispanic speaking community Unity3D.


    thanks and hope you can guide or help me in this.
     
  48. bloodmuffin

    bloodmuffin

    Joined:
    Jul 28, 2010
    Posts:
    1
    Im using the code at the top of page 7 of this post and it has a place where you can put animations into the code, my model has animations but i do not know the code to put them in. can somebody help me?
     
  49. nevaran

    nevaran

    Joined:
    May 21, 2010
    Posts:
    247
    all of those scripts are not realy like the wow camera... :? im working on some of u guys's script(updating the needs) so ill post it in maybe a day or so :)
     
  50. nevaran

    nevaran

    Joined:
    May 21, 2010
    Posts:
    247
    all of those scripts are not realy like the wow camera... :? im working on some of u guys's script(updating the needs) so ill post it in maybe a day or so :)