Advertisement
Guest User

Untitled

a guest
Jan 19th, 2020
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.36 KB | None | 0 0
  1. using UnityEngine;
  2.  
  3. namespace Whilefun.FPEKit {
  4.  
  5. [RequireComponent(typeof(CharacterController))]
  6. [RequireComponent(typeof(AudioSource))]
  7. [RequireComponent(typeof(FPEMouseLook))]
  8.  
  9. public class FPEFirstPersonController : MonoBehaviour
  10. {
  11.  
  12. [Header("Movement Speeds")]
  13. [SerializeField]
  14. private float m_WalkSpeedCrouching = 2.0f;
  15. [SerializeField]
  16. private float m_RunSpeedCrouching = 2.0f;
  17. [SerializeField]
  18. private float m_WalkSpeedStanding = 4.0f;
  19. [SerializeField]
  20. private float m_RunSpeedStanding = 10.0f;
  21.  
  22. private bool isWalking = true;
  23.  
  24. // These impact the rate at which the cumulativeStepCycleCount is increased with steps of respective style.
  25. [Header("Movement Stride Sizes (For Audio)")]
  26. [SerializeField]
  27. private float walkStepLengthCrouching = 3.5f;
  28. [SerializeField]
  29. private float runStepLengthCrouching = 3.0f;
  30. [SerializeField]
  31. private float walkStepLengthStanding = 1.0f;
  32. [SerializeField]
  33. private float runStepLengthStanding = 0.7f;
  34.  
  35. [Header("Jumping")]
  36. [SerializeField]
  37. private float m_JumpSpeed = 8.0f;
  38. [SerializeField]
  39. private float m_StickToGroundForce = 10.0f;
  40. [SerializeField]
  41. private float m_GravityMultiplier = 2.0f;
  42. [SerializeField, Tooltip("Minimum downward speed required before player is considered to have landed from a jump or fall. Default is -1;")]
  43. private float minimumFallSpeed = -1.0f;
  44.  
  45. // Walking things
  46. private float cumulativeStepCycleCount = 0.0f;
  47. private float nextStepInCycle = 0.0f;
  48. [SerializeField]
  49. private float stepInterval = 5.0f;
  50.  
  51. [Header("View Bob")]
  52. [SerializeField]
  53. private bool cameraBobEnabled = true;
  54. [SerializeField]
  55. private FPELerpControlledBob m_JumpBob = new FPELerpControlledBob();
  56. [SerializeField]
  57. private AnimationCurve CameraBobCurve = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(0.5f, 1f), new Keyframe(1f, 0f), new Keyframe(1.5f, -1f), new Keyframe(2f, 0f));
  58. [SerializeField]
  59. private Vector2 bobRangeStanding = new Vector2(0.05f, 0.1f);
  60. [SerializeField]
  61. private Vector2 bobRangeCrouching = new Vector2(0.2f, 0.2f);
  62.  
  63. [Header("Audio")]
  64. [SerializeField]
  65. private FPESoundBank footstepSounds;
  66. [SerializeField]
  67. private FPESoundBank jumpSounds;
  68. [SerializeField]
  69. private FPESoundBank landingSounds;
  70.  
  71. private Camera m_Camera;
  72. private bool m_Jump;
  73. private float m_YRotation;
  74. private Vector2 m_Input;
  75. private Vector3 m_MoveDir = Vector3.zero;
  76. private CharacterController m_CharacterController;
  77. private CollisionFlags m_CollisionFlags;
  78. private bool m_PreviouslyGrounded = true;
  79. //private Vector3 m_OriginalCameraPosition;
  80. private bool m_Jumping;
  81. private AudioSource m_AudioSource;
  82.  
  83. // Crouching Stuff //
  84. private bool isCrouching = false;
  85. private float standingHeight = 0.0f;
  86. private float crouchingHeight = 0.0f;
  87. private float previousCharacterHeight = 0.0f;
  88. //The denominator with which we divide "standing" height to determine crouching height
  89. private float characterCrouchDivisor = 2.0f;
  90. private CharacterController controller;
  91. // Crouching camera stuff
  92. private Vector3 cameraOffsetStanding = Vector3.zero;
  93. private Vector3 cameraOffsetCrouching = Vector3.zero;
  94.  
  95. private float bobCurveTime = 0.0f;
  96. private float bobCycleX = 0.0f;
  97. private float bobCycleY = 0.0f;
  98.  
  99. private bool movementEnabled = true;
  100. private float currentSpeed = 0.0f;
  101. private bool movementStarted = false;
  102.  
  103. // Custom stuff for my own version of this stanard script
  104. [Header("Custom Flags for Movement Options")]
  105. [Tooltip("Toggle movement sounds on and off")]
  106. public bool enableMovementSounds = false;
  107. [SerializeField, Tooltip("Toggle jump ability on and off")]
  108. private bool jumpEnabled = false;
  109. [SerializeField, Tooltip("Toggle run ability on and off")]
  110. private bool runEnabled = true;
  111. [SerializeField, Tooltip("Toggle crouch ability on and off")]
  112. private bool crouchEnabled = true;
  113. [SerializeField, Tooltip("If true, crouch will be a toggle")]
  114. private bool crouchAsToggle = true;
  115.  
  116. // Player docking stuff
  117. [SerializeField, Tooltip("Distance at which the player will stop moving and snap to dock and undock positions")]
  118. private float dockSnapDistance = 0.1f;
  119. [SerializeField, Tooltip("Rate at which the player will smoothly move to dock and undock positions (larger number means quicker movement)")]
  120. private float dockingLerpFactor = 5.0f;
  121.  
  122. private bool playerDocked = false;
  123. public enum ePlayerDockingState
  124. {
  125. IDLE = 0,
  126. DOCKING,
  127. UNDOCKING
  128. }
  129. private ePlayerDockingState currentDockingState = ePlayerDockingState.IDLE;
  130.  
  131. private Vector2 targetMaxAngles = Vector2.zero;
  132. private Vector3 targetFocalPoint = Vector3.zero;
  133. private Vector3 targetDockPosition = Vector3.zero;
  134. private Vector3 previousFocalPoint = Vector3.zero;
  135. private Vector3 previousWorldPosition = Vector3.zero;
  136.  
  137. public bool playerFrozen = false;
  138.  
  139. void Awake()
  140. {
  141.  
  142. controller = gameObject.GetComponent<CharacterController>();
  143.  
  144. standingHeight = controller.height;
  145. crouchingHeight = standingHeight / characterCrouchDivisor;
  146.  
  147. cameraOffsetStanding = Camera.main.transform.localPosition;
  148. cameraOffsetCrouching = cameraOffsetStanding;
  149. cameraOffsetCrouching.y -= 0.6f;
  150.  
  151. bobCurveTime = CameraBobCurve[CameraBobCurve.length - 1].time;
  152.  
  153. }
  154.  
  155. private void Start()
  156. {
  157.  
  158. m_CharacterController = GetComponent<CharacterController>();
  159. m_Camera = Camera.main;
  160.  
  161. cumulativeStepCycleCount = 0.0f;
  162. nextStepInCycle = cumulativeStepCycleCount / 2.0f;
  163.  
  164. m_Jumping = false;
  165. m_AudioSource = GetComponent<AudioSource>();
  166. gameObject.GetComponent<FPEMouseLook>().Init(transform, m_Camera.transform);
  167.  
  168. }
  169.  
  170.  
  171. private void Update()
  172. {
  173.  
  174. if (playerFrozen)
  175. {
  176. // Nothing
  177. }
  178. else if (playerDocked)
  179. {
  180.  
  181. if (currentDockingState == ePlayerDockingState.DOCKING)
  182. {
  183.  
  184. if(Vector3.Distance(transform.position, targetDockPosition) < dockSnapDistance)
  185. {
  186.  
  187. transform.position = targetDockPosition;
  188. gameObject.GetComponent<FPEMouseLook>().LookAtPosition(transform, m_Camera.transform, targetFocalPoint);
  189. gameObject.GetComponent<FPEMouseLook>().enableLookRestriction(targetMaxAngles);
  190. gameObject.GetComponent<FPEMouseLook>().enableMouseLook = true;
  191. currentDockingState = ePlayerDockingState.IDLE;
  192.  
  193. }
  194.  
  195. }
  196. else if (currentDockingState == ePlayerDockingState.UNDOCKING)
  197. {
  198.  
  199. if (Vector3.Distance(transform.position, targetDockPosition) < dockSnapDistance)
  200. {
  201.  
  202. transform.position = targetDockPosition;
  203. gameObject.GetComponent<FPEMouseLook>().LookAtPosition(transform, m_Camera.transform, targetFocalPoint);
  204. gameObject.GetComponent<FPEMouseLook>().disableLookRestriction();
  205. gameObject.GetComponent<FPEMouseLook>().enableMouseLook = true;
  206. currentDockingState = ePlayerDockingState.IDLE;
  207. playerDocked = false;
  208.  
  209. }
  210.  
  211. }
  212.  
  213. }
  214. else
  215. {
  216.  
  217. // Only jump if we are allowed, not already jumping, and not crouched
  218. if (jumpEnabled && !m_Jump && !isCrouching)
  219. {
  220.  
  221. // Workaround for conflicting jump and menu buttons when using XBox controller. When assigned bumper is pressed when menu is open, player jumps when menu is closed.
  222. if (Time.timeScale != 0.0f && m_CharacterController.isGrounded)
  223. {
  224. m_Jump = FPEInputManager.Instance.GetButtonDown(FPEInputManager.eFPEInput.FPE_INPUT_JUMP);
  225. }
  226.  
  227. }
  228.  
  229. if (!m_PreviouslyGrounded && m_CharacterController.isGrounded && (m_MoveDir.y < minimumFallSpeed))
  230. {
  231.  
  232. StartCoroutine(m_JumpBob.DoBobCycle());
  233. PlayLandingSound();
  234. m_MoveDir.y = 0f;
  235. m_Jumping = false;
  236.  
  237. }
  238.  
  239. if (!m_CharacterController.isGrounded && !m_Jumping && m_PreviouslyGrounded)
  240. {
  241. m_MoveDir.y = 0f;
  242. }
  243.  
  244. m_PreviouslyGrounded = m_CharacterController.isGrounded;
  245.  
  246. // Crouch based on crouch method (toggle vs. hold down)
  247. if (crouchEnabled)
  248. {
  249.  
  250. if (movementEnabled)
  251. {
  252.  
  253. if (crouchAsToggle)
  254. {
  255.  
  256. if (FPEInputManager.Instance.GetButtonDown(FPEInputManager.eFPEInput.FPE_INPUT_CROUCH))
  257. {
  258. if (isCrouching)
  259. {
  260. if (haveHeadRoomToStand())
  261. {
  262. isCrouching = false;
  263. }
  264. }
  265. else
  266. {
  267. isCrouching = true;
  268. }
  269. }
  270. }
  271. else
  272. {
  273. if (FPEInputManager.Instance.GetButton(FPEInputManager.eFPEInput.FPE_INPUT_CROUCH))
  274. {
  275. isCrouching = true;
  276. }
  277. else
  278. {
  279. if (isCrouching)
  280. {
  281. if (haveHeadRoomToStand())
  282. {
  283. isCrouching = false;
  284. }
  285. }
  286. }
  287. }
  288.  
  289. }
  290.  
  291. }
  292. else
  293. {
  294. // Set it to false here in case crouching is disabled during play, and player was mid-crouch
  295. isCrouching = false;
  296. }
  297.  
  298. // Crouching stuff
  299. previousCharacterHeight = controller.height;
  300.  
  301. // Footstep audio special case: If player moves a little, but not a "full stride", there should still be a foot step sound. And if they just stopped walking, there should also be one
  302. if (FPEInputManager.Instance.GetButtonDown(FPEInputManager.eFPEInput.FPE_INPUT_HORIZONTAL) || FPEInputManager.Instance.GetButtonDown(FPEInputManager.eFPEInput.FPE_INPUT_VERTICAL) && !movementStarted)
  303. {
  304. movementStarted = true;
  305. cumulativeStepCycleCount = 0.0f;
  306. nextStepInCycle = cumulativeStepCycleCount + stepInterval;
  307. PlayFootStepAudio();
  308. }
  309. if (FPEInputManager.Instance.GetButtonDown(FPEInputManager.eFPEInput.FPE_INPUT_HORIZONTAL) || FPEInputManager.Instance.GetButtonDown(FPEInputManager.eFPEInput.FPE_INPUT_VERTICAL) && movementStarted)
  310. {
  311. movementStarted = false;
  312. PlayFootStepAudio();
  313. }
  314.  
  315. }
  316.  
  317. }
  318.  
  319.  
  320. private void FixedUpdate()
  321. {
  322.  
  323. RotateView();
  324.  
  325. currentSpeed = 0.0f;
  326. GetInput(out currentSpeed);
  327.  
  328. if (playerFrozen)
  329. {
  330. // Nothing
  331. }
  332. else if (playerDocked)
  333. {
  334.  
  335. if (currentDockingState == ePlayerDockingState.DOCKING)
  336. {
  337.  
  338. transform.position = Vector3.Lerp(transform.position, targetDockPosition, dockingLerpFactor * Time.fixedDeltaTime);
  339. gameObject.GetComponent<FPEMouseLook>().LookAtPosition(transform, m_Camera.transform, targetFocalPoint);
  340.  
  341. }
  342. else if (currentDockingState == ePlayerDockingState.UNDOCKING)
  343. {
  344.  
  345. transform.position = Vector3.Lerp(transform.position, targetDockPosition, dockingLerpFactor * Time.fixedDeltaTime);
  346. gameObject.GetComponent<FPEMouseLook>().LookAtPosition(transform, m_Camera.transform, targetFocalPoint);
  347.  
  348. }
  349.  
  350. }
  351. else
  352. {
  353.  
  354. if (isCrouching)
  355. {
  356. gameObject.GetComponent<CharacterController>().height = Mathf.Lerp(gameObject.GetComponent<CharacterController>().height, crouchingHeight, 5 * Time.fixedDeltaTime);
  357. }
  358. else
  359. {
  360. gameObject.GetComponent<CharacterController>().height = Mathf.Lerp(gameObject.GetComponent<CharacterController>().height, standingHeight, 5 * Time.fixedDeltaTime);
  361. }
  362.  
  363. // We move the transform to be the x/z and exactly middle of Y relative to controller height change from crouch/stand
  364. gameObject.transform.position = new Vector3(gameObject.transform.position.x, gameObject.transform.position.y + (controller.height - previousCharacterHeight) / 2, gameObject.transform.position.z);
  365.  
  366. // always move along the camera forward as it is the direction that it being aimed at
  367. Vector3 desiredMove = Vector3.zero;
  368.  
  369. if (movementEnabled)
  370. {
  371. desiredMove = transform.forward * m_Input.y + transform.right * m_Input.x;
  372. }
  373.  
  374. // get a normal for the surface that is being touched to move along it
  375. RaycastHit hitInfo;
  376. Physics.SphereCast(transform.position, m_CharacterController.radius, Vector3.down, out hitInfo, m_CharacterController.height / 2f);
  377. desiredMove = Vector3.ProjectOnPlane(desiredMove, hitInfo.normal).normalized;
  378.  
  379. m_MoveDir.x = desiredMove.x * currentSpeed;
  380. m_MoveDir.z = desiredMove.z * currentSpeed;
  381.  
  382. if (m_CharacterController.isGrounded)
  383. {
  384.  
  385. m_MoveDir.y = -m_StickToGroundForce;
  386.  
  387. if (m_Jump)
  388. {
  389.  
  390. m_MoveDir.y = m_JumpSpeed;
  391. PlayJumpSound();
  392. m_Jump = false;
  393. m_Jumping = true;
  394.  
  395. }
  396.  
  397. }
  398. else
  399. {
  400. m_MoveDir += Physics.gravity * m_GravityMultiplier * Time.fixedDeltaTime;
  401. }
  402.  
  403. m_CollisionFlags = m_CharacterController.Move(m_MoveDir * Time.fixedDeltaTime);
  404.  
  405. ProgressStepCycle(currentSpeed);
  406. UpdateCameraPosition(currentSpeed);
  407.  
  408. }
  409.  
  410. }
  411.  
  412. private void UpdateCameraPosition(float speed)
  413. {
  414.  
  415. if (cameraBobEnabled)
  416. {
  417.  
  418. if (m_CharacterController.velocity.magnitude > 0 && m_CharacterController.isGrounded)
  419. {
  420.  
  421. float xOffset = CameraBobCurve.Evaluate(bobCycleX);
  422. float yOffset = CameraBobCurve.Evaluate(bobCycleY);
  423.  
  424. Vector3 newCameraPosition = cameraOffsetStanding;
  425. Vector2 bobRange = bobRangeStanding;
  426.  
  427. if (isCrouching)
  428. {
  429. newCameraPosition = cameraOffsetCrouching;
  430. bobRange = bobRangeCrouching;
  431. }
  432.  
  433. newCameraPosition.y += (yOffset * bobRange.y) - m_JumpBob.Offset();
  434. newCameraPosition.x += xOffset * bobRange.x;
  435.  
  436. // Update bob cycle
  437. float VerticalToHorizontalRatioStanding = 2.0f;
  438. bobCycleX += (speed * Time.deltaTime) / stepInterval;
  439. bobCycleY += ((speed * Time.deltaTime) / stepInterval) * VerticalToHorizontalRatioStanding;
  440.  
  441. if (bobCycleX > bobCurveTime)
  442. {
  443. bobCycleX = bobCycleX - bobCurveTime;
  444. }
  445. if (bobCycleY > bobCurveTime)
  446. {
  447. bobCycleY = bobCycleY - bobCurveTime;
  448. }
  449.  
  450. // Lastly, lerp toward our new target camera position
  451. //m_Camera.transform.localPosition = newCameraPosition;
  452. m_Camera.transform.localPosition = Vector3.Lerp(m_Camera.transform.localPosition, newCameraPosition, 0.1f);
  453.  
  454.  
  455. }
  456. else
  457. {
  458.  
  459. // If we aren't actively moving or bobbing, just lerp toward our appropriate camera position
  460. if (isCrouching)
  461. {
  462. Vector3 newCameraPosition = cameraOffsetCrouching;
  463. newCameraPosition.y -= m_JumpBob.Offset();
  464. m_Camera.transform.localPosition = Vector3.Lerp(m_Camera.transform.localPosition, newCameraPosition, 0.1f);
  465. }
  466. else
  467. {
  468. Vector3 newCameraPosition = cameraOffsetStanding;
  469. newCameraPosition.y -= m_JumpBob.Offset();
  470. m_Camera.transform.localPosition = Vector3.Lerp(m_Camera.transform.localPosition, newCameraPosition, 0.1f);
  471. }
  472.  
  473. }
  474.  
  475. }
  476. else
  477. {
  478.  
  479. if (isCrouching)
  480. {
  481. m_Camera.transform.localPosition = Vector3.Lerp(m_Camera.transform.localPosition, cameraOffsetCrouching, 0.1f);
  482. }
  483. else
  484. {
  485. m_Camera.transform.localPosition = Vector3.Lerp(m_Camera.transform.localPosition, cameraOffsetStanding, 0.1f);
  486. }
  487.  
  488. }
  489.  
  490.  
  491. }
  492.  
  493. private void PlayJumpSound()
  494. {
  495.  
  496. if (enableMovementSounds)
  497. {
  498. jumpSounds.Play(m_AudioSource);
  499. }
  500.  
  501. }
  502.  
  503. private void PlayLandingSound()
  504. {
  505.  
  506. // We check timeSinceLevelLoad to prevent perpetual clunky land sound when every scene starts
  507. if (enableMovementSounds && Time.timeSinceLevelLoad > 1f)
  508. {
  509. landingSounds.Play(m_AudioSource);
  510. nextStepInCycle = cumulativeStepCycleCount + 0.5f;
  511. }
  512.  
  513. }
  514.  
  515. private void ProgressStepCycle(float speed)
  516. {
  517.  
  518. if (m_CharacterController.velocity.sqrMagnitude > 0.0f && (m_Input.x != 0.0f || m_Input.y != 0.0f))
  519. {
  520.  
  521. if (isCrouching)
  522. {
  523. cumulativeStepCycleCount += (m_CharacterController.velocity.magnitude + (speed * (isWalking ? walkStepLengthCrouching : runStepLengthCrouching))) * Time.fixedDeltaTime;
  524. }
  525. else
  526. {
  527. cumulativeStepCycleCount += (m_CharacterController.velocity.magnitude + (speed * (isWalking ? walkStepLengthStanding : runStepLengthStanding))) * Time.fixedDeltaTime;
  528. }
  529.  
  530. }
  531.  
  532. if (!(cumulativeStepCycleCount > nextStepInCycle))
  533. {
  534. return;
  535. }
  536.  
  537. nextStepInCycle = cumulativeStepCycleCount + stepInterval;
  538.  
  539. PlayFootStepAudio();
  540.  
  541.  
  542. }
  543.  
  544. private void PlayFootStepAudio()
  545. {
  546.  
  547. if (!m_CharacterController.isGrounded)
  548. {
  549. return;
  550. }
  551.  
  552. if (enableMovementSounds && movementEnabled)
  553. {
  554. footstepSounds.Play(m_AudioSource);
  555. }
  556.  
  557. }
  558.  
  559. private void GetInput(out float speed)
  560. {
  561.  
  562. float horizontal = FPEInputManager.Instance.GetAxis(FPEInputManager.eFPEInput.FPE_INPUT_HORIZONTAL);
  563. float vertical = FPEInputManager.Instance.GetAxis(FPEInputManager.eFPEInput.FPE_INPUT_VERTICAL);
  564.  
  565. // Keep track of whether or not the character is walking or running
  566. isWalking = (runEnabled ? (!FPEInputManager.Instance.GetButton(FPEInputManager.eFPEInput.FPE_INPUT_RUN)) : true);
  567.  
  568. // Set the desired speed to be walking or running
  569. if (isCrouching)
  570. {
  571. speed = isWalking ? m_WalkSpeedCrouching : m_RunSpeedCrouching;
  572. }
  573. else
  574. {
  575. speed = isWalking ? m_WalkSpeedStanding : m_RunSpeedStanding;
  576. }
  577.  
  578. m_Input = new Vector2(horizontal, vertical);
  579.  
  580. // normalize input if it exceeds 1 in combined length:
  581. if (m_Input.sqrMagnitude > 1.0f)
  582. {
  583. m_Input.Normalize();
  584. }
  585.  
  586. }
  587.  
  588. private void RotateView()
  589. {
  590. gameObject.GetComponent<FPEMouseLook>().LookRotation(transform, m_Camera.transform);
  591. }
  592.  
  593. private void OnControllerColliderHit(ControllerColliderHit hit)
  594. {
  595.  
  596. Rigidbody body = hit.collider.attachedRigidbody;
  597.  
  598. // Don't move the rigidbody if the character is on top of it
  599. if (m_CollisionFlags == CollisionFlags.Below)
  600. {
  601. return;
  602. }
  603.  
  604. if (body == null || body.isKinematic)
  605. {
  606. return;
  607. }
  608.  
  609. body.AddForceAtPosition(m_CharacterController.velocity * 0.1f, hit.point, ForceMode.Impulse);
  610.  
  611. }
  612.  
  613.  
  614. private bool haveHeadRoomToStand()
  615. {
  616.  
  617. bool haveHeadRoom = true;
  618. //Debug.DrawRay(gameObject.transform.position, gameObject.transform.up * (standingHeight - (controller.height/2.0f)), Color.red);
  619.  
  620. RaycastHit headRoomHit;
  621. if (Physics.Raycast(gameObject.transform.position, gameObject.transform.up, out headRoomHit, (standingHeight - (controller.height / 2.0f))))
  622. {
  623. //Debug.Log("Headroom hit " + headRoomHit.collider.transform.name);
  624. haveHeadRoom = false;
  625. }
  626.  
  627. return haveHeadRoom;
  628.  
  629. }
  630.  
  631.  
  632. public void dockThePlayer(Transform dockTransform, Vector2 maxAngleFromFocalPoint, Vector3 focalPoint, bool smoothDock = false)
  633. {
  634.  
  635. playerDocked = true;
  636.  
  637. // Make a "fake" focal point to restore to, just an invisible point in front of where the player was looking prior to docking
  638. previousFocalPoint = m_Camera.transform.position + (m_Camera.transform.forward * 5.0f);
  639. previousWorldPosition = transform.position;
  640.  
  641. if (smoothDock)
  642. {
  643.  
  644. targetDockPosition = dockTransform.position;
  645. targetMaxAngles = maxAngleFromFocalPoint;
  646. targetFocalPoint = focalPoint;
  647. currentDockingState = ePlayerDockingState.DOCKING;
  648.  
  649. }
  650. else
  651. {
  652.  
  653. transform.position = dockTransform.position;
  654. gameObject.GetComponent<FPEMouseLook>().LookAtPosition(transform, m_Camera.transform, focalPoint);
  655. gameObject.GetComponent<FPEMouseLook>().enableLookRestriction(maxAngleFromFocalPoint);
  656.  
  657. }
  658.  
  659. }
  660.  
  661. public void unDockThePlayer(bool smoothUndock = false)
  662. {
  663.  
  664. if (playerDocked)
  665. {
  666.  
  667. if (smoothUndock)
  668. {
  669.  
  670. targetDockPosition = previousWorldPosition;
  671. targetFocalPoint = previousFocalPoint;
  672. gameObject.GetComponent<FPEMouseLook>().enableMouseLook = false;
  673. currentDockingState = ePlayerDockingState.UNDOCKING;
  674.  
  675. }
  676. else
  677. {
  678.  
  679. transform.position = previousWorldPosition;
  680. gameObject.GetComponent<FPEMouseLook>().disableLookRestriction();
  681. gameObject.GetComponent<FPEMouseLook>().LookAtPosition(transform, m_Camera.transform, previousFocalPoint);
  682. playerDocked = false;
  683.  
  684. }
  685.  
  686. }
  687.  
  688. }
  689.  
  690. public Vector3 GetCurrentPlayerFocalPoint()
  691. {
  692. return (m_Camera.transform.position + (m_Camera.transform.forward * 5.0f));
  693. }
  694.  
  695. public void enableMovement()
  696. {
  697. movementEnabled = true;
  698. }
  699.  
  700. public void disableMovement()
  701. {
  702. movementEnabled = false;
  703. }
  704.  
  705. public void enableRun()
  706. {
  707. runEnabled = true;
  708. }
  709.  
  710. public void disableRun()
  711. {
  712. runEnabled = false;
  713. }
  714.  
  715. public void enableJump()
  716. {
  717. jumpEnabled = true;
  718. }
  719.  
  720. public void disableJump()
  721. {
  722. jumpEnabled = false;
  723. }
  724.  
  725. public void enableCrouch()
  726. {
  727. crouchEnabled = true;
  728. }
  729.  
  730. public void disableCrouch()
  731. {
  732. crouchEnabled = false;
  733. }
  734.  
  735. public bool dockInProgress()
  736. {
  737. return (currentDockingState != ePlayerDockingState.IDLE);
  738. }
  739.  
  740. /// <summary>
  741. /// Forces player's camera to look at a position
  742. /// </summary>
  743. /// <param name="position">The position to look at</param>
  744. public void forcePlayerLookToPosition(Vector3 position)
  745. {
  746. gameObject.GetComponent<FPEMouseLook>().LookAtPosition(transform, m_Camera.transform, position);
  747. }
  748.  
  749. #region SAVING_AND_LOADING
  750.  
  751. //
  752. // Assumptions:
  753. // -----------
  754. // 1. Player can never access save menu when they are in the middle of a dock movement (e.g. currentDockingState is not IDLE)
  755. // 2. When game is loaded, player is kicked to gameplay (e.g. Movement and MouseLook state is always ENABLED upon restoration of state)
  756. //
  757.  
  758. public FPEPlayerStateSaveData getPlayerStateDataForSavedGame()
  759. {
  760.  
  761. GameObject tempDock = FPEInteractionManagerScript.Instance.getCurrentDockForSaveGame();
  762. string currentDockName = (tempDock == null ? "" : tempDock.name);
  763. FPEPlayerStateSaveData playerData = new FPEPlayerStateSaveData(transform, GetCurrentPlayerFocalPoint(), isCrouching, playerDocked, currentDockName, targetMaxAngles, targetFocalPoint, targetDockPosition, previousFocalPoint, previousWorldPosition);
  764. return playerData;
  765.  
  766. }
  767.  
  768. public void restorePlayerStateFromSavedGame(FPEPlayerStateSaveData data)
  769. {
  770.  
  771. // Player position and look focus
  772. transform.position = data.playerPosition();
  773. transform.rotation = data.playerRotation();
  774. gameObject.GetComponent<FPEMouseLook>().LookAtPosition(transform, m_Camera.transform, data.playerLookAt());
  775. isCrouching = data.Crouching;
  776. playerDocked = data.Docked;
  777. targetMaxAngles = data.MaxAngles;
  778. targetFocalPoint = data.TargetFocalPos;
  779. targetDockPosition = data.TargetDockPos;
  780. previousFocalPoint = data.PreviousFocalPos;
  781. previousWorldPosition = data.PreviousWorldPos;
  782.  
  783. // Look for dock, if required
  784. if (data.Docked && data.DockName != "")
  785. {
  786.  
  787. FPEInteractableDockScript[] allDocks = GameObject.FindObjectsOfType<FPEInteractableDockScript>();
  788. GameObject foundDock = null;
  789.  
  790. for (int i = 0; i < allDocks.Length; i++)
  791. {
  792.  
  793. if(allDocks[i].gameObject.name == data.DockName)
  794. {
  795. foundDock = allDocks[i].gameObject;
  796. break;
  797. }
  798.  
  799. }
  800.  
  801. if(foundDock != null)
  802. {
  803.  
  804. gameObject.GetComponent<FPEMouseLook>().enableLookRestriction(targetMaxAngles);
  805. FPEInteractionManagerScript.Instance.restoreCurrentDockFromSavedGame(foundDock);
  806. isCrouching = false;
  807.  
  808. }
  809. // If there was supposed to be a dock per the save file, but it cannot be found, try to restore the player state in a friendly way
  810. else
  811. {
  812.  
  813. Debug.LogError("FPEFirstPersonController.restorePlayerStateFromSavedGame():: Saved dock named '"+ data.DockName + "' could not be found in the scene. Restoring player to undocked state in last known good world position instead. Your scene must have changed, or this is an old saved game that is no longer compatible with the most recent version of your game or scene.");
  814. transform.position = data.PreviousWorldPos;
  815. transform.rotation = Quaternion.identity;
  816. gameObject.GetComponent<FPEMouseLook>().LookAtPosition(transform, m_Camera.transform, data.PreviousFocalPos);
  817. playerDocked = false;
  818. isCrouching = false;
  819.  
  820. }
  821.  
  822. }
  823.  
  824. // We ALWAYS assume the player can move their mouse once a game is loaded we restore player state
  825. gameObject.GetComponent<FPEMouseLook>().enableMouseLook = true;
  826.  
  827. }
  828.  
  829. public void setPlayerLookToNeutralLevelLoadedPosition()
  830. {
  831.  
  832.  
  833. // Create a neutral "look forward" position based on player's transform position and rotation
  834. Vector3 neutralLookAt = transform.position + m_Camera.transform.localPosition + (transform.forward * 5.0f);
  835. gameObject.GetComponent<FPEMouseLook>().LookAtPosition(transform, m_Camera.transform, neutralLookAt);
  836.  
  837. }
  838.  
  839. /// <summary>
  840. /// A special function used by FPESaveLoadManager via FPEInteractionManager to ensure player states are reset when returning
  841. /// to the main menu. Made for special New Game -> Dock/Crouch/Etc. -> Exit to Menu -> New Game edge case.
  842. /// </summary>
  843. public void resetPlayerForMainMenu()
  844. {
  845.  
  846. gameObject.GetComponent<FPEMouseLook>().disableLookRestriction();
  847. playerDocked = false;
  848. isCrouching = false;
  849.  
  850. }
  851.  
  852. #endregion
  853.  
  854. }
  855.  
  856. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement