Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
This question was closed May 26, 2013 at 05:28 AM by robertbu for the following reason:

Potential broad discussion topic

avatar image
0
Question by XionXinX · May 26, 2013 at 02:15 AM · c#camera

Can someone help me understand this code.

I have been reading up on the Scripting Reference and using a calculator to see why some of these equations are useful once they are run through. I still can't fully understand how it is working. I know basic C# Syntax and I understand some of what it all does. I feel more like I am putting together code that I have previously seen do what I want, without actually understanding the code. Below is a some camera code I nabbed from a forum thread and have been trying to reverse engineer it to be able to write my own variant. Much Appreciated if you can help me out.

EDIT: I understand what the variables are doing, I understand what the different updates are accomplishing and so forth. I don't understand how the equations and if statements inside LateUpdate are accomplishing an orbiting "MMO Like" camera. I have a broad idea as to what each bit of code does, but what is actually doing escapes me. Vectors, Quaternions, Mathf functions and so forth are a tad abstract to me. I included the entire script so that if anyone wants to explain they can use the original variable names and so forth. Thank You

 using UnityEngine; 
 using System.Collections; 
 
 public class WowCamera : MonoBehaviour 
 { 
     public Transform target; 
     
     public float targetHeight = 1.7f; 
     public float distance = 5.0f;
     public float offsetFromWall = 0.1f;
 
     public float maxDistance = 20; 
     public float minDistance = .6f; 
 
     public float xSpeed = 200.0f; 
     public float ySpeed = 200.0f; 
 
     public int yMinLimit = -80; 
     public int yMaxLimit = 80; 
 
     public int zoomRate = 40; 
 
     public float rotationDampening = 3.0f; 
     public float zoomDampening = 5.0f; 
     
     public LayerMask collisionLayers = -1;
 
     private float xDeg = 0.0f; 
     private float yDeg = 0.0f; 
     private float currentDistance; 
     private float desiredDistance; 
     private float correctedDistance; 
 
     void Start () 
     { 
         Vector3 angles = transform.eulerAngles; 
         xDeg = angles.x; 
         yDeg = angles.y; 
 
         currentDistance = distance; 
         desiredDistance = distance; 
         correctedDistance = distance; 
 
         // Make the rigid body not change rotation 
         if (rigidbody) 
             rigidbody.freezeRotation = true; 
     } 
     
     /** 
      * Camera logic on LateUpdate to only update after all character movement logic has been handled. 
      */ 
     void LateUpdate () 
     { 
         Vector3 vTargetOffset;
         
        // Don't do anything if target is not defined 
         if (!target) 
             return; 
 
         // If either mouse buttons are down, let the mouse govern camera position 
         if (Input.GetMouseButton(0) || Input.GetMouseButton(1)) 
         { 
             xDeg += Input.GetAxis ("Mouse X") * xSpeed * 0.02f; 
             yDeg -= Input.GetAxis ("Mouse Y") * ySpeed * 0.02f; 
         } 
         // otherwise, ease behind the target if any of the directional keys are pressed 
         else if (Input.GetAxis("Vertical") != 0 || Input.GetAxis("Horizontal") != 0) 
         { 
             float targetRotationAngle = target.eulerAngles.y; 
             float currentRotationAngle = transform.eulerAngles.y; 
             xDeg = Mathf.LerpAngle (currentRotationAngle, targetRotationAngle, rotationDampening * Time.deltaTime); 
         } 
 
         yDeg = ClampAngle (yDeg, yMinLimit, yMaxLimit); 
 
         // set camera rotation 
         Quaternion rotation = Quaternion.Euler (yDeg, xDeg, 0); 
 
         // calculate the desired distance 
         desiredDistance -= Input.GetAxis ("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs (desiredDistance); 
         desiredDistance = Mathf.Clamp (desiredDistance, minDistance, maxDistance); 
         correctedDistance = desiredDistance; 
 
         // calculate desired camera position
         vTargetOffset = new Vector3 (0, -targetHeight, 0);
         Vector3 position = target.position - (rotation * Vector3.forward * desiredDistance + vTargetOffset); 
 
         // check for collision using the true target's desired registration point as set by user using height 
         RaycastHit collisionHit; 
         Vector3 trueTargetPosition = new Vector3 (target.position.x, target.position.y + targetHeight, target.position.z); 
 
         // if there was a collision, correct the camera position and calculate the corrected distance 
         bool isCorrected = false; 
         if (Physics.Linecast (trueTargetPosition, position, out collisionHit, collisionLayers.value)) 
         { 
             // calculate the distance from the original estimated position to the collision location,
             // subtracting out a safety "offset" distance from the object we hit.  The offset will help
             // keep the camera from being right on top of the surface we hit, which usually shows up as
             // the surface geometry getting partially clipped by the camera's front clipping plane.
             correctedDistance = Vector3.Distance (trueTargetPosition, collisionHit.point) - offsetFromWall; 
             isCorrected = true;
         }
 
         // For smoothing, lerp distance only if either distance wasn't corrected, or correctedDistance is more than currentDistance 
         currentDistance = !isCorrected || correctedDistance > currentDistance ? Mathf.Lerp (currentDistance, correctedDistance, Time.deltaTime * zoomDampening) : correctedDistance; 
 
         // keep within legal limits
         currentDistance = Mathf.Clamp (currentDistance, minDistance, maxDistance); 
 
         // recalculate position based on the new currentDistance 
         position = target.position - (rotation * Vector3.forward * currentDistance + vTargetOffset); 
         
         transform.rotation = rotation; 
         transform.position = position; 
     } 
 
     private static float ClampAngle (float angle, float min, float max) 
     { 
         if (angle < -360) 
             angle += 360; 
         if (angle > 360) 
             angle -= 360; 
         return Mathf.Clamp (angle, min, max); 
     } 
 } 
 
Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Thom Denick · May 26, 2013 at 02:24 AM 0
Share

Is there a specific question in there? You already have a ton of comments. You need to isolate exactly where are you confused and rephrase the question that specific part of the script.

avatar image XionXinX · May 26, 2013 at 02:35 AM 0
Share

Updated my post to further narrow in what my concerns are. Thanks

1 Reply

  • Sort: 
avatar image
1
Best Answer

Answer by robertbu · May 26, 2013 at 05:28 AM

I am heartened that someone wants to understand some code rather than have someone solve their problem for them (as so often happens on UA). On the other hand, UA is not setup for a discussion, which this question could turn into. In general discussions and broad how-too-like-topics similar this one belong on Unity Forums. So I'm going to take middle ground and add some addition comments to the LateUpdate() portion of the code and then close this answer.

 void LateUpdate () 
 { 
     Vector3 vTargetOffset;
  
     // Don't do anything if target is not defined because if we do, we will generate null reference
         // exceptions
     if (!target) 
         return; 
  
     // If either mouse buttons are down, let the mouse govern camera position 
     if (Input.GetMouseButton(0) || Input.GetMouseButton(1)) 
     { 
             // Get Input.GetAxis() will return values in the range of -1 to 1.  xDeg is the current
             //   'x' rotation based on the incremental 'X' mouse movemment.  This is a bit confusing
             //    since our 'x' mouse movement will control the rotation around the 'y' axis, and the 'y' 
             //    movement will control rotation around the 'x' axis, just as in the real world if 
             //    we were to spipe a cylinder from left to right we would cause it to rotate on the 
             //   'y' axis.  I probably would have swapped the names of xDeg and yDeg.
         xDeg += Input.GetAxis ("Mouse X") * xSpeed * 0.02f; 
         yDeg -= Input.GetAxis ("Mouse Y") * ySpeed * 0.02f; 
     } 
     // otherwise, ease behind the target if any of the directional keys are pressed 
     else if (Input.GetAxis("Vertical") != 0 || Input.GetAxis("Horizontal") != 0) 
     { 
             // We want to match the rotation of the camera to the rotation of target.
             //  The desired position is behind the target, so when the camera
             //  is in the desired rotation and position, it will be looking from the 
             //  back of the character facing the character.
         float targetRotationAngle = target.eulerAngles.y; 
         float currentRotationAngle = transform.eulerAngles.y;
             
             // This is a common but unintuitive and unconventional use of Lerp().  It takes approximately the 
             //  same small percentage bite towards the target rotation each frame.  As the current and and
             //  target become closer together, the same percentage is a smaller angle.  The result is an
             //  eased movement.  This line helps ease the camera from the current rotation to the 
             //  target/desired rotation over time.
         xDeg = Mathf.LerpAngle (currentRotationAngle, targetRotationAngle, rotationDampening * Time.deltaTime); 
     } 
     
         // Keeps the rotation around the 'x' axis within specified limits.
     yDeg = ClampAngle (yDeg, yMinLimit, yMaxLimit); 
  
     // Set camera rotation.  Note the use of 'yDeg' for the 'x' component, and 'xDeg' for the 'y' component
         //   as mentioned in the mouse movement code above.
     Quaternion rotation = Quaternion.Euler (yDeg, xDeg, 0); 
  
     // calculate the desired distance - The mouse scroll wheel will increase or decrease the desired distance
         //   of the camera from the character.  But that distance is clamped to the specified limits
     desiredDistance -= Input.GetAxis ("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs (desiredDistance); 
     desiredDistance = Mathf.Clamp (desiredDistance, minDistance, maxDistance); 
     correctedDistance = desiredDistance; 
  
         // Note the desired position of the camera is at the top of the head of the character. 
         //  The value is negated because the next line of code negates it again. 
     vTargetOffset = new Vector3 (0, -targetHeight, 0);
         
         // This calculates a vector from the back of the target the desired distance behind the 
         //   character and shifted up to the head.  Actually it calculates a vector from the front 
         //   down toward the feet, and then turns that vector around so that it is going out the 
         //   back and up.
     Vector3 position = target.position - (rotation * Vector3.forward * desiredDistance + vTargetOffset); 
  
     // check for collision using the true target's desired registration point as set by user using height 
     RaycastHit collisionHit; 
     Vector3 trueTargetPosition = new Vector3 (target.position.x, target.position.y + targetHeight, target.position.z); 
  
         // The Linecast() is to detect anything like walls between the desired position of the camera and the 
         //  target position.  If it find an object, it brings the camera closer to the target so that the camera 
         //  does not end up inside walls and (therefore wold clip out sections of the walls).
         
     // if there was a collision, correct the camera position and calculate the corrected distance 
     bool isCorrected = false; 
     if (Physics.Linecast (trueTargetPosition, position, out collisionHit, collisionLayers.value)) 
     { 
         // calculate the distance from the original estimated position to the collision location,
         // subtracting out a safety "offset" distance from the object we hit.  The offset will help
         // keep the camera from being right on top of the surface we hit, which usually shows up as
         // the surface geometry getting partially clipped by the camera's front clipping plane.
         correctedDistance = Vector3.Distance (trueTargetPosition, collisionHit.point) - offsetFromWall; 
         isCorrected = true;
     }
  
     // For smoothing, lerp distance only if either distance wasn't corrected, or correctedDistance is more than currentDistance 
     currentDistance = !isCorrected || correctedDistance > currentDistance ? Mathf.Lerp (currentDistance, correctedDistance, Time.deltaTime * zoomDampening) : correctedDistance;
         
         // The preceeding line of code can be rewritten as follows (which should be easier to understand):
         
         // if (!isCorrected || correctedDistance > currentDistance)
         //      currentDistance = Mathf.Lerp (currentDistance, correctedDistance, Time.deltaTime * zoomDampening);
         // else 
         //    currentDistance = correctedDistance;
         
         // Note the Lerp() here brings the camera to the correctedDistance over time and is similer to the 
         //  LerpAngle() above in that it is an eased movement.
  
    // keep the distance within specified limits
     currentDistance = Mathf.Clamp (currentDistance, minDistance, maxDistance); 
  
     // recalculate position based on the new currentDistance 
         //  This is the same calculation we saw just before the Linecast() only using 
         //  currentDistance instead of desiredDistance
     position = target.position - (rotation * Vector3.forward * currentDistance + vTargetOffset); 
  
     transform.rotation = rotation; 
     transform.position = position; 
 } 
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image XionXinX · May 26, 2013 at 05:38 AM 0
Share

Wow, thanks. I think I am starting to grasp a bit more of what it's actually doing. If I have any more $$anonymous$$d boggling code ($$anonymous$$d boggling to me) I will be sure to be very specific and try not to present it like this. Thank You!

Follow this Question

Answers Answers and Comments

14 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Multiple Cars not working 1 Answer

Implementing Scoring System 2 Answers

Why is my camera switching angles? 0 Answers

Functions via camera rotations... 1 Answer

UDP implementation in Unity, unable to send to two different machines 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges