PlayerControl.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // --------------------------------------------------------------------------------------------------------------------
  2. // <copyright file="PlayerControl.cs" company="Exit Games GmbH">
  3. // Part of: Photon Unity Networking Demos
  4. // </copyright>
  5. // <summary>
  6. // Used in SlotRacer Demo
  7. // </summary>
  8. // <author>developer@exitgames.com</author>
  9. // --------------------------------------------------------------------------------------------------------------------
  10. using UnityEngine;
  11. using System.Collections;
  12. using Photon.Pun.Demo.SlotRacer.Utils;
  13. using Photon.Pun.UtilityScripts;
  14. namespace Photon.Pun.Demo.SlotRacer
  15. {
  16. /// <summary>
  17. /// Player control.
  18. /// Interface the User Inputs and PUN
  19. /// Handle the Car instance
  20. /// </summary>
  21. [RequireComponent(typeof(SplineWalker))]
  22. public class PlayerControl : MonoBehaviourPun, IPunObservable
  23. {
  24. /// <summary>
  25. /// The car prefabs to pick depending on the grid position.
  26. /// </summary>
  27. public GameObject[] CarPrefabs;
  28. /// <summary>
  29. /// The maximum speed. Maximum speed is reached with a 1 unit per seconds acceleration
  30. /// </summary>
  31. public float MaximumSpeed = 20;
  32. /// <summary>
  33. /// The drag when user is not accelerating
  34. /// </summary>
  35. public float Drag = 5;
  36. /// <summary>
  37. /// The current speed.
  38. /// Only used for locaPlayer
  39. /// </summary>
  40. private float CurrentSpeed;
  41. /// <summary>
  42. /// The current distance on the spline
  43. /// Only used for locaPlayer
  44. /// </summary>
  45. private float CurrentDistance;
  46. /// <summary>
  47. /// The car instance.
  48. /// </summary>
  49. private GameObject CarInstance;
  50. /// <summary>
  51. /// The spline walker. Must be on this GameObject
  52. /// </summary>
  53. private SplineWalker SplineWalker;
  54. /// <summary>
  55. /// flag to force latest data to avoid initial drifts when player is instantiated.
  56. /// </summary>
  57. private bool m_firstTake = true;
  58. private float m_input;
  59. #region IPunObservable implementation
  60. /// <summary>
  61. /// this is where data is sent and received for this Component from the PUN Network.
  62. /// </summary>
  63. /// <param name="stream">Stream.</param>
  64. /// <param name="info">Info.</param>
  65. void IPunObservable.OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
  66. {
  67. // currently there is no strategy to improve on bandwidth, just passing the current distance and speed is enough,
  68. // Input could be passed and then used to better control speed value
  69. // Data could be wrapped as a vector2 or vector3 to save a couple of bytes
  70. if (stream.IsWriting)
  71. {
  72. stream.SendNext(this.CurrentDistance);
  73. stream.SendNext(this.CurrentSpeed);
  74. stream.SendNext(this.m_input);
  75. }
  76. else
  77. {
  78. if (this.m_firstTake)
  79. {
  80. this.m_firstTake = false;
  81. }
  82. this.CurrentDistance = (float) stream.ReceiveNext();
  83. this.CurrentSpeed = (float) stream.ReceiveNext();
  84. this.m_input = (float) stream.ReceiveNext();
  85. }
  86. }
  87. #endregion IPunObservable implementation
  88. #region private
  89. /// <summary>
  90. /// Setups the car on track.
  91. /// </summary>
  92. /// <param name="gridStartIndex">Grid start index.</param>
  93. private void SetupCarOnTrack(int gridStartIndex)
  94. {
  95. // Setup the SplineWalker to be on the right starting grid position.
  96. this.SplineWalker.spline = SlotLanes.Instance.GridPositions[gridStartIndex].Spline;
  97. this.SplineWalker.currentDistance = SlotLanes.Instance.GridPositions[gridStartIndex].currentDistance;
  98. this.SplineWalker.ExecutePositioning();
  99. // create a new car
  100. this.CarInstance = (GameObject) Instantiate(this.CarPrefabs[gridStartIndex], this.transform.position, this.transform.rotation);
  101. // We'll wait for the first serializatin to pass, else we'll have a glitch where the car is positioned at the wrong position.
  102. if (!this.photonView.IsMine)
  103. {
  104. this.CarInstance.SetActive(false);
  105. }
  106. // depending on wether we control this instance locally, we force the car to become active ( because when you are alone in the room, serialization doesn't happen, but still we want to allow the user to race around)
  107. if (PhotonNetwork.CurrentRoom.PlayerCount == 1)
  108. {
  109. this.m_firstTake = false;
  110. }
  111. this.CarInstance.transform.SetParent(this.transform);
  112. }
  113. #endregion private
  114. #region Monobehaviour
  115. /// <summary>
  116. /// Cache the SplineWalker and flag context for clean serialization when joining late.
  117. /// </summary>
  118. private void Awake()
  119. {
  120. this.SplineWalker = this.GetComponent<SplineWalker>();
  121. this.m_firstTake = true;
  122. }
  123. /// <summary>
  124. /// Start this instance as a coroutine
  125. /// Waits for a Playernumber to be assigned and only then setup the car and put it on the right starting position on the lane.
  126. /// </summary>
  127. private IEnumerator Start()
  128. {
  129. // Wait until a Player Number is assigned
  130. // PlayerNumbering component must be in the scene.
  131. yield return new WaitUntil(() => this.photonView.Owner.GetPlayerNumber() >= 0);
  132. // now we can set it up.
  133. this.SetupCarOnTrack(this.photonView.Owner.GetPlayerNumber());
  134. }
  135. /// <summary>
  136. /// Make sure we delete instances linked to this component, else when user is leaving the room, its car instance would remain
  137. /// </summary>
  138. private void OnDestroy()
  139. {
  140. Destroy(this.CarInstance);
  141. }
  142. // Update is called once per frame
  143. private void Update()
  144. {
  145. if (this.SplineWalker == null || this.CarInstance == null)
  146. {
  147. return;
  148. }
  149. if (this.photonView.IsMine)
  150. {
  151. this.m_input = Input.GetAxis("Vertical");
  152. if (this.m_input == 0f)
  153. {
  154. this.CurrentSpeed -= Time.deltaTime * this.Drag;
  155. }
  156. else
  157. {
  158. this.CurrentSpeed += this.m_input;
  159. }
  160. this.CurrentSpeed = Mathf.Clamp(this.CurrentSpeed, 0f, this.MaximumSpeed);
  161. this.SplineWalker.Speed = this.CurrentSpeed;
  162. this.CurrentDistance = this.SplineWalker.currentDistance;
  163. }
  164. else
  165. {
  166. if (this.m_input == 0f)
  167. {
  168. this.CurrentSpeed -= Time.deltaTime * this.Drag;
  169. }
  170. this.CurrentSpeed = Mathf.Clamp (this.CurrentSpeed, 0f, this.MaximumSpeed);
  171. this.SplineWalker.Speed = this.CurrentSpeed;
  172. if (this.CurrentDistance != 0 && this.SplineWalker.currentDistance != this.CurrentDistance)
  173. {
  174. //Debug.Log ("SplineWalker.currentDistance=" + SplineWalker.currentDistance + " CurrentDistance=" + CurrentDistance);
  175. this.SplineWalker.Speed += (this.CurrentDistance - this.SplineWalker.currentDistance) * Time.deltaTime * 50f;
  176. }
  177. }
  178. // Only activate the car if we are sure we have the proper positioning, else it will glitch visually during the initialisation process.
  179. if (!this.m_firstTake && !this.CarInstance.activeSelf)
  180. {
  181. this.CarInstance.SetActive(true);
  182. this.SplineWalker.Speed = this.CurrentSpeed;
  183. this.SplineWalker.SetPositionOnSpline (this.CurrentDistance);
  184. }
  185. }
  186. #endregion Monobehaviour
  187. }
  188. }