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. ggunhouse

    ggunhouse

    Joined:
    Nov 18, 2009
    Posts:
    59
    Hi,
    I have used a script posted earlier in this thread by Paintbrush, but it's not working exactly as I'd like in the context in which I'm using it. If you think you can help, please read my description of the problem here:
    http://forum.unity3d.com/viewtopic.php?t=42984

    [Edit: maybe related to what GrimWare is talking about above?]
     
  2. baxter

    baxter

    Joined:
    Jul 4, 2009
    Posts:
    39
    Why when im try to attach the script in c# at my camera unity say.........has not finished compilation yet.................... :evil:
     
  3. baxter

    baxter

    Joined:
    Jul 4, 2009
    Posts:
    39
    Hey Guys i have Resolved my problem and i have Update the version in C# for the control of target when turn the camera and move the Target....Now you can with left Button rotate the camera around the player and with Right button rotate the target in the world,and if Press the left right button together you can move the target forward like WOW!
    missed only the collision with a GameObject and it's a mmorpg controller!
    !try it!
    :wink:


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

    trinitysj

    Joined:
    Jan 15, 2010
    Posts:
    54
    I get the same error as above cannot add it to my main camera. I would love to use this, as well, am i correct that this is a .cs script and not a .js script?

    thanks
     
  5. baxter

    baxter

    Joined:
    Jul 4, 2009
    Posts:
    39
    this script is written in c# not in javascript....is
    .cs.....not .js....
     
  6. Wox

    Wox

    Joined:
    Dec 14, 2009
    Posts:
    93
    About the collision, why not send a ray from the character to the camera, then put the camera on the collision point - some dist, just a thought. then u get that "popping" camera thats in wow when u get something in-front of the camera.
     
  7. dr-mad

    dr-mad

    Joined:
    Feb 15, 2010
    Posts:
    19
    hi im new to scripting in cs an js but i learning it

    my question is if i use the mouse button lets say te left mouse button then it my cursor springs to the middle of the screen how is this defined because i want to set that off just like the reall wow then the mouse stay visable and not move to the middle of the screen if i click

    can someone explain where i should look and try to fix this ??

    thanks for the time to read this ;)

    i figure it out i only have to delete this

    if(Input.GetMouseButton(1) || Input.GetMouseButton(0))
    Screen.lockCursor = true;
    else
    Screen.lockCursor = false;

    in the control script ;)
     
  8. vishesh-l

    vishesh-l

    Joined:
    Feb 14, 2010
    Posts:
    27
    hi,
    i tried to implement this,
    but b4 i ask my query,id like to know how the wow control is supposed to work(since i havent played wow)

    is this supposed to be like a keyboardless character control?

    1. the left button moves the: camera around the character-works fine

    2. right button rotates the character-works fine- but my character rotates without the walk animation(where in this script do i tell it to play walk animation when right mouse button is pressed...also what code to i write for this ,or instead should i just change the arrow keys to mouse click in my character animation script? )

    3. pressing both buttons moves the charater forward-again my character doesnt walk...
    4. my character goes thru the terrain when both mouse buttons are pressed(works fine with the arrow keys)

    5. just curious to know whats the purpose of the arrow keys in wow if its controlled entirely by mouse?
     
  9. Syflux

    Syflux

    Joined:
    Mar 1, 2010
    Posts:
    12
    Is it possible to have the WOW camera follow vertically as well? For example in a space game where the ship flies up the camera would point up and stay behind the ship. Any input would be of great help!
     
  10. Calledtogaming

    Calledtogaming

    Joined:
    Mar 2, 2010
    Posts:
    16
    I just want to give a personal thanks to everyone who was involved in making this code. I'm very new to scripting and I've been trying for two days to get this exact thing going. SO I really appreciate all the hard work. Now I just need to get a character that's not a cylinder so I can see where I'm facing, lol.

    Excellent Job!

    Edit: So, I found out that when I use the two mouse buttons together to move, I fall through the world. Is this a scripting error, or something else wrong with my scene? Doesn't happen with any other form of movement... only when I use both mouse buttons together.
     
  11. jin76

    jin76

    Joined:
    Mar 4, 2010
    Posts:
    364
    great script guys ^^ !!!!!!!

    i am just having issue with collision detection.when ever i try to go up a mountain i just go through it and sometime fall of the terrain. can some tell me how to fix. I am noob in scripting :oops:

    thanks in advance for all help
     
  12. ICS499

    ICS499

    Joined:
    Feb 20, 2010
    Posts:
    11
    This may or may not help somebody; hopefully it will.

    The way I have my game right now; the camera is quite far from the player, so when you go into a building things get funky. To fix this I made a script that would bring the camera close when you enter a trigger.It's probably not the cleanest code, or way to do it, but it works. I'm just doing this for a class project so it should do.

    You need to add this to WowCamera.cs:

    Code (csharp):
    1.  
    2.     public void setDistance(float dist) {
    3.         maxDistance = dist;
    4.         minDistance = dist;
    5.         distance = dist;
    6.     }
    7.    
    8.  
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class SwitchCam: MonoBehaviour {
    6. public float nearDist = 2.5f;
    7. public float farDist = 12.0f;
    8.    
    9.     IEnumerator OnTriggerEnter (Collider col) {
    10.         if(col.gameObject.tag == "Player") {
    11.             WowCamera wc;
    12.             wc = (WowCamera)FindObjectOfType (typeof(WowCamera));      
    13.  
    14.             float actualDist = (float)farDist;
    15.             while(nearDist <= actualDist) {
    16.                 actualDist -= 0.1f;
    17.                 if(actualDist > nearDist/2) yield return new WaitForSeconds(0.01f);
    18.                 if(actualDist < nearDist/2) yield return new WaitForSeconds(0.015f);
    19.                 wc.setDistance(actualDist);
    20.             }
    21.         }
    22.     }
    23.    
    24.    
    25.     IEnumerator OnTriggerExit(Collider col) {
    26.         if(col.gameObject.tag == "Player") {
    27.             WowCamera wc;
    28.             wc = (WowCamera)FindObjectOfType (typeof(WowCamera));      
    29.             float actualDist = (float)nearDist;
    30.             while(farDist >= actualDist) {
    31.                 actualDist += 0.1f;
    32.                 if(actualDist < farDist/2) yield return new WaitForSeconds(0.015f);
    33.                 if(actualDist > farDist/2) yield return new WaitForSeconds(0.01f);
    34.                 wc.setDistance(actualDist);
    35.             }
    36.         }
    37.     }
    38. }
    39.  
    Heres a Demo of it working; try walking into the cabin. Pardon the crappy models and whatnot.

    http://chaospanda.com/499/fireball.html
     
  13. Vimalakirti

    Vimalakirti

    Joined:
    Oct 12, 2009
    Posts:
    755
    To check for objects in the way, I did this:

    Code (csharp):
    1.     // Finally, POSITION the CAMERA:
    2. var position;
    3. position = target.position - (cameraZoomDummy.rotation * Vector3.forward * distance + Vector3(0,-targetHeight,0));
    4. transform.position = position;
    5.        
    6. // Is View Blocked ?
    7. var hit : RaycastHit;
    8. var trueTargetPosition : Vector3 = target.transform.position - Vector3(0,-targetHeight,0);
    9. // Cast the line to check:
    10. if (Physics.Linecast (trueTargetPosition, transform.position, hit)) {  
    11.     // If so, shorten distance so camera is in front of object:
    12.     distance = Vector3.Distance (trueTargetPosition, hit.point);
    13.     // Finally, rePOSITION the CAMERA:
    14.     position = target.position - (cameraZoomDummy.rotation * Vector3.forward * distance + Vector3(0,-targetHeight,0));
    15.     transform.position = position;
    16. }
    Notice I position it, then check. If something's in the way, I re-position it.

    It seems to work.
     
  14. Synthetique

    Synthetique

    Joined:
    Feb 27, 2010
    Posts:
    10
    First I want to say thank you guys for some great scipts. The movement and camera works perfectly imo. But there's have a slight problem with the mouse pointer when I try to click on my GUI buttons and sliders.
    When I click, the mouse snaps to the middle of the screen. What would be the best way to disable the camera scripts while clicking on GUIs? I'm not very experienced with GUI scripting so I don't really know where to start looking.
     
  15. Vimalakirti

    Vimalakirti

    Joined:
    Oct 12, 2009
    Posts:
    755
    Synth,

    That cursor-to-middle-of-screen business has to do with these two lines I think:
    Code (csharp):
    1.  
    2.    if(Input.GetMouseButton(1) || Input.GetMouseButton(0))
    3.       Screen.lockCursor = true;
    4.    else
    5.       Screen.lockCursor = false;
    6.  
    7.  
    I just took these lines out completely cause that popping to middle of the screen was making me crazy.
     
  16. Synthetique

    Synthetique

    Joined:
    Feb 27, 2010
    Posts:
    10

    Hi Vimalakirti. Thanks for the answer. I tried removing those lines, but then the camera became less responsive. The best solution imo would be for the scripts to ignore mouse inputs when they occur over a GUI element.
    I have an interface with buttons and sliders, so I want the camera and character scripts to ignore only the mouse input while clicking buttons or dragging sliders.

    I'll see if I can get it to work and post the result here. Though if someone more experienced knows a way, I'd be so grateful
     
  17. mattconley2011

    mattconley2011

    Joined:
    Feb 22, 2010
    Posts:
    105
    Has anyone fixed all the problems with this? if so, could you post the scripts needed?
    Thank You!
     
  18. Synthetique

    Synthetique

    Joined:
    Feb 27, 2010
    Posts:
    10
    It would be so easy to script this behaviour if I only knew how to check for GUI elements within OnMouseDown.
     
  19. Synthetique

    Synthetique

    Joined:
    Feb 27, 2010
    Posts:
    10
    I may have found something. It's late night here though so I won't be able to try this out until tomorrow night. Just thought I'd share:


    edit:

    Ok I had to try it quickly. It worked perfectly. ^^
    I edited the character controller code to look like this:
    Code (csharp):
    1. if (GUIUtility.hotControl == 0) {
    2.         if(Input.GetMouseButton(1) || Input.GetMouseButton(0))
    3.             Screen.lockCursor = true;
    4.         else
    5.             Screen.lockCursor = false;
    6.     }
    Also adding it to the camera script would make it somewhat like wow style.

    I put it here:
    Code (csharp):
    1.         if (GUIUtility.hotControl == 0) {
    2.             if (Input.GetMouseButton(0) || Input.GetMouseButton(1))
    3.             {
    4.                 xDeg += Input.GetAxis ("Mouse X") * xSpeed * 0.02f;
    5.                 yDeg -= Input.GetAxis ("Mouse Y") * ySpeed * 0.02f;
    6.             }
    7.        
    8.         // otherwise, ease behind the target if any of the directional keys are pressed
    9.             else if (Input.GetAxis("Vertical") != 0 || Input.GetAxis("Horizontal") != 0)
    10.             {
    11.                 float targetRotationAngle = target.eulerAngles.y;
    12.                 float currentRotationAngle = transform.eulerAngles.y;
    13.                 xDeg = Mathf.LerpAngle (currentRotationAngle, targetRotationAngle, rotationDampening * Time.deltaTime);
    14.             }
    15.         }
     
  20. mattconley2011

    mattconley2011

    Joined:
    Feb 22, 2010
    Posts:
    105
    ok, so i took a script form this post but im having problems, could someone post the scripts that work? please, and explain how to set everything up THANK YOU!!!!!
     
  21. Synthetique

    Synthetique

    Joined:
    Feb 27, 2010
    Posts:
    10
    First I added a layer called "Characters".
    Then I created an empty GameObject called "CamSpot" and dragged it into my character hierarchy. I want the camera to look at this gameobject because it is not animated, so the camera wont wobble.
    And then I put my character in the new Characters layer I just made.
    Then I put the Walker script on the character and tagged her as GameController.


    Then I put the WowCamera script on the camera and tagged it as MainCamera. In the cam script property Collision Layers, I unchecked "Characters". Then I set the CamSpot gameobject as the target.
     

    Attached Files:

  22. eviltenchi_84

    eviltenchi_84

    Joined:
    Feb 18, 2010
    Posts:
    99
    Code (csharp):
    1.  // calculate desired camera position
    2.         Vector3 position = target.position - (rotation * Vector3.forward * desiredDistance + new Vector3(0, -targetHeight, 0));
    Playing with the y and z values seems to reduce the clipping issue since you are changing the where unity thinks the camera is and not the actual position. Basically, the camera would calculate the collision too late and you could already see through a wall. With some tweaks, you can make it so Unity thinks the camera is hit earlier and thus apply the zoom to the player sooner.

    (0, -targetHeight + .05f, .05f) worked for me but I made it so the camera distance was static at 10.
     
  23. jin76

    jin76

    Joined:
    Mar 4, 2010
    Posts:
    364
    still not working :(.
     
  24. Vimalakirti

    Vimalakirti

    Joined:
    Oct 12, 2009
    Posts:
    755
    I'm not sure if anyone is using my method for keeping the camera in front of walls, but I made a minor adjustment. I put the new distance variable as tempDistance so that when the obstacle is passed, the camera goes back to where it was. This way, you don't need to re-scroll out to your favorite distance:


    Code (csharp):
    1.  
    2.    // Finally, POSITION the CAMERA:
    3. var position;
    4. position = target.position - (cameraZoomDummy.rotation * Vector3.forward * distance + Vector3(0,-targetHeight,0));
    5. transform.position = position;
    6.      
    7. // Is View Blocked ?
    8. var hit : RaycastHit;
    9. var trueTargetPosition : Vector3 = target.transform.position - Vector3(0,-targetHeight,0);
    10. // Cast the line to check:
    11. if (Physics.Linecast (trueTargetPosition, transform.position, hit)) {
    12.    // If so, shorten distance so camera is in front of object:
    13. //
    14. // new variable here:
    15. //
    16.    var tempDistance = Vector3.Distance (trueTargetPosition, hit.point);
    17.    // Finally, rePOSITION the CAMERA:
    18. //
    19. // with the new variable:
    20. //
    21.    position = target.position - (cameraZoomDummy.rotation * Vector3.forward * tempDistance + Vector3(0,-targetHeight,0));
    22.    transform.position = position;
    23. }
     
  25. pickledzebra

    pickledzebra

    Joined:
    Feb 25, 2010
    Posts:
    33
    Excellent thread! Thanks so much to the posters sharing their efforts.
     
  26. Deleted User

    Deleted User

    Guest


    Thanks works fine (I can move the mouse around and rotate the player).
    But when I click "w" to walk, unity is crashing.
    Please help, thanks
     
  27. Vimalakirti

    Vimalakirti

    Joined:
    Oct 12, 2009
    Posts:
    755
    I just wanted to post my scripts here because this thread has been so helpful to me.

    This is wow style camera control, using wasd or arrow keys to turn and move forward and backwards.

    LMB to turn camera
    RMB to turn character and camera
    scroll middle mouse wheel to zoom in and out

    Camera will stay in front of obstacles

    The animation script makes your character idle, walk, run, and jump appropriately.

    There's even a basic chat feature where you press enter to open a window, type in your line, then when you press enter again it appears above your character's head for a few seconds then disappears. You can get rid of this by removing the isTalking boolean where it comes up, and removing the entire OnGUI() function.

    It should be pretty much plug and play, ready to go.

    Camera Script (attach to main camera, then drag your player to "Target" slot in inspector window):
    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. var zoomRate = 20;
    12. var rotationDampening = 3.0;
    13. private var x = 0.0;
    14. private var y = 0.0;
    15. var isTalking:boolean = false;
    16.  
    17. @script AddComponentMenu("Camera-Control/WoW Camera")
    18.  
    19. function Start () {
    20.     var angles = transform.eulerAngles;
    21.     x = angles.y;
    22.     y = angles.x;
    23.  
    24.    // Make the rigid body not change rotation
    25.       if (rigidbody)
    26.       rigidbody.freezeRotation = true;
    27. }
    28.  
    29. function LateUpdate () {
    30.    if(!target)
    31.       return;
    32.    
    33.    // If either mouse buttons are down, let them govern camera position
    34.    if (Input.GetMouseButton(0) || (Input.GetMouseButton(1))){
    35.    x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
    36.    y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
    37.    
    38.    
    39.    // otherwise, ease behind the target if any of the directional keys are pressed
    40.    } else if(Input.GetAxis("Vertical") || Input.GetAxis("Horizontal")) {
    41.       var targetRotationAngle = target.eulerAngles.y;
    42.       var currentRotationAngle = transform.eulerAngles.y;
    43.       x = Mathf.LerpAngle(currentRotationAngle, targetRotationAngle, rotationDampening * Time.deltaTime);
    44.     }
    45.      
    46.  
    47.    distance -= (Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime) * zoomRate * Mathf.Abs(distance);
    48.    distance = Mathf.Clamp(distance, minDistance, maxDistance);
    49.    
    50.    y = ClampAngle(y, yMinLimit, yMaxLimit);
    51.    
    52.   // ROTATE CAMERA:
    53.    var rotation:Quaternion = Quaternion.Euler(y, x, 0);
    54.    transform.rotation = rotation;
    55.    
    56.    // POSITION CAMERA:
    57.    var position = target.position - (rotation * Vector3.forward * distance + Vector3(0,-targetHeight,0));
    58.    transform.position = position;
    59.    
    60.     // IS VIEW BLOCKED?
    61.     var hit : RaycastHit;
    62.     var trueTargetPosition : Vector3 = target.transform.position - Vector3(0,-targetHeight,0);
    63.     // Cast the line to check:
    64.     if (Physics.Linecast (trueTargetPosition, transform.position, hit)) {  
    65.         // If so, shorten distance so camera is in front of object:
    66.         var tempDistance = Vector3.Distance (trueTargetPosition, hit.point) - 0.28;
    67.         // Finally, rePOSITION the CAMERA:
    68.         position = target.position - (rotation * Vector3.forward * tempDistance + Vector3(0,-targetHeight,0));
    69.         transform.position = position;
    70.     }
    71. }
    72.  
    73. static function ClampAngle (angle : float, min : float, max : float) {
    74.    if (angle < -360)
    75.       angle += 360;
    76.    if (angle > 360)
    77.       angle -= 360;
    78.    return Mathf.Clamp (angle, min, max);
    79.    
    80. }
    Controller script (attach to player. Player must also have a character controller component):

    Code (csharp):
    1. // Movement Variables:
    2. private var jumpSpeed:float = 9.0;
    3. private var gravity:float = 20.0;
    4. private var runSpeed:float = 5.0;
    5. private var walkSpeed:float = 1.7;
    6. private var rotateSpeed:float = 150.0;
    7. private var grounded:boolean = false;
    8. private var moveDirection:Vector3 = Vector3.zero;
    9. private var isWalking:boolean = true;
    10. private var moveStatus:String = "idle";
    11. private var xSpeed = 250.0;
    12. private var ySpeed = 120.0;
    13. private var yMinLimit = -40;
    14. private var yMaxLimit = 80;
    15. private var x = 0.0;
    16. private var y = 0.0;
    17.  
    18. // Chat Variables:
    19. public var isTalking:boolean = false;
    20. public var playerChatBubble:boolean = false;
    21. public var commandLine:String = "";
    22.  
    23. // Script Variables
    24. private var anim;
    25.  
    26. // ------------------------------------------------------------------ AWAKE ! ---------------------
    27. function Awake(){
    28.     // Load Script Variables:
    29.     anim = GetComponent (Animations);
    30. }
    31.  
    32. // -------------------------------------------------------- KEYBOARD INPUT DETECT ------------
    33. function OnGUI () {
    34.     if (Event.current.Equals (Event.KeyboardEvent ("return")) )
    35.             {
    36.             print("return pressed");
    37.             isTalking = !isTalking;
    38.             var cameraObject = GameObject.FindWithTag("MainCamera");
    39.             var cameraScript : MyCamera = cameraObject.GetComponent(MyCamera);
    40.             cameraScript.isTalking = isTalking;
    41.     }
    42.     if(isTalking){
    43.             GUI.SetNextControlName ("ChatField");
    44.             commandLine = GUI.TextField (Rect (10, Screen.height - 32, 600, 20), commandLine, 25);
    45.             GUI.FocusControl ("ChatField");
    46.             }
    47.    
    48.  
    49.     if (commandLine!="")
    50.             {
    51.                 print("going to the function");
    52.                 timeSaid = Time.time;
    53.                 playerChatBubble = true;
    54.                 entering = GetComponent(TextEnter);
    55.                 entering.timeSaid = Time.time;
    56.                 entering.EnterText();
    57.             }
    58.     if(playerChatBubble){
    59.         entering = GetComponent(TextEnter);
    60.         entering.PlayerChatBubble();
    61.     }
    62. }; 
    63.  
    64. // -------------------------------------------------------------------------------------------------------------
    65. // ----------------------------------------------------------- UPDATE ---------------------------------------
    66. // -------------------------------------------------------------------------------------------------------------
    67.  
    68. function Update () {
    69. if(!isTalking){                 // <---- !isTalking
    70.    //
    71.    // Only allow movement and jumps while -----------------  GROUNDED -------------
    72.    if(grounded) {
    73.         moveDirection = new Vector3((Input.GetMouseButton(1) ? Input.GetAxis("Horizontal") : 0),0,Input.GetAxis("Vertical"));
    74.        
    75.         // if moving forward and to the side at the same time, compensate for distance
    76.         // TODO: may be better way to do this?
    77.         if(Input.GetMouseButton(1)  Input.GetAxis("Horizontal")  Input.GetAxis("Vertical")) {
    78.             moveDirection *= .7;
    79.         }
    80.        
    81.         moveDirection = transform.TransformDirection(moveDirection);
    82.         moveDirection *= isWalking ? walkSpeed : runSpeed;
    83.        
    84.         moveStatus = "idle";
    85.         if(moveDirection != Vector3.zero) {
    86.             moveStatus = isWalking ? "walking" : "running";
    87.             if (isWalking){
    88.                 anim.Walk();
    89.             } else {
    90.                 anim.Run();
    91.             }
    92.         } else {
    93.             anim.Idle();
    94.         }
    95.         // Jump!
    96.         if(Input.GetButton("Jump"))
    97.         {
    98.             anim.Jump();
    99.             moveDirection.y = jumpSpeed;
    100.         }
    101.     }                                                                   // END "IS GROUNDED"
    102. }                                                                       // END "!TALKING"
    103.     // Allow turning at anytime. Keep the character facing in the same direction as the Camera if the right mouse button is down.
    104.     if(Input.GetMouseButton(1)) {
    105.         transform.rotation = Quaternion.Euler(0,Camera.main.transform.eulerAngles.y,0);
    106.     } else {
    107.         transform.Rotate(0,Input.GetAxis("Horizontal") * rotateSpeed * Time.deltaTime, 0);
    108.     }
    109.    
    110.     // Toggle walking/running with the T key
    111.     if(Input.GetKeyDown("t"))
    112.         isWalking = !isWalking;
    113.        
    114.     //Apply gravity
    115.     moveDirection.y -= gravity * Time.deltaTime;
    116.     //Move controller
    117.     var controller:CharacterController = GetComponent(CharacterController);
    118.     var flags = controller.Move(moveDirection * Time.deltaTime);
    119.     grounded = (flags  CollisionFlags.Below) != 0;
    120.     };
    121.     static function ClampAngle (angle : float, min : float, max : float) {
    122.    if (angle < -360)
    123.       angle += 360;
    124.    if (angle > 360)
    125.       angle -= 360;
    126.    return Mathf.Clamp (angle, min, max);
    127. }
    128.  
    129. // -------------------------------------------------------------------------------------------------------------
    130. // ----------------------------------------------------------- END UPDATE  --------------------------------
    131. // -------------------------------------------------------------------------------------------------------------
    132.  
    133. @script RequireComponent(CharacterController)
    And the Animation script (attach to player):

    Code (csharp):
    1. // "Animations.js" -- Animation controller script
    2. //
    3. function Start () {
    4.     animation.wrapMode = WrapMode.Loop;
    5. //  animation["jump"].wrapMode = WrapMode.Once;
    6. //  animation["sit"].wrapMode = WrapMode.Once;
    7.     animation.Stop();
    8.     Idle();
    9. }
    10.  
    11. function Walk() {
    12.     animation.CrossFade("walk", 0.3);
    13. }
    14.  
    15. function Run () {
    16.       animation.CrossFade("run", 0.3);
    17. }
    18.  
    19. function Idle () {
    20.     animation.CrossFade("idle", 0.3);
    21. }
    22.  
    23. function Jump () {
    24.     animation.CrossFade("jump", 0.3);
    25. }

    Thanks everyone for all their posts and help. I hope this helps people, too!
     
  28. RickP

    RickP

    Joined:
    Apr 4, 2010
    Posts:
    262
    I'm getting an error in the player script.

    The name 'MyCamera' does not denote a valid type.

    This looks amazingly promising. I would love to get this error fixed and just use this besides my other thread camera :)


    Also, doesn't look like you have strafing in this?
     
  29. Vimalakirti

    Vimalakirti

    Joined:
    Oct 12, 2009
    Posts:
    755
    Did you title the camera script "MyCamera"? A different name could make the error.

    Also, just to be sure, all these are written in JS, not c#.
     
  30. RickP

    RickP

    Joined:
    Apr 4, 2010
    Posts:
    262
    Cool, I got this working. It's very cool! A strafe would be ideal I think, but thank you for posting this. It'll be very helpful for lots of people!
     
  31. BlackMantis

    BlackMantis

    Joined:
    Feb 7, 2010
    Posts:
    1,475
    I'm gettin an error for the unknown identifier TextEnter.
    :?:
     
  32. Cursed

    Cursed

    Joined:
    Apr 1, 2010
    Posts:
    7
    Hey, I used your WoW camera scripts before it worked.
    And now its not working. I get some error's.
    Can you guys help me? tutorial or something?
     
  33. Vimalakirti

    Vimalakirti

    Joined:
    Oct 12, 2009
    Posts:
    755
    Mantis:
    TextEnter is a variable in the camera script as well as the character controller. You need to use both of them if you want to use that feature. If you don't want that chat feature (rather useless without multi-player) then remove it wherever it occurs. Take out the whole OnGui function, and when you get that error, double click on the error (which will take you to the line of code where it happened) and take out the textEnter variable there, until they're all gone. It's basic debugging.

    Cursed:
    If you post the errors, maybe we can help.
     
  34. Cursed

    Cursed

    Joined:
    Apr 1, 2010
    Posts:
    7
    Hey :) Ermm I sort of fixed it..
    But you know when you use the right mouse button to turn how would I change the code so that when I turn and then press W the character walks where I've moved the camera to point like the real wow :)
     
  35. Cursed

    Cursed

    Joined:
    Apr 1, 2010
    Posts:
    7
    Im getting another error.
    you guys got any idea?
    Code (csharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2. Boo.Lang.Runtime.RuntimeServices.Dispatch (System.Object target, System.String cacheKeyName, System.Type[] cacheKeyTypes, System.Object[] args, Boo.Lang.Runtime.DispatcherFactory factory) [0x00000]
    3. Boo.Lang.Runtime.RuntimeServices.Dispatch (System.Object target, System.String cacheKeyName, System.Object[] args, Boo.Lang.Runtime.DispatcherFactory factory) [0x00000]
    4. Boo.Lang.Runtime.RuntimeServices.Invoke (System.Object target, System.String name, System.Object[] args) [0x00000]
    5. UnityScript.Lang.UnityRuntimeServices.Invoke (System.Object target, System.String name, System.Object[] args, System.Type scriptBaseType) [0x00000]
    6. ThirdPersonWalker.Update ()   (at Assets\ThirdPersonWalker.js:63)
     
  36. Vimalakirti

    Vimalakirti

    Joined:
    Oct 12, 2009
    Posts:
    755
    Cursed:
    For my set up, right mouse button turns the character, and w does make him walk forward at the same time.

    For your errors, it says it's a NullReferenceException which means it didn't find what it was looking for. Down a bit it says "(at Assets\ThirdPersonWalker.js:63)" Which means this happens at line 63 in your ThirdPersonWalker script. I need to know what that line is to help you with your dilemma.
     
  37. Cursed

    Cursed

    Joined:
    Apr 1, 2010
    Posts:
    7
    Mine dosent do this it just walks forward as normal :(
    The error stop when I tick is talking and the other one below it. But I close unity re open and.. Its gone :S

    Something realy wierd is going on.
    Have you got any ideas?
    Im using the free/Indie version of unity..
     
  38. Vimalakirti

    Vimalakirti

    Joined:
    Oct 12, 2009
    Posts:
    755
    Are you using the scripts exactly as I posted them? If not, could you post your scripts?
     
  39. Cursed

    Cursed

    Joined:
    Apr 1, 2010
    Posts:
    7
    Yea there exactly as you posted.

    Also I tried to remove the onGUI() thing in the script and I got an error.
    So I replaced it and its still giving me the error :/

    Can you show me what exactly to do?

    I am using a capsule as my character, and the main camera, I added the rigid body Character Controller.
    I've grouped them together and I've added the scripts to the capsule and the camera.
     
  40. Vimalakirti

    Vimalakirti

    Joined:
    Oct 12, 2009
    Posts:
    755
    I'm doing a test and it's buggy, all right.

    Stay tuned.
     
  41. Vimalakirti

    Vimalakirti

    Joined:
    Oct 12, 2009
    Posts:
    755
    Okay. I've distilled the WoW style Camera script and character controller down to their most basic elements and have tested them. Here it is with instructions:

    1) Create your "player" object. This can be a simple cube. Click on the cube, click on Component > Physics > Character Controller. When it says "A BoxCollider is already added, do you want to replace it with a CharacterController" click Yes.

    2) Create a new Java Script. Rename it "Controller" and copy and paste this code to that script and save it:

    Code (csharp):
    1. // Movement Variables:
    2. private var jumpSpeed:float = 9.0;
    3. private var gravity:float = 20.0;
    4. private var runSpeed:float = 5.0;
    5. private var walkSpeed:float = 1.7;
    6. private var rotateSpeed:float = 150.0;
    7. private var grounded:boolean = false;
    8. private var moveDirection:Vector3 = Vector3.zero;
    9. private var isWalking:boolean = true;
    10. private var moveStatus:String = "idle";
    11. private var xSpeed = 250.0;
    12. private var ySpeed = 120.0;
    13. private var yMinLimit = -40;
    14. private var yMaxLimit = 80;
    15. private var x = 0.0;
    16. private var y = 0.0;
    17.  
    18.  
    19. // -------------------------------------------------------------------------------------------------------------
    20. // ----------------------------------------------------------- UPDATE ---------------------------------------
    21. // -------------------------------------------------------------------------------------------------------------
    22.  
    23. function Update () {
    24.    //
    25.    // Only allow movement and jumps while -----------------  GROUNDED -------------
    26.    if(grounded) {
    27.         moveDirection = new Vector3((Input.GetMouseButton(1) ? Input.GetAxis("Horizontal") : 0),0,Input.GetAxis("Vertical"));
    28.        
    29.         // if moving forward and to the side at the same time, compensate for distance
    30.         // TODO: may be better way to do this?
    31.         if(Input.GetMouseButton(1)  Input.GetAxis("Horizontal")  Input.GetAxis("Vertical")) {
    32.             moveDirection *= .7;
    33.         }
    34.        
    35.         moveDirection = transform.TransformDirection(moveDirection);
    36.         moveDirection *= isWalking ? walkSpeed : runSpeed;
    37.        
    38.         moveStatus = "idle";
    39.         if(moveDirection != Vector3.zero) {
    40.             moveStatus = isWalking ? "walking" : "running";
    41.             if (isWalking){
    42.                 // invoke WALK animation here
    43.             } else {
    44.                 // call RUN animation here
    45.             }
    46.         } else {
    47.             // call IDLE animation here
    48.         }
    49.         // Jump!
    50.         if(Input.GetButton("Jump"))
    51.         {
    52.             // call JUMP animation here
    53.             moveDirection.y = jumpSpeed;
    54.         }
    55.     }                                                                   // END "IS GROUNDED"
    56.    
    57.     // Allow turning at anytime. Keep the character facing in the same direction as the Camera if the right mouse button is down.
    58.     if(Input.GetMouseButton(1)) {
    59.         transform.rotation = Quaternion.Euler(0,Camera.main.transform.eulerAngles.y,0);
    60.     } else {
    61.         transform.Rotate(0,Input.GetAxis("Horizontal") * rotateSpeed * Time.deltaTime, 0);
    62.     }
    63.    
    64.     // Toggle walking/running with the T key
    65.     if(Input.GetKeyDown("t"))
    66.         isWalking = !isWalking;
    67.        
    68.     //Apply gravity
    69.     moveDirection.y -= gravity * Time.deltaTime;
    70.     //Move controller
    71.     var controller:CharacterController = GetComponent(CharacterController);
    72.     var flags = controller.Move(moveDirection * Time.deltaTime);
    73.     grounded = (flags  CollisionFlags.Below) != 0;
    74.     };
    75.     static function ClampAngle (angle : float, min : float, max : float) {
    76.    if (angle < -360)
    77.       angle += 360;
    78.    if (angle > 360)
    79.       angle -= 360;
    80.    return Mathf.Clamp (angle, min, max);
    81. }
    82.  
    83. // -------------------------------------------------------------------------------------------------------------
    84. // ----------------------------------------------------------- END UPDATE  --------------------------------
    85. // -------------------------------------------------------------------------------------------------------------
    86.  
    87. @script RequireComponent(CharacterController)
    3) Drag and drop that script onto your player (cube).

    4) Create a new Java Script. Rename it "MyCamera" and copy and paste this code to that script and save it:

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

    6) Click once on that Main Camera so that you can see the components in the Inspector window. In the MyCamera Script, there is a variable called "Target." Drag and drop your player or cube into that slot.

    7) Press Play.

    Make sure there's a light in your scene and some other objects so you can see your character / cube moving around.

    There are comments in the Controller script telling you where to call your animations if you have any (idle, walk, run, jump).
     
  42. Cor1312

    Cor1312

    Joined:
    Apr 12, 2010
    Posts:
    34
    Thanks for posting this awesome script. I tried it out and it looks great.

    I'm trying to port it to C# right now and I'm having problems with this line:

    else if(Input.GetAxis("Vertical") || Input.GetAxis("Horizontal"))

    Return value for Input.GetAxis() should be float. What exactly is being compared in this statement?
     
  43. RickP

    RickP

    Joined:
    Apr 4, 2010
    Posts:
    262
    If you had to add a strafe to this script when the Q E keys, how would you go about doing that?
     
  44. Vimalakirti

    Vimalakirti

    Joined:
    Oct 12, 2009
    Posts:
    755
    jianwei.jwtan:
    Please post your progress with the C# version. I am moving my coding from JS to C# and am not good enough yet to do these controllers, and that's causing some problems. Thanks.

    Perhaps JS will return true for a float if it is > 0.0. I assume that C# wants something to be definitely true, so try re-writing it like this:

    Code (csharp):
    1. else if(Input.GetAxis("Vertical") > 0.01 || Input.GetAxis("Horizontal") > 0.01)
    The threshold of 0.01 might need to be adjusted, but see if that get's rid of the error.

    Rick:
    That's a little involved. You would set up your keys so that you could use a line
    Code (csharp):
    1. if(Input.GetAxis("StrafeLeft"))
    which would trigger a few things:
    If character isn't already moving, then it would create move direction to his left or right, with a move speed of run or walk. Then it would move the character while turning the character in the direction he's moving, but WITHOUT turning the camera, and would have the character facing forward again when you stopped strafing. You would also want to trigger a strafe animation.

    If the character is already moving, it would modify the move direction at a diagonal left or right, WITHOUT turning the character.

    There would be a few sub routines to take care of. I would love to solve this problem, but won't have time to take it on for a while.

    Perhaps others can help?
    :roll:
     
  45. RickP

    RickP

    Joined:
    Apr 4, 2010
    Posts:
    262
    Actually I was able to modify what you had to fit my needs of strafing, but removed things like the left mouse button moving things around which for my current needs is what I want. Maybe I'll look at it more if I require the exact 3rd person controls.

    I was just talking about strafing because that's how WoW works and the thread says WoW movement.

    Thanks
     
  46. Cor1312

    Cor1312

    Joined:
    Apr 12, 2010
    Posts:
    34
    I tried using:
    Code (csharp):
    1. Input.GetAxis("Vertical") != 0
    This seems to work.

    I will post the rest of my code when I've finished, still working on porting the movement controls at the moment.
     
  47. susantio

    susantio

    Joined:
    Jul 14, 2009
    Posts:
    100
    Vimalakirti: Thank you so much for sharing this script. Is it possible when the character rotate to trigger a specific animation (a rotate animation). and also the same with walking backward (a backward animation), it would also be cool to have a different speed when walking backward as well. I'm fairly new to scripting so any help is much appreciated.
     
  48. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    Vimalakirti, your script is really nice, and works great. Before I had a system of grouped empty game objects for dealing with camera rotation and I'm glad a much more elegant solution was found. Thanks again for posting this!
     
  49. Deleted User

    Deleted User

    Guest

    Thanks for the script.

    Is it possible to add keys for Q/E. To walk left and right?

    Thanks
     
  50. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    Actually, im getting some weird issues with the camera collision. Seems to work ok most of the time, but if I tilt the camera at the extremes (up and down) and jump while moving, I am getting weird flickering.

    Anyone else experience this? I'm modifying the script at bit as well to allow for strafing, and changing the way it operates, so now you just assign the movement script to your object and in the properties you can select which camera you want to follow your character. As opposed to having 2 scripts to have to assign.

    I really like the fact of not having to have nested empty game objects to control the rotation though, thats very nice and clean.

    I will post any progress I make on the script.