Advertisement
Aranyalma2

Unity_3D_char_controller

Aug 14th, 2018
239
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.74 KB | None | 0 0
  1. using System;
  2. using UnityEngine;
  3. using UnityStandardAssets.CrossPlatformInput;
  4.  
  5. namespace UnityStandardAssets.Characters.FirstPerson
  6. {
  7.     [RequireComponent(typeof (Rigidbody))]
  8.     [RequireComponent(typeof (CapsuleCollider))]
  9.     public class RigidbodyFirstPersonController : MonoBehaviour
  10.     {
  11.         [Serializable]
  12.         public class MovementSettings
  13.         {
  14.             public float ForwardSpeed = 4.0f;   // Speed when walking forward
  15.             public float BackwardSpeed = 2.0f;  // Speed when walking backwards
  16.             public float StrafeSpeed = 2.0f;    // Speed when walking sideways
  17.             public float RunMultiplier = 2.0f;   // Speed when sprinting
  18.             public KeyCode RunKey = KeyCode.LeftShift;
  19.             public float JumpForce = 25f;
  20.             public AnimationCurve SlopeCurveModifier = new AnimationCurve(new Keyframe(-90.0f, 1.0f), new Keyframe(0.0f, 1.0f), new Keyframe(90.0f, 0.0f));
  21.             [HideInInspector] public float CurrentTargetSpeed = 4f;
  22.  
  23. #if !MOBILE_INPUT
  24.             private bool m_Running;
  25. #endif
  26.  
  27.             public void UpdateDesiredTargetSpeed(Vector2 input)
  28.             {
  29.                 if (input == Vector2.zero) return;
  30.                 if (input.x > 0 || input.x < 0)
  31.                 {
  32.                     //strafe
  33.                     CurrentTargetSpeed = StrafeSpeed;
  34.                 }
  35.                 if (input.y < 0)
  36.                 {
  37.                     //backwards
  38.                     CurrentTargetSpeed = BackwardSpeed;
  39.                 }
  40.                 if (input.y > 0)
  41.                 {
  42.                     //forwards
  43.                     //handled last as if strafing and moving forward at the same time forwards speed should take precedence
  44.                     CurrentTargetSpeed = ForwardSpeed;
  45.                 }
  46. #if !MOBILE_INPUT
  47.                 if (Input.GetKey(RunKey))
  48.                 {
  49.                     CurrentTargetSpeed *= RunMultiplier;
  50.                     m_Running = true;
  51.                 }
  52.                 else
  53.                 {
  54.                     m_Running = false;
  55.                 }
  56. #endif
  57.             }
  58.  
  59. #if !MOBILE_INPUT
  60.             public bool Running
  61.             {
  62.                 get { return m_Running; }
  63.             }
  64. #endif
  65.         }
  66.  
  67.  
  68.         [Serializable]
  69.         public class AdvancedSettings
  70.         {
  71.             public float groundCheckDistance = 0.01f; // distance for checking if the controller is grounded ( 0.01f seems to work best for this )
  72.             public float stickToGroundHelperDistance = 0.5f; // stops the character
  73.             public float slowDownRate = 20f; // rate at which the controller comes to a stop when there is no input
  74.             public float movingDrag = 5f; // rate at which the controlls comes to a stop when moving
  75.             public bool airControl; // can the user control the direction that is being moved in the air
  76.             [Tooltip("set it to 0.1 or more if you get stuck in wall")]
  77.             public float shellOffset; //reduce the radius by that ratio to avoid getting stuck in wall (a value of 0.1f is nice)
  78.         }
  79.  
  80.  
  81.         public Camera cam;
  82.         public MovementSettings movementSettings = new MovementSettings();
  83.         public MouseLook mouseLook = new MouseLook();
  84.         public AdvancedSettings advancedSettings = new AdvancedSettings();
  85.  
  86.  
  87.         private Rigidbody m_RigidBody;
  88.         private CapsuleCollider m_Capsule;
  89.         private float m_YRotation;
  90.         private Vector3 m_GroundContactNormal;
  91.         private bool m_Jump, m_PreviouslyGrounded, m_Jumping, m_IsGrounded;
  92.  
  93.  
  94.         public Vector3 Velocity
  95.         {
  96.             get { return m_RigidBody.velocity; }
  97.         }
  98.  
  99.         public float speedPercent
  100.         {
  101.             get { return Velocity.sqrMagnitude / (movementSettings.CurrentTargetSpeed * movementSettings.CurrentTargetSpeed); }
  102.         }
  103.  
  104.         public bool Grounded
  105.         {
  106.             get { return m_IsGrounded; }
  107.         }
  108.  
  109.         public bool Jumping
  110.         {
  111.             get { return m_Jumping; }
  112.         }
  113.  
  114.         public bool Running
  115.         {
  116.             get
  117.             {
  118.  #if !MOBILE_INPUT
  119.                 return movementSettings.Running;
  120. #else
  121.                 return false;
  122. #endif
  123.             }
  124.         }
  125.  
  126.  
  127.         private void Start()
  128.         {
  129.             m_RigidBody = GetComponent<Rigidbody>();
  130.             m_Capsule = GetComponent<CapsuleCollider>();
  131.             mouseLook.Init (transform, cam.transform);
  132.         }
  133.  
  134.  
  135.         private void Update()
  136.         {
  137.             RotateView();
  138.  
  139.             if (CrossPlatformInputManager.GetButtonDown("Jump") && !m_Jump)
  140.             {
  141.                 m_Jump = true;
  142.             }
  143.         }
  144.  
  145.  
  146.         private void FixedUpdate()
  147.         {
  148.             GroundCheck();
  149.             Vector2 input = GetInput();
  150.             bool hasInput = (Mathf.Abs(input.x) > float.Epsilon || Mathf.Abs(input.y) > float.Epsilon);
  151.             if ( hasInput && (advancedSettings.airControl || m_IsGrounded))
  152.             {
  153.                 // always move along the camera forward as it is the direction that it being aimed at
  154.                 Vector3 desiredMove = cam.transform.forward*input.y + cam.transform.right*input.x;
  155.                 desiredMove = Vector3.ProjectOnPlane(desiredMove, m_GroundContactNormal).normalized;
  156.  
  157.                 desiredMove.x = desiredMove.x*movementSettings.CurrentTargetSpeed;
  158.                 desiredMove.z = desiredMove.z*movementSettings.CurrentTargetSpeed;
  159.                 desiredMove.y = desiredMove.y*movementSettings.CurrentTargetSpeed;
  160.                 if (m_RigidBody.velocity.sqrMagnitude <
  161.                     (movementSettings.CurrentTargetSpeed*movementSettings.CurrentTargetSpeed))
  162.                 {
  163.                     m_RigidBody.AddForce(desiredMove*SlopeMultiplier(), ForceMode.Impulse);
  164.                 }
  165.             }
  166.  
  167.             if (m_IsGrounded)
  168.             {
  169.                 if( !hasInput )
  170.                 {
  171.                     m_RigidBody.drag = advancedSettings.slowDownRate;
  172.                 }
  173.                 else
  174.                 {
  175.                     m_RigidBody.drag = advancedSettings.movingDrag;
  176.                 }
  177.  
  178.                 if (m_Jump)
  179.                 {
  180.                     m_RigidBody.drag = 0f;
  181.                     m_RigidBody.velocity = new Vector3(m_RigidBody.velocity.x, 0f, m_RigidBody.velocity.z);
  182.                     m_RigidBody.AddForce(new Vector3(0f, movementSettings.JumpForce, 0f), ForceMode.Impulse);
  183.                     m_Jumping = true;
  184.                 }
  185.  
  186.                 if (!m_Jumping && Mathf.Abs(input.x) < float.Epsilon && Mathf.Abs(input.y) < float.Epsilon && m_RigidBody.velocity.magnitude < 1f)
  187.                 {
  188.                     m_RigidBody.Sleep();
  189.                 }
  190.             }
  191.             else
  192.             {
  193.                 m_RigidBody.drag = 0f;
  194.                 if (m_PreviouslyGrounded && !m_Jumping)
  195.                 {
  196.                     StickToGroundHelper();
  197.                 }
  198.             }
  199.             m_Jump = false;
  200.         }
  201.  
  202.  
  203.         private float SlopeMultiplier()
  204.         {
  205.             float angle = Vector3.Angle(m_GroundContactNormal, Vector3.up);
  206.             return movementSettings.SlopeCurveModifier.Evaluate(angle);
  207.         }
  208.  
  209.  
  210.         private void StickToGroundHelper()
  211.         {
  212.             RaycastHit hitInfo;
  213.             if (Physics.SphereCast(transform.position, m_Capsule.radius * (1.0f - advancedSettings.shellOffset), Vector3.down, out hitInfo,
  214.                                    ((m_Capsule.height/2f) - m_Capsule.radius) +
  215.                                    advancedSettings.stickToGroundHelperDistance, Physics.AllLayers, QueryTriggerInteraction.Ignore))
  216.             {
  217.                 if (Mathf.Abs(Vector3.Angle(hitInfo.normal, Vector3.up)) < 85f)
  218.                 {
  219.                     m_RigidBody.velocity = Vector3.ProjectOnPlane(m_RigidBody.velocity, hitInfo.normal);
  220.                 }
  221.             }
  222.         }
  223.  
  224.  
  225.         private Vector2 GetInput()
  226.         {
  227.            
  228.             Vector2 input = new Vector2
  229.                 {
  230.                     x = CrossPlatformInputManager.GetAxis("Horizontal"),
  231.                     y = CrossPlatformInputManager.GetAxis("Vertical")
  232.                 };
  233.             movementSettings.UpdateDesiredTargetSpeed(input);
  234.             return input;
  235.         }
  236.  
  237.  
  238.         private void RotateView()
  239.         {
  240.             //avoids the mouse looking if the game is effectively paused
  241.             if (Mathf.Abs(Time.timeScale) < float.Epsilon) return;
  242.  
  243.             // get the rotation before it's changed
  244.             float oldYRotation = transform.eulerAngles.y;
  245.  
  246.             mouseLook.LookRotation (transform, cam.transform);
  247.  
  248.             if (m_IsGrounded || advancedSettings.airControl)
  249.             {
  250.                 // Rotate the rigidbody velocity to match the new direction that the character is looking
  251.                 Quaternion velRotation = Quaternion.AngleAxis(transform.eulerAngles.y - oldYRotation, Vector3.up);
  252.                 m_RigidBody.velocity = velRotation*m_RigidBody.velocity;
  253.             }
  254.         }
  255.  
  256.         /// sphere cast down just beyond the bottom of the capsule to see if the capsule is colliding round the bottom
  257.         private void GroundCheck()
  258.         {
  259.             m_PreviouslyGrounded = m_IsGrounded;
  260.             RaycastHit hitInfo;
  261.             if (Physics.SphereCast(transform.position, m_Capsule.radius * (1.0f - advancedSettings.shellOffset), Vector3.down, out hitInfo,
  262.                                    ((m_Capsule.height/2f) - m_Capsule.radius) + advancedSettings.groundCheckDistance, Physics.AllLayers, QueryTriggerInteraction.Ignore))
  263.             {
  264.                 m_IsGrounded = true;
  265.                 m_GroundContactNormal = hitInfo.normal;
  266.             }
  267.             else
  268.             {
  269.                 m_IsGrounded = false;
  270.                 m_GroundContactNormal = Vector3.up;
  271.             }
  272.             if (!m_PreviouslyGrounded && m_IsGrounded && m_Jumping)
  273.             {
  274.                 m_Jumping = false;
  275.             }
  276.         }
  277.     }
  278. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement