├── MoveCamera.cs └── PlayerMovement.cs /MoveCamera.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class MoveCamera : MonoBehaviour { 4 | 5 | public Transform player; 6 | 7 | void Update() { 8 | transform.position = player.transform.position; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /PlayerMovement.cs: -------------------------------------------------------------------------------- 1 | // PlayerMovement 2 | using System; 3 | using UnityEngine; 4 | 5 | public class PlayerMovement : MonoBehaviour 6 | { 7 | [Header("Assignables")] 8 | //Assignables 9 | public Transform playerCam; 10 | public Transform orientation; 11 | private Collider playerCollider; 12 | public Rigidbody rb; 13 | 14 | [Space(10)] 15 | 16 | public LayerMask whatIsGround; 17 | public LayerMask whatIsWallrunnable; 18 | 19 | [Header("MovementSettings")] 20 | //Movement Settings 21 | public float sensitivity = 50f; 22 | public float moveSpeed = 4500f; 23 | public float walkSpeed = 20f; 24 | public float runSpeed = 10f; 25 | public bool grounded; 26 | public bool onWall; 27 | 28 | //Private Floats 29 | private float wallRunGravity = 1f; 30 | private float maxSlopeAngle = 35f; 31 | private float wallRunRotation; 32 | private float slideSlowdown = 0.2f; 33 | private float actualWallRotation; 34 | private float wallRotationVel; 35 | private float desiredX; 36 | private float xRotation; 37 | private float sensMultiplier = 1f; 38 | private float jumpCooldown = 0.25f; 39 | private float jumpForce = 550f; 40 | private float x; 41 | private float y; 42 | private float vel; 43 | 44 | //Private bools 45 | private bool readyToJump; 46 | private bool jumping; 47 | private bool sprinting; 48 | private bool crouching; 49 | private bool wallRunning; 50 | private bool cancelling; 51 | private bool readyToWallrun = true; 52 | private bool airborne; 53 | private bool onGround; 54 | private bool surfing; 55 | private bool cancellingGrounded; 56 | private bool cancellingWall; 57 | private bool cancellingSurf; 58 | 59 | //Private Vector3's 60 | private Vector3 grapplePoint; 61 | private Vector3 normalVector; 62 | private Vector3 wallNormalVector; 63 | private Vector3 wallRunPos; 64 | private Vector3 previousLookdir; 65 | 66 | //Private int 67 | private int nw; 68 | 69 | //Instance 70 | public static PlayerMovement Instance { get; private set; } 71 | 72 | private void Awake() 73 | { 74 | Instance = this; 75 | rb = GetComponent(); 76 | } 77 | 78 | private void Start() 79 | { 80 | playerCollider = GetComponent(); 81 | Cursor.lockState = CursorLockMode.Locked; 82 | Cursor.visible = false; 83 | readyToJump = true; 84 | wallNormalVector = Vector3.up; 85 | } 86 | 87 | private void LateUpdate() 88 | { 89 | //For wallrunning 90 | WallRunning(); 91 | } 92 | 93 | private void FixedUpdate() 94 | { 95 | //For moving 96 | Movement(); 97 | } 98 | 99 | private void Update() 100 | { 101 | //Input 102 | MyInput(); 103 | //Looking around 104 | Look(); 105 | } 106 | 107 | //Player input 108 | private void MyInput() 109 | { 110 | x = Input.GetAxisRaw("Horizontal"); 111 | y = Input.GetAxisRaw("Vertical"); 112 | jumping = Input.GetButton("Jump"); 113 | crouching = Input.GetKey(KeyCode.LeftShift); 114 | if (Input.GetKeyDown(KeyCode.LeftShift)) 115 | { 116 | StartCrouch(); 117 | } 118 | if (Input.GetKeyUp(KeyCode.LeftShift)) 119 | { 120 | StopCrouch(); 121 | } 122 | } 123 | 124 | //Scale player down 125 | private void StartCrouch() 126 | { 127 | float num = 400f; 128 | base.transform.localScale = new Vector3(1f, 0.5f, 1f); 129 | base.transform.position = new Vector3(base.transform.position.x, base.transform.position.y - 0.5f, base.transform.position.z); 130 | if (rb.velocity.magnitude > 0.1f && grounded) 131 | { 132 | rb.AddForce(orientation.transform.forward * num); 133 | } 134 | } 135 | 136 | //Scale player to original size 137 | private void StopCrouch() 138 | { 139 | base.transform.localScale = new Vector3(1f, 1.5f, 1f); 140 | base.transform.position = new Vector3(base.transform.position.x, base.transform.position.y + 0.5f, base.transform.position.z); 141 | } 142 | 143 | //Moving around with WASD 144 | private void Movement() 145 | { 146 | rb.AddForce(Vector3.down * Time.deltaTime * 10f); 147 | Vector2 mag = FindVelRelativeToLook(); 148 | float num = mag.x; 149 | float num2 = mag.y; 150 | CounterMovement(x, y, mag); 151 | if (readyToJump && jumping) 152 | { 153 | Jump(); 154 | } 155 | float num3 = walkSpeed; 156 | if (sprinting) 157 | { 158 | num3 = runSpeed; 159 | } 160 | if (crouching && grounded && readyToJump) 161 | { 162 | rb.AddForce(Vector3.down * Time.deltaTime * 3000f); 163 | return; 164 | } 165 | if (x > 0f && num > num3) 166 | { 167 | x = 0f; 168 | } 169 | if (x < 0f && num < 0f - num3) 170 | { 171 | x = 0f; 172 | } 173 | if (y > 0f && num2 > num3) 174 | { 175 | y = 0f; 176 | } 177 | if (y < 0f && num2 < 0f - num3) 178 | { 179 | y = 0f; 180 | } 181 | float num4 = 1f; 182 | float num5 = 1f; 183 | if (!grounded) 184 | { 185 | num4 = 0.5f; 186 | num5 = 0.5f; 187 | } 188 | if (grounded && crouching) 189 | { 190 | num5 = 0f; 191 | } 192 | if (wallRunning) 193 | { 194 | num5 = 0.3f; 195 | num4 = 0.3f; 196 | } 197 | if (surfing) 198 | { 199 | num4 = 0.7f; 200 | num5 = 0.3f; 201 | } 202 | rb.AddForce(orientation.transform.forward * y * moveSpeed * Time.deltaTime * num4 * num5); 203 | rb.AddForce(orientation.transform.right * x * moveSpeed * Time.deltaTime * num4); 204 | } 205 | 206 | //Ready to jump again 207 | private void ResetJump() 208 | { 209 | readyToJump = true; 210 | } 211 | 212 | //Player go fly 213 | private void Jump() 214 | { 215 | if ((grounded || wallRunning || surfing) && readyToJump) 216 | { 217 | MonoBehaviour.print("jumping"); 218 | Vector3 velocity = rb.velocity; 219 | readyToJump = false; 220 | rb.AddForce(Vector2.up * jumpForce * 1.5f); 221 | rb.AddForce(normalVector * jumpForce * 0.5f); 222 | if (rb.velocity.y < 0.5f) 223 | { 224 | rb.velocity = new Vector3(velocity.x, 0f, velocity.z); 225 | } 226 | else if (rb.velocity.y > 0f) 227 | { 228 | rb.velocity = new Vector3(velocity.x, velocity.y / 2f, velocity.z); 229 | } 230 | if (wallRunning) 231 | { 232 | rb.AddForce(wallNormalVector * jumpForce * 3f); 233 | } 234 | Invoke("ResetJump", jumpCooldown); 235 | if (wallRunning) 236 | { 237 | wallRunning = false; 238 | } 239 | } 240 | } 241 | 242 | //Looking around by using your mouse 243 | private void Look() 244 | { 245 | float num = Input.GetAxis("Mouse X") * sensitivity * Time.fixedDeltaTime * sensMultiplier; 246 | float num2 = Input.GetAxis("Mouse Y") * sensitivity * Time.fixedDeltaTime * sensMultiplier; 247 | desiredX = playerCam.transform.localRotation.eulerAngles.y + num; 248 | xRotation -= num2; 249 | xRotation = Mathf.Clamp(xRotation, -90f, 90f); 250 | FindWallRunRotation(); 251 | actualWallRotation = Mathf.SmoothDamp(actualWallRotation, wallRunRotation, ref wallRotationVel, 0.2f); 252 | playerCam.transform.localRotation = Quaternion.Euler(xRotation, desiredX, actualWallRotation); 253 | orientation.transform.localRotation = Quaternion.Euler(0f, desiredX, 0f); 254 | } 255 | 256 | //Make the player movement feel good 257 | private void CounterMovement(float x, float y, Vector2 mag) 258 | { 259 | if (!grounded || jumping) 260 | { 261 | return; 262 | } 263 | float num = 0.16f; 264 | float num2 = 0.01f; 265 | if (crouching) 266 | { 267 | rb.AddForce(moveSpeed * Time.deltaTime * -rb.velocity.normalized * slideSlowdown); 268 | return; 269 | } 270 | if ((Math.Abs(mag.x) > num2 && Math.Abs(x) < 0.05f) || (mag.x < 0f - num2 && x > 0f) || (mag.x > num2 && x < 0f)) 271 | { 272 | rb.AddForce(moveSpeed * orientation.transform.right * Time.deltaTime * (0f - mag.x) * num); 273 | } 274 | if ((Math.Abs(mag.y) > num2 && Math.Abs(y) < 0.05f) || (mag.y < 0f - num2 && y > 0f) || (mag.y > num2 && y < 0f)) 275 | { 276 | rb.AddForce(moveSpeed * orientation.transform.forward * Time.deltaTime * (0f - mag.y) * num); 277 | } 278 | if (Mathf.Sqrt(Mathf.Pow(rb.velocity.x, 2f) + Mathf.Pow(rb.velocity.z, 2f)) > walkSpeed) 279 | { 280 | float num3 = rb.velocity.y; 281 | Vector3 vector = rb.velocity.normalized * walkSpeed; 282 | rb.velocity = new Vector3(vector.x, num3, vector.z); 283 | } 284 | } 285 | 286 | public Vector2 FindVelRelativeToLook() 287 | { 288 | float current = orientation.transform.eulerAngles.y; 289 | float target = Mathf.Atan2(rb.velocity.x, rb.velocity.z) * 57.29578f; 290 | float num = Mathf.DeltaAngle(current, target); 291 | float num2 = 90f - num; 292 | float magnitude = rb.velocity.magnitude; 293 | return new Vector2(y: magnitude * Mathf.Cos(num * ((float)Math.PI / 180f)), x: magnitude * Mathf.Cos(num2 * ((float)Math.PI / 180f))); 294 | } 295 | 296 | private void FindWallRunRotation() 297 | { 298 | if (!wallRunning) 299 | { 300 | wallRunRotation = 0f; 301 | return; 302 | } 303 | _ = new Vector3(0f, playerCam.transform.rotation.y, 0f).normalized; 304 | new Vector3(0f, 0f, 1f); 305 | float num = 0f; 306 | float current = playerCam.transform.rotation.eulerAngles.y; 307 | if (Math.Abs(wallNormalVector.x - 1f) < 0.1f) 308 | { 309 | num = 90f; 310 | } 311 | else if (Math.Abs(wallNormalVector.x - -1f) < 0.1f) 312 | { 313 | num = 270f; 314 | } 315 | else if (Math.Abs(wallNormalVector.z - 1f) < 0.1f) 316 | { 317 | num = 0f; 318 | } 319 | else if (Math.Abs(wallNormalVector.z - -1f) < 0.1f) 320 | { 321 | num = 180f; 322 | } 323 | num = Vector3.SignedAngle(new Vector3(0f, 0f, 1f), wallNormalVector, Vector3.up); 324 | float num2 = Mathf.DeltaAngle(current, num); 325 | wallRunRotation = (0f - num2 / 90f) * 15f; 326 | if (!readyToWallrun) 327 | { 328 | return; 329 | } 330 | if ((Mathf.Abs(wallRunRotation) < 4f && y > 0f && Math.Abs(x) < 0.1f) || (Mathf.Abs(wallRunRotation) > 22f && y < 0f && Math.Abs(x) < 0.1f)) 331 | { 332 | if (!cancelling) 333 | { 334 | cancelling = true; 335 | CancelInvoke("CancelWallrun"); 336 | Invoke("CancelWallrun", 0.2f); 337 | } 338 | } 339 | else 340 | { 341 | cancelling = false; 342 | CancelInvoke("CancelWallrun"); 343 | } 344 | } 345 | 346 | private void CancelWallrun() 347 | { 348 | MonoBehaviour.print("cancelled"); 349 | Invoke("GetReadyToWallrun", 0.1f); 350 | rb.AddForce(wallNormalVector * 600f); 351 | readyToWallrun = false; 352 | } 353 | 354 | private void GetReadyToWallrun() 355 | { 356 | readyToWallrun = true; 357 | } 358 | 359 | private void WallRunning() 360 | { 361 | if (wallRunning) 362 | { 363 | rb.AddForce(-wallNormalVector * Time.deltaTime * moveSpeed); 364 | rb.AddForce(Vector3.up * Time.deltaTime * rb.mass * 100f * wallRunGravity); 365 | } 366 | } 367 | 368 | private bool IsFloor(Vector3 v) 369 | { 370 | return Vector3.Angle(Vector3.up, v) < maxSlopeAngle; 371 | } 372 | 373 | private bool IsSurf(Vector3 v) 374 | { 375 | float num = Vector3.Angle(Vector3.up, v); 376 | if (num < 89f) 377 | { 378 | return num > maxSlopeAngle; 379 | } 380 | return false; 381 | } 382 | 383 | private bool IsWall(Vector3 v) 384 | { 385 | return Math.Abs(90f - Vector3.Angle(Vector3.up, v)) < 0.1f; 386 | } 387 | 388 | private bool IsRoof(Vector3 v) 389 | { 390 | return v.y == -1f; 391 | } 392 | 393 | private void StartWallRun(Vector3 normal) 394 | { 395 | if (!grounded && readyToWallrun) 396 | { 397 | wallNormalVector = normal; 398 | float num = 20f; 399 | if (!wallRunning) 400 | { 401 | rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z); 402 | rb.AddForce(Vector3.up * num, ForceMode.Impulse); 403 | } 404 | wallRunning = true; 405 | } 406 | } 407 | 408 | private void OnCollisionStay(Collision other) 409 | { 410 | int layer = other.gameObject.layer; 411 | if ((int)whatIsGround != ((int)whatIsGround | (1 << layer))) 412 | { 413 | return; 414 | } 415 | for (int i = 0; i < other.contactCount; i++) 416 | { 417 | Vector3 normal = other.contacts[i].normal; 418 | if (IsFloor(normal)) 419 | { 420 | if (wallRunning) 421 | { 422 | wallRunning = false; 423 | } 424 | grounded = true; 425 | normalVector = normal; 426 | cancellingGrounded = false; 427 | CancelInvoke("StopGrounded"); 428 | } 429 | if (IsWall(normal) && layer == LayerMask.NameToLayer("Ground")) 430 | { 431 | StartWallRun(normal); 432 | onWall = true; 433 | cancellingWall = false; 434 | CancelInvoke("StopWall"); 435 | } 436 | if (IsSurf(normal)) 437 | { 438 | surfing = true; 439 | cancellingSurf = false; 440 | CancelInvoke("StopSurf"); 441 | } 442 | IsRoof(normal); 443 | } 444 | float num = 3f; 445 | if (!cancellingGrounded) 446 | { 447 | cancellingGrounded = true; 448 | Invoke("StopGrounded", Time.deltaTime * num); 449 | } 450 | if (!cancellingWall) 451 | { 452 | cancellingWall = true; 453 | Invoke("StopWall", Time.deltaTime * num); 454 | } 455 | if (!cancellingSurf) 456 | { 457 | cancellingSurf = true; 458 | Invoke("StopSurf", Time.deltaTime * num); 459 | } 460 | } 461 | 462 | private void StopGrounded() 463 | { 464 | grounded = false; 465 | } 466 | 467 | private void StopWall() 468 | { 469 | onWall = false; 470 | wallRunning = false; 471 | } 472 | 473 | private void StopSurf() 474 | { 475 | surfing = false; 476 | } 477 | 478 | public Vector3 GetVelocity() 479 | { 480 | return rb.velocity; 481 | } 482 | 483 | public float GetFallSpeed() 484 | { 485 | return rb.velocity.y; 486 | } 487 | 488 | public Collider GetPlayerCollider() 489 | { 490 | return playerCollider; 491 | } 492 | 493 | public Transform GetPlayerCamTransform() 494 | { 495 | return playerCam.transform; 496 | } 497 | 498 | public bool IsCrouching() 499 | { 500 | return crouching; 501 | } 502 | 503 | public Rigidbody GetRb() 504 | { 505 | return rb; 506 | } 507 | } 508 | --------------------------------------------------------------------------------