123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- // --------------------------------------------------------------------------------------------------------------------
- // <copyright file="PlayerControl.cs" company="Exit Games GmbH">
- // Part of: Photon Unity Networking Demos
- // </copyright>
- // <summary>
- // Used in SlotRacer Demo
- // </summary>
- // <author>developer@exitgames.com</author>
- // --------------------------------------------------------------------------------------------------------------------
- using UnityEngine;
- using System.Collections;
- using Photon.Pun.Demo.SlotRacer.Utils;
- using Photon.Pun.UtilityScripts;
- namespace Photon.Pun.Demo.SlotRacer
- {
- /// <summary>
- /// Player control.
- /// Interface the User Inputs and PUN
- /// Handle the Car instance
- /// </summary>
- [RequireComponent(typeof(SplineWalker))]
- public class PlayerControl : MonoBehaviourPun, IPunObservable
- {
- /// <summary>
- /// The car prefabs to pick depending on the grid position.
- /// </summary>
- public GameObject[] CarPrefabs;
- /// <summary>
- /// The maximum speed. Maximum speed is reached with a 1 unit per seconds acceleration
- /// </summary>
- public float MaximumSpeed = 20;
- /// <summary>
- /// The drag when user is not accelerating
- /// </summary>
- public float Drag = 5;
- /// <summary>
- /// The current speed.
- /// Only used for locaPlayer
- /// </summary>
- private float CurrentSpeed;
- /// <summary>
- /// The current distance on the spline
- /// Only used for locaPlayer
- /// </summary>
- private float CurrentDistance;
- /// <summary>
- /// The car instance.
- /// </summary>
- private GameObject CarInstance;
- /// <summary>
- /// The spline walker. Must be on this GameObject
- /// </summary>
- private SplineWalker SplineWalker;
- /// <summary>
- /// flag to force latest data to avoid initial drifts when player is instantiated.
- /// </summary>
- private bool m_firstTake = true;
- private float m_input;
- #region IPunObservable implementation
- /// <summary>
- /// this is where data is sent and received for this Component from the PUN Network.
- /// </summary>
- /// <param name="stream">Stream.</param>
- /// <param name="info">Info.</param>
- void IPunObservable.OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
- {
- // currently there is no strategy to improve on bandwidth, just passing the current distance and speed is enough,
- // Input could be passed and then used to better control speed value
- // Data could be wrapped as a vector2 or vector3 to save a couple of bytes
- if (stream.IsWriting)
- {
- stream.SendNext(this.CurrentDistance);
- stream.SendNext(this.CurrentSpeed);
- stream.SendNext(this.m_input);
- }
- else
- {
- if (this.m_firstTake)
- {
- this.m_firstTake = false;
- }
- this.CurrentDistance = (float) stream.ReceiveNext();
- this.CurrentSpeed = (float) stream.ReceiveNext();
- this.m_input = (float) stream.ReceiveNext();
- }
- }
- #endregion IPunObservable implementation
- #region private
- /// <summary>
- /// Setups the car on track.
- /// </summary>
- /// <param name="gridStartIndex">Grid start index.</param>
- private void SetupCarOnTrack(int gridStartIndex)
- {
- // Setup the SplineWalker to be on the right starting grid position.
- this.SplineWalker.spline = SlotLanes.Instance.GridPositions[gridStartIndex].Spline;
- this.SplineWalker.currentDistance = SlotLanes.Instance.GridPositions[gridStartIndex].currentDistance;
- this.SplineWalker.ExecutePositioning();
- // create a new car
- this.CarInstance = (GameObject) Instantiate(this.CarPrefabs[gridStartIndex], this.transform.position, this.transform.rotation);
- // We'll wait for the first serializatin to pass, else we'll have a glitch where the car is positioned at the wrong position.
- if (!this.photonView.IsMine)
- {
- this.CarInstance.SetActive(false);
- }
- // 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)
- if (PhotonNetwork.CurrentRoom.PlayerCount == 1)
- {
- this.m_firstTake = false;
- }
- this.CarInstance.transform.SetParent(this.transform);
- }
- #endregion private
- #region Monobehaviour
- /// <summary>
- /// Cache the SplineWalker and flag context for clean serialization when joining late.
- /// </summary>
- private void Awake()
- {
- this.SplineWalker = this.GetComponent<SplineWalker>();
- this.m_firstTake = true;
- }
- /// <summary>
- /// Start this instance as a coroutine
- /// Waits for a Playernumber to be assigned and only then setup the car and put it on the right starting position on the lane.
- /// </summary>
- private IEnumerator Start()
- {
- // Wait until a Player Number is assigned
- // PlayerNumbering component must be in the scene.
- yield return new WaitUntil(() => this.photonView.Owner.GetPlayerNumber() >= 0);
- // now we can set it up.
- this.SetupCarOnTrack(this.photonView.Owner.GetPlayerNumber());
- }
- /// <summary>
- /// Make sure we delete instances linked to this component, else when user is leaving the room, its car instance would remain
- /// </summary>
- private void OnDestroy()
- {
- Destroy(this.CarInstance);
- }
- // Update is called once per frame
- private void Update()
- {
- if (this.SplineWalker == null || this.CarInstance == null)
- {
- return;
- }
- if (this.photonView.IsMine)
- {
- this.m_input = Input.GetAxis("Vertical");
- if (this.m_input == 0f)
- {
- this.CurrentSpeed -= Time.deltaTime * this.Drag;
- }
- else
- {
- this.CurrentSpeed += this.m_input;
- }
- this.CurrentSpeed = Mathf.Clamp(this.CurrentSpeed, 0f, this.MaximumSpeed);
- this.SplineWalker.Speed = this.CurrentSpeed;
- this.CurrentDistance = this.SplineWalker.currentDistance;
- }
- else
- {
- if (this.m_input == 0f)
- {
- this.CurrentSpeed -= Time.deltaTime * this.Drag;
- }
- this.CurrentSpeed = Mathf.Clamp (this.CurrentSpeed, 0f, this.MaximumSpeed);
- this.SplineWalker.Speed = this.CurrentSpeed;
- if (this.CurrentDistance != 0 && this.SplineWalker.currentDistance != this.CurrentDistance)
- {
- //Debug.Log ("SplineWalker.currentDistance=" + SplineWalker.currentDistance + " CurrentDistance=" + CurrentDistance);
- this.SplineWalker.Speed += (this.CurrentDistance - this.SplineWalker.currentDistance) * Time.deltaTime * 50f;
- }
- }
- // Only activate the car if we are sure we have the proper positioning, else it will glitch visually during the initialisation process.
- if (!this.m_firstTake && !this.CarInstance.activeSelf)
- {
- this.CarInstance.SetActive(true);
- this.SplineWalker.Speed = this.CurrentSpeed;
- this.SplineWalker.SetPositionOnSpline (this.CurrentDistance);
- }
- }
- #endregion Monobehaviour
- }
- }
|