1+ using UnityEngine ;
2+
3+ [ AddComponentMenu ( "Player Movement and Camera Controller" ) ]
4+ public class PlayerMovement : MonoBehaviour
5+ {
6+ Vector2 _mouseAbsolute ;
7+ Vector2 _smoothMouse ;
8+ Vector2 targetDirection ;
9+ Vector2 targetCharacterDirection ;
10+
11+ [ Header ( "Camera Settings" ) ]
12+ public bool lockCursor = true ;
13+ public Vector2 clampInDegrees = new Vector2 ( 360 , 180 ) ;
14+ public Vector2 sensitivity = new Vector2 ( 2 , 2 ) ;
15+ public Vector2 smoothing = new Vector2 ( 1.5f , 1.5f ) ;
16+ public string cameraName = "Camera" ;
17+
18+ [ Space ]
19+ [ Header ( "Movement Settings" ) ]
20+ //instance variables (tweak these to change the feel of the player controller)
21+ public float walkingSpeed = 7.5f ;
22+ public float sprintingSpeed = 11f ;
23+ public float jumpingSpeed = 6f ;
24+ public float crouchingSpeed = 3f ;
25+ public float jumpForce = 100f ;
26+ public bool holdToCrouch = true ;
27+ public bool jumpCrouching = true ;
28+ Vector3 crouchScale = new Vector3 ( 1 , 0.5f , 1 ) ; //change for how large you want when crouching
29+ Vector3 standScale = new Vector3 ( 1 , 1 , 1 ) ;
30+ public float extraGravity = 0.1f ;
31+
32+ //references
33+ private Rigidbody rb ;
34+ private GameObject cam ;
35+
36+ [ Space ]
37+ [ Header ( "Keyboard Settings" ) ]
38+ public KeyCode jump = KeyCode . Space ;
39+ public KeyCode sprint = KeyCode . LeftShift ;
40+ public KeyCode crouch = KeyCode . Z ;
41+ public KeyCode lockToggle = KeyCode . Q ;
42+
43+
44+ [ Space ]
45+ [ Header ( "Debug Info" ) ]
46+ //states
47+ public bool isJumping = false ;
48+ public bool isGrounded = true ;
49+ public bool isCrouching = false ;
50+ public float currentSpeed ;
51+
52+ void Start ( )
53+ {
54+ rb = gameObject . GetComponent < Rigidbody > ( ) ;
55+ cam = gameObject . transform . Find ( cameraName ) . gameObject ;
56+ currentSpeed = walkingSpeed ;
57+
58+ // Set target direction to the camera's initial orientation.
59+ targetDirection = transform . localRotation . eulerAngles ;
60+ // Set target direction for the character body to its inital state.
61+ targetCharacterDirection = transform . localRotation . eulerAngles ;
62+ }
63+
64+ private void Update ( )
65+ {
66+ // Allow the script to clamp based on a desired target value.
67+ var targetOrientation = Quaternion . Euler ( targetDirection ) ;
68+ var targetCharacterOrientation = Quaternion . Euler ( targetCharacterDirection ) ;
69+
70+ // Get raw mouse input for a cleaner reading on more sensitive mice.
71+ var mouseDelta = new Vector2 ( Input . GetAxisRaw ( "Mouse X" ) , Input . GetAxisRaw ( "Mouse Y" ) ) ;
72+
73+ // Scale input against the sensitivity setting and multiply that against the smoothing value.
74+ mouseDelta = Vector2 . Scale ( mouseDelta , new Vector2 ( sensitivity . x * smoothing . x , sensitivity . y * smoothing . y ) ) ;
75+
76+ // Interpolate mouse movement over time to apply smoothing delta.
77+ _smoothMouse . x = Mathf . Lerp ( _smoothMouse . x , mouseDelta . x , 1f / smoothing . x ) ;
78+ _smoothMouse . y = Mathf . Lerp ( _smoothMouse . y , mouseDelta . y , 1f / smoothing . y ) ;
79+
80+ // Find the absolute mouse movement value from point zero.
81+ _mouseAbsolute += _smoothMouse ;
82+
83+ // Clamp and apply the local x value first, so as not to be affected by world transforms.
84+ if ( clampInDegrees . x < 360 )
85+ _mouseAbsolute . x = Mathf . Clamp ( _mouseAbsolute . x , - clampInDegrees . x * 0.5f , clampInDegrees . x * 0.5f ) ;
86+
87+ // Then clamp and apply the global y value.
88+ if ( clampInDegrees . y < 360 )
89+ _mouseAbsolute . y = Mathf . Clamp ( _mouseAbsolute . y , - clampInDegrees . y * 0.5f , clampInDegrees . y * 0.5f ) ;
90+
91+ cam . transform . localRotation = Quaternion . AngleAxis ( - _mouseAbsolute . y , targetOrientation * Vector3 . right ) * targetOrientation ;
92+
93+ var yRotation = Quaternion . AngleAxis ( _mouseAbsolute . x , Vector3 . up ) ;
94+ transform . localRotation = yRotation * targetCharacterOrientation ;
95+ }
96+
97+ void FixedUpdate ( )
98+ {
99+ //Mouse lock toggle
100+ if ( Input . GetKeyDown ( lockToggle ) )
101+ lockCursor = ! lockCursor ;
102+
103+ if ( lockCursor )
104+ Cursor . lockState = CursorLockMode . Locked ;
105+ else
106+ Cursor . lockState = CursorLockMode . None ;
107+
108+ //WSAD movement
109+ Vector3 input = new Vector3 ( Input . GetAxisRaw ( "Horizontal" ) , 0 , Input . GetAxisRaw ( "Vertical" ) ) ;
110+ input = input . normalized ;
111+ Vector3 forwardVel = transform . forward * currentSpeed * input . z ;
112+ Vector3 horizontalVel = transform . right * currentSpeed * input . x ;
113+ rb . velocity = horizontalVel + forwardVel + new Vector3 ( 0 , rb . velocity . y , 0 ) ;
114+
115+ //Jumping
116+ if ( Input . GetKey ( jump ) && isGrounded )
117+ Jump ( ) ;
118+
119+ //Sprinting
120+ if ( Input . GetKey ( sprint ) && ! isJumping && ! isCrouching )
121+ currentSpeed = sprintingSpeed ;
122+ else if ( ! isCrouching && ! isJumping )
123+ currentSpeed = walkingSpeed ;
124+
125+ //Crouching (alot of if)
126+ if ( Input . GetKey ( crouch ) )
127+ {
128+ if ( isCrouching && ! holdToCrouch )
129+ Crouch ( false ) ;
130+ else if ( ! isCrouching && jumpCrouching )
131+ Crouch ( true ) ;
132+ else if ( ! isCrouching && ! isJumping && ! jumpCrouching )
133+ Crouch ( true ) ;
134+ }
135+ else if ( holdToCrouch && isCrouching )
136+ {
137+ Crouch ( false ) ;
138+ }
139+
140+ //Extra gravity for more realistic jumping
141+ rb . AddForce ( new Vector3 ( 0 , - extraGravity , 0 ) , ForceMode . Impulse ) ;
142+ }
143+
144+ //handling jumping
145+ void Jump ( )
146+ {
147+ currentSpeed = jumpingSpeed ;
148+ isGrounded = false ;
149+ isJumping = true ;
150+ rb . AddForce ( transform . up * jumpForce , ForceMode . Impulse ) ;
151+ if ( isCrouching )
152+ currentSpeed = crouchingSpeed ;
153+ }
154+
155+ //toggle crouch
156+ void Crouch ( bool crouch )
157+ {
158+ isCrouching = crouch ;
159+ if ( crouch )
160+ {
161+ currentSpeed = crouchingSpeed ;
162+ transform . localScale = crouchScale ;
163+ transform . position = new Vector3 ( transform . position . x , transform . position . y - 0.5f , transform . position . z ) ;
164+ }
165+ else
166+ {
167+ currentSpeed = walkingSpeed ;
168+ transform . localScale = standScale ;
169+ transform . position = new Vector3 ( transform . position . x , transform . position . y + 0.5f , transform . position . z ) ;
170+ }
171+ }
172+
173+ //ground check
174+ //* make sure whatever you want to be the ground in your game matches the tag below called "Ground" or change it to whatever you want
175+ private void OnCollisionEnter ( Collision other )
176+ {
177+ if ( other . gameObject . tag == "Ground" )
178+ {
179+ if ( isCrouching )
180+ currentSpeed = crouchingSpeed ;
181+ else
182+ currentSpeed = walkingSpeed ;
183+ isJumping = false ;
184+ isGrounded = true ;
185+ }
186+ }
187+
188+ public void setupCharacter ( )
189+ {
190+ if ( ! gameObject . GetComponent < Rigidbody > ( ) )
191+ {
192+ Rigidbody rb = gameObject . AddComponent ( typeof ( Rigidbody ) ) as Rigidbody ;
193+ rb . mass = 10 ;
194+ Debug . Log ( "Added Rigidbody" ) ;
195+ }
196+ else
197+ {
198+ Debug . Log ( "Rigidbody already found" ) ;
199+ }
200+
201+ Physics . gravity = new Vector3 ( 0 , - 19F , 0 ) ;
202+ Debug . Log ( "Physics set" ) ;
203+ if ( ! gameObject . transform . Find ( "Camera" ) )
204+ {
205+ Vector3 old = transform . position ;
206+ gameObject . transform . position = new Vector3 ( 0 , - 0.8f , 0 ) ; // Hmmm
207+ GameObject go = new GameObject ( "Camera" ) ;
208+ go . AddComponent < Camera > ( ) ;
209+ go . AddComponent < AudioListener > ( ) ;
210+ go . transform . rotation = new Quaternion ( 0 , 0 , 0 , 0 ) ;
211+ go . transform . localScale = new Vector3 ( 1 , 1 , 1 ) ;
212+ go . transform . parent = transform ; // Hacky way to do it
213+ gameObject . transform . position = old ; // But it works
214+ Debug . Log ( "Camera created" ) ;
215+ }
216+ else
217+ {
218+ Debug . Log ( "Camera already created" ) ;
219+ }
220+ }
221+ }
0 commit comments