- Home /
 
Mecanim and Camera Problems
Hello guys, here are some scripts,
TP_Camera
 using UnityEngine;
 using System.Collections;
 
 
 public class TP_Camera : MonoBehaviour {
     
     public static TP_Camera Instance;
     
     public Transform TargetLookAt;
     public float Distance = 5f;
     public float DistanceMin = 1f;
     public float DistanceMax = 35f;
     public float DistanceSmooth = 0.05f;
     public float DistanceResumeSmooth = 1f;
     public float X_MouseSensitivity = 5f;
     public float Y_MouseSensitivity = 5f;
     public float MouseWheelSensitivity = 7.5f;
     public float X_Smooth = 0.05f;
     public float Y_Smooth = 0.1f;
     public float Y_MinLimit = -45f;
     public float Y_MaxLimit = 90f;
     public float OcclusionDistanceStep = 0.5f;
     public int MaxOcclusionChecks = 10;
     
     
     
     
     private float MouseX = 0f;
     private float MouseY = 0f;
     private float velX = 0f;
     private float velY = 0f;
     private float velZ = 0f;
     private float velDistance = 0f;
     private float startDistance = 0f;
     private Vector3 position = Vector3.zero;
     private Vector3 desiredPosition = Vector3.zero;
     private float desiredDistance = 0f;
     private float distanceSmooth = 0f;
     private float preOccludedDistance = 0;
     
     
     
     
     
     
     void Awake()
     {
         Instance = this;
     }
     
     void Start() 
     {
         Distance = Mathf.Clamp(Distance, DistanceMin, DistanceMax);
         startDistance = Distance;
         Reset();
     }
     
     
     
     void LateUpdate() 
     {
         if (TargetLookAt == null)
             return;
         
         HandlePlayerInput();
         
         var count = 0;
         do
         {
             CalculateDesiredPosition ();
             count++;
         } 
         while(CheckIfOccluded (count));
         
         
         UpdatePosition();
     }
     
     void HandlePlayerInput()
     {
         var deadZone = 0.1f;
         
         //if (Input.GetMouseButton(1))
         //{ 
         //check for the right mouse button  is down or not. Now it is down and get Mouse Axis input
         MouseX += Input.GetAxis("Mouse X") * X_MouseSensitivity;
         MouseY -= Input.GetAxis("Mouse Y") * Y_MouseSensitivity;
         //}
         
         //Clamping limit of Mouse Y
         MouseY = Helper.ClampAngle(MouseY, Y_MinLimit, Y_MaxLimit);
         
         
         if (Input.GetAxis("Mouse ScrollWheel") < -deadZone || Input.GetAxis("Mouse ScrollWheel") > deadZone)
         {
             desiredDistance = Mathf.Clamp(Distance - Input.GetAxis("Mouse ScrollWheel") * MouseWheelSensitivity,
                                           DistanceMin, DistanceMax);
             
             preOccludedDistance = desiredDistance;
             distanceSmooth = DistanceSmooth;
             
             
         }
     }
     
     
     void CalculateDesiredPosition()
     { 
         ResetDesiredDistance ();
         
         // Evaluate Distance
         Distance = Mathf.SmoothDamp(Distance, desiredDistance, ref velDistance, distanceSmooth);
         
         //Calculate desired position
         desiredPosition = CalculatePosition(MouseY, MouseX, Distance);
     }
     
     Vector3 CalculatePosition(float rotationX, float rotationY, float distance)
     {
         Vector3 direction = new Vector3(0, 0, -distance);
         Quaternion rotation = Quaternion.Euler(rotationX, rotationY, 0);
         return TargetLookAt.position + rotation * direction;
         
     }
     
     bool CheckIfOccluded(int count)
     {
         var isOccluded = false;
         
         var nearestDistance = CheckCameraPoints (TargetLookAt.position, desiredPosition);
         
         if (nearestDistance != -1)
         {
             if (count < MaxOcclusionChecks) {
                 isOccluded = true;
                 Distance -= OcclusionDistanceStep;
                 ;
                 if (Distance < 0.3f)
                 {
                     Distance = 0.3f;
                 }
                 
             }
             else 
             {
                 Distance = nearestDistance - Camera.main.nearClipPlane;
                 if (Distance < DistanceMin)
                 {
                     Distance = nearestDistance - Camera.main.nearClipPlane;
                 }
             }
             
             desiredDistance = Distance;
             distanceSmooth = DistanceResumeSmooth;
             
         }
         
         if (isOccluded = false) 
         {
             Hider.Instance.Show ();
             return isOccluded;
         }
         
         if (Distance < 1f)
             Hider.Instance.Hide();
         else
             Hider.Instance.Show ();
         
         return isOccluded;
     }
     
     
     float CheckCameraPoints(Vector3 from, Vector3 to)
     {
         var nearestDistance = -1f;
         
         RaycastHit hitInfo;
         
         Helper.ClipPlanePoints clipPlanePoints = Helper.ClipPlaneAtNear (to);
         
         //Draw lines in editor 
         Debug.DrawLine(from, to + transform.forward * -camera.nearClipPlane, Color.red);
         Debug.DrawLine (from, clipPlanePoints.UpperLeft);
         Debug.DrawLine (from, clipPlanePoints.UpperRight);
         Debug.DrawLine (from, clipPlanePoints.LowerLeft);
         Debug.DrawLine (from, clipPlanePoints.LowerRight);
         
         Debug.DrawLine(clipPlanePoints.UpperLeft, clipPlanePoints.UpperRight, Color.green);
         Debug.DrawLine(clipPlanePoints.UpperRight, clipPlanePoints.LowerRight, Color.green);
         Debug.DrawLine(clipPlanePoints.LowerRight, clipPlanePoints.LowerLeft, Color.green);
         Debug.DrawLine(clipPlanePoints.LowerLeft, clipPlanePoints.UpperLeft, Color.green);
         
         if (Physics.Linecast (from, clipPlanePoints.UpperLeft, out hitInfo) && hitInfo.collider.tag != "Player")
             nearestDistance = hitInfo.distance;
         
         if (Physics.Linecast (from, clipPlanePoints.LowerLeft, out hitInfo) && hitInfo.collider.tag != "Player")
             if(hitInfo.distance < nearestDistance || nearestDistance == -1)
                 nearestDistance = hitInfo.distance;
         
         if (Physics.Linecast (from, clipPlanePoints.UpperRight, out hitInfo) && hitInfo.collider.tag != "Player")
             if(hitInfo.distance < nearestDistance || nearestDistance == -1)
                 nearestDistance = hitInfo.distance;
         
         if (Physics.Linecast (from, clipPlanePoints.LowerRight, out hitInfo) && hitInfo.collider.tag != "Player")
             if(hitInfo.distance < nearestDistance || nearestDistance == -1)
                 nearestDistance = hitInfo.distance;
         
         if (Physics.Linecast (from, to + transform.forward * -camera.nearClipPlane, out hitInfo) && hitInfo.collider.tag != "Player")
             if(hitInfo.distance < nearestDistance || nearestDistance == -1)
                 nearestDistance = hitInfo.distance;
         
         return nearestDistance;
     }
     
     void ResetDesiredDistance()
     {
         if (desiredDistance < preOccludedDistance) 
         {
             var pos = CalculatePosition (MouseY, MouseX, preOccludedDistance);
             var nearestDistance = CheckCameraPoints (TargetLookAt.position, pos);
             
             if(nearestDistance == -1 || nearestDistance > preOccludedDistance)
             {
                 desiredDistance = preOccludedDistance;
             }
         }
     }
     
     void UpdatePosition()
     {
         var posX = Mathf.SmoothDamp(position.x, desiredPosition.x, ref velX, X_Smooth);
         var posY = Mathf.SmoothDamp(position.y, desiredPosition.y, ref velY, Y_Smooth);
         var posZ = Mathf.SmoothDamp(position.z, desiredPosition.z, ref velZ, X_Smooth);
         position = new Vector3(posX, posY, posZ);
         transform.position = position;
         
         transform.LookAt(TargetLookAt);
     }
     
     public void Reset()
     {
         MouseX = 0f;
         MouseY = 10f;
         Distance = startDistance;
         desiredDistance = Distance;
         preOccludedDistance = Distance;
         
     }
     
     
     
     
     public static void UseExistingOrCreateNewMainCamera()
     {
         GameObject tempCamera;
         GameObject targetLookAt;
         TP_Camera myCamera;
         
         if( Camera.mainCamera != null)
         {
             tempCamera = Camera.mainCamera.gameObject;    
         }
         else
         {
             tempCamera = new GameObject("Main Camera");
             tempCamera.AddComponent("Camera");
             tempCamera.tag = "MainCamera";
             
         }
         
         tempCamera.AddComponent ("TP_Camera");
         myCamera = tempCamera.GetComponent ("TP_Camera") as TP_Camera;
         
         targetLookAt = GameObject.Find("targetLookAt") as GameObject;
         
         if(  targetLookAt == null)
         {
             targetLookAt = new GameObject("targetLookAt");
             targetLookAt.transform.position = Vector3.zero;
         }
         
         myCamera.TargetLookAt = targetLookAt.transform;
     }
 }
 
   
 
               Hider
 using UnityEngine;
 using System.Collections;
 
 public class Hider : MonoBehaviour {
 
     public static Hider Instance;
 
     public static SkinnedMeshRenderer renderer;
     private ParticleSystem parti;
 
     // Use this for initialization
     void Start () {
         Instance = this;
         renderer = GetComponent<SkinnedMeshRenderer> ();
         parti = GetComponent<ParticleSystem> ();
     }
     
     // Update is called once per frame
     void Update () {
     
     }
 
     public void Hide()
     {
         renderer.enabled = false;
         parti.enableEmission = true;
     }
 
     public void Show()
     {
         renderer.enabled = true;
         parti.enableEmission = false;
     }
 }
 
 
               Helper
 using UnityEngine;
 
 public static class Helper
 {
 
     public struct ClipPlanePoints
     {
         public Vector3 UpperLeft;
         public Vector3 UpperRight;
         public Vector3 LowerLeft;
         public Vector3 LowerRight;
     }
     public static float ClampAngle(float angle, float min, float max)
     { 
     
         do
         {
 
             if (angle < -360)
                 angle += 360;
 
             if (angle > 360)
                 angle -= 360;
 
 
         }while (angle < -360 || angle > 360);
 
         return Mathf.Clamp(angle, min, max);
     }
 
     public static ClipPlanePoints ClipPlaneAtNear(Vector3 pos)
     {
         var clipPlanePoints = new ClipPlanePoints();
 
         if (Camera.mainCamera == null)
             return clipPlanePoints;
 
         var transform = Camera.mainCamera.transform;
         var halfFOV = (Camera.mainCamera.fieldOfView / 2) * Mathf.Deg2Rad;
         var aspect = Camera.mainCamera.aspect;
         var distance = Camera.mainCamera.nearClipPlane;
         var height = distance * Mathf.Tan (halfFOV);
         var width = height * aspect;
 
         clipPlanePoints.LowerRight = pos + transform.right * width;
         clipPlanePoints.LowerRight -= transform.up * height;
         clipPlanePoints.LowerRight += transform.forward * distance;
 
         clipPlanePoints.LowerLeft = pos - transform.right * width;
         clipPlanePoints.LowerLeft -= transform.up * height;
         clipPlanePoints.LowerLeft += transform.forward * distance;
 
         clipPlanePoints.UpperRight = pos + transform.right * width;
         clipPlanePoints.UpperRight += transform.up * height;
         clipPlanePoints.UpperRight += transform.forward * distance;
 
         clipPlanePoints.UpperLeft = pos - transform.right * width;
         clipPlanePoints.UpperLeft += transform.up * height;
         clipPlanePoints.UpperLeft += transform.forward * distance;
 
         return clipPlanePoints;
     }
 
 }
 
 
 
               My scene test web player : https://dl.dropboxusercontent.com/u/103772852/New%20folder/New%20folder.html
if you play the game, you will understand my problem.
Camera is shaking. and the mecanim animartion gets stuck for no reason when running.
targetLookAt is a empty gameobject and my bad the script won't find it and i have to reference it in public.
The camera shakes and animation gets stuck, i first thought it was problem with my mecanim setup, then i used unities own tuto but it doesn't works either.
TP_Camera works great without rigidbody attached to the player and instead of mecanim character controller should be used.
Mecanim works great without TP_Camera script in Camera.
I spent 5 days working, and this is the only thing i can figure out. I have edited many lines changed it but all finally end up being the same problem.
Any pros there ?
By the way, here is The mecanim controller script, not edited and directly from unity.
 using UnityEngine;
 using System.Collections;
 
 // Require these components when using this script
 [RequireComponent(typeof (Animator))]
 [RequireComponent(typeof (CapsuleCollider))]
 [RequireComponent(typeof (Rigidbody))]
 public class BotControlScript : MonoBehaviour
 {
     [System.NonSerialized]                    
     public float lookWeight;                    // the amount to transition when using head look
     
     [System.NonSerialized]
     public Transform enemy;                        // a transform to Lerp the camera to during head look
     
     public float animSpeed = 1.5f;                // a public setting for overall animator animation speed
     public float lookSmoother = 3f;                // a smoothing setting for camera motion
     public bool useCurves;                        // a setting for teaching purposes to show use of curves
 
     
     private Animator anim;                            // a reference to the animator on the character
     private AnimatorStateInfo currentBaseState;            // a reference to the current state of the animator, used for base layer
     private AnimatorStateInfo layer2CurrentState;    // a reference to the current state of the animator, used for layer 2
     private CapsuleCollider col;                    // a reference to the capsule collider of the character
     
 
     static int idleState = Animator.StringToHash("Base Layer.Idle");    
     static int locoState = Animator.StringToHash("Base Layer.Locomotion");            // these integers are references to our animator's states
     static int jumpState = Animator.StringToHash("Base Layer.Jump");                // and are used to check state for various actions to occur
     static int jumpDownState = Animator.StringToHash("Base Layer.JumpDown");        // within our FixedUpdate() function below
     static int fallState = Animator.StringToHash("Base Layer.Fall");
     static int rollState = Animator.StringToHash("Base Layer.Roll");
     static int waveState = Animator.StringToHash("Layer2.Wave");
     
 
     void Start ()
     {
         // initialising reference variables
         anim = GetComponent<Animator>();                      
         col = GetComponent<CapsuleCollider>();                
         enemy = GameObject.Find("Enemy").transform;    
         if(anim.layerCount ==2)
             anim.SetLayerWeight(1, 1);
     }
     
     
     void FixedUpdate ()
     {
         float h = Input.GetAxis("Horizontal");                // setup h variable as our horizontal input axis
         float v = Input.GetAxis("Vertical");                // setup v variables as our vertical input axis
         anim.SetFloat("Speed", v);                            // set our animator's float parameter 'Speed' equal to the vertical input axis                
         anim.SetFloat("Direction", h);                         // set our animator's float parameter 'Direction' equal to the horizontal input axis        
         anim.speed = animSpeed;                                // set the speed of our animator to the public variable 'animSpeed'
         anim.SetLookAtWeight(lookWeight);                    // set the Look At Weight - amount to use look at IK vs using the head's animation
         currentBaseState = anim.GetCurrentAnimatorStateInfo(0);    // set our currentState variable to the current state of the Base Layer (0) of animation
         
         if(anim.layerCount ==2)        
             layer2CurrentState = anim.GetCurrentAnimatorStateInfo(1);    // set our layer2CurrentState variable to the current state of the second Layer (1) of animation
         
         
         // LOOK AT ENEMY
         
         // if we hold Alt..
         if(Input.GetButton("Fire2"))
         {
             // ...set a position to look at with the head, and use Lerp to smooth the look weight from animation to IK (see line 54)
             anim.SetLookAtPosition(enemy.position);
             lookWeight = Mathf.Lerp(lookWeight,1f,Time.deltaTime*lookSmoother);
         }
         // else, return to using animation for the head by lerping back to 0 for look at weight
         else
         {
             lookWeight = Mathf.Lerp(lookWeight,0f,Time.deltaTime*lookSmoother);
         }
         
         // STANDARD JUMPING
         
         // if we are currently in a state called Locomotion (see line 25), then allow Jump input (Space) to set the Jump bool parameter in the Animator to true
         if (currentBaseState.nameHash == locoState)
         {
             if(Input.GetButtonDown("Jump"))
             {
                 anim.SetBool("Jump", true);
             }
         }
         
         // if we are in the jumping state... 
         else if(currentBaseState.nameHash == jumpState)
         {
             //  ..and not still in transition..
             if(!anim.IsInTransition(0))
             {
                 if(useCurves)
                     // ..set the collider height to a float curve in the clip called ColliderHeight
                     col.height = anim.GetFloat("ColliderHeight");
                 
                 // reset the Jump bool so we can jump again, and so that the state does not loop 
                 anim.SetBool("Jump", false);
             }
             
             // Raycast down from the center of the character.. 
             Ray ray = new Ray(transform.position + Vector3.up, -Vector3.up);
             RaycastHit hitInfo = new RaycastHit();
             
             if (Physics.Raycast(ray, out hitInfo))
             {
                 // ..if distance to the ground is more than 1.75, use Match Target
                 if (hitInfo.distance > 1.75f)
                 {
                     
                     // MatchTarget allows us to take over animation and smoothly transition our character towards a location - the hit point from the ray.
                     // Here we're telling the Root of the character to only be influenced on the Y axis (MatchTargetWeightMask) and only occur between 0.35 and 0.5
                     // of the timeline of our animation clip
                     anim.MatchTarget(hitInfo.point, Quaternion.identity, AvatarTarget.Root, new MatchTargetWeightMask(new Vector3(0, 1, 0), 0), 0.35f, 0.5f);
                 }
             }
         }
         
         
         // JUMP DOWN AND ROLL 
         
         // if we are jumping down, set our Collider's Y position to the float curve from the animation clip - 
         // this is a slight lowering so that the collider hits the floor as the character extends his legs
         else if (currentBaseState.nameHash == jumpDownState)
         {
             col.center = new Vector3(0, anim.GetFloat("ColliderY"), 0);
         }
         
         // if we are falling, set our Grounded boolean to true when our character's root 
         // position is less that 0.6, this allows us to transition from fall into roll and run
         // we then set the Collider's Height equal to the float curve from the animation clip
         else if (currentBaseState.nameHash == fallState)
         {
             col.height = anim.GetFloat("ColliderHeight");
         }
         
         // if we are in the roll state and not in transition, set Collider Height to the float curve from the animation clip 
         // this ensures we are in a short spherical capsule height during the roll, so we can smash through the lower
         // boxes, and then extends the collider as we come out of the roll
         // we also moderate the Y position of the collider using another of these curves on line 128
         else if (currentBaseState.nameHash == rollState)
         {
             if(!anim.IsInTransition(0))
             {
                 if(useCurves)
                     col.height = anim.GetFloat("ColliderHeight");
                 
                 col.center = new Vector3(0, anim.GetFloat("ColliderY"), 0);
                 
             }
         }
         // IDLE
         
         // check if we are at idle, if so, let us Wave!
         else if (currentBaseState.nameHash == idleState)
         {
             if(Input.GetButtonUp("Jump"))
             {
                 anim.SetBool("Wave", true);
             }
         }
         // if we enter the waving state, reset the bool to let us wave again in future
         if(layer2CurrentState.nameHash == waveState)
         {
             anim.SetBool("Wave", false);
         }
     }
 }
 
 
              Your answer