using System.Collections; using UnityEngine; #if hNW_PHOTON using Photon.Pun; #endif namespace Passer { /// /// A Counter can be used to record a integer number. /// /// The Counter can be incremented and decremented and functions cal be called based on the value. /// /// \image html CounterInspector.png /// /// * %Value, see Counter::value /// * %Minimum, see Counter::min /// * %Maximum, see Counter::max /// * %Network Sync, see Counter::networking. This property is only available when a supported networking solution is included in the project. /// * Events /// - Value Change Event, see Counter::counterEvent /// /// \version 4.0 and higher public class Counter : MonoBehaviour { #region Properties [SerializeField] protected int _value; /// /// Sets or gets the value of the Counter /// /// If networking is enabled, the value is synchoronized across the network. public int value { get { return _value; } set { LocalSetValue(value); CallRemote(nameof(LocalSetValue), value); } } [RemoteCallable] private void LocalSetValue(int value) { _value = value; counterEvent.value = _value; } /// /// The minimum value for the Counter /// public int min = 0; /// /// The maximum value for the Counter /// public int max = 10; public float timer = 0; private bool timerActive = false; #if hNW_PHOTON /// /// Synchronize the value across the network. /// public bool networking = false; protected PhotonView photonView; #endif #endregion Properties #region Init protected virtual void Awake() { #if hNW_PHOTON photonView = GetComponent(); if (photonView == null) networking = false; #endif counterEvent.value = _value; } #endregion #region Update protected virtual void FixedUpdate() { CheckBounds(); CheckTimer(); } protected virtual void CheckBounds() { if (min > max) min = max; if (max < min) max = min; _value = Mathf.Clamp(_value, min, max); } private void CheckTimer() { if (timerActive) { if (value <= min) { timer = 0; timerActive = false; } return; } if (timer > 0) StartCoroutine(StartTimer()); } IEnumerator StartTimer() { timerActive = true; while (_value > min && timerActive && timer > 0) { yield return new WaitForSeconds(timer); Decrement(); } timer = 0; timerActive = false; yield return null; } #endregion /// /// Decrements the Counter value by 1 /// /// If the Counter value is equal or lower than the minimum value, /// the value is not changed public void Decrement() { if (_value > min) { LocalDecrement(); CallRemote(nameof(LocalDecrement)); } } [RemoteCallable] private void LocalDecrement() { _value--; // don't use value as this will set value on network // NetworkedDecrement is network safe counterEvent.value = _value; } /// /// Increments the Counter value by 1 /// /// If the Counter value is equal or higher than the maximum value, /// the value is not changed /// If networking is enabled, the value is incremented on all clients /// and event handlers are called on all clients public void Increment() { if (_value < max) { LocalIncrement(); CallRemote(nameof(LocalIncrement)); } } [RemoteCallable] private void LocalIncrement() { _value++; // don't use value as this will set value on network counterEvent.value = _value; } /// /// Sets the Counter value to the minimum value /// public void SetValueToMin() { LocalSetToMin(); CallRemote(nameof(LocalSetToMin)); } [RemoteCallable] private void LocalSetToMin() { value = min; } /// /// Sets the Counter value to the maximum value /// public void SetValueToMax() { LocalSetToMax(); CallRemote(nameof(LocalSetToMax)); } [RemoteCallable] private void LocalSetToMax() { value = max; } public void SetTimer(int seconds) { SetTimer(seconds, 1); } public void SetTimer(int seconds, float speed) { _value = seconds; timer = speed; CheckTimer(); } #region Networking #if hNW_PHOTON class RemoteCallable : PunRPC { } #else class RemoteCallable : System.Attribute { } #endif protected void CallRemote(string functionName, params object[] parameters) { #if hNW_PHOTON if (networking == false || photonView == null || !PhotonNetwork.IsConnected) return; photonView.RPC(functionName, RpcTarget.Others, parameters); #endif } #endregion #region Events /// /// Can be used to call values based on the Counter value /// public IntEventHandlers counterEvent = new IntEventHandlers() { label = "Value Change Event", tooltip = "Call functions using counter values\n" + "Parameter: the counter value", eventTypeLabels = new string[] { "Never", "On Min", "On Max", "While Min", "While Max", "When Changed", "Always" } }; #endregion } }