防加速器Demo https://pan.baidu.com/s/1hsO9r7I
思路
"本地间隔时间"和“服务器间隔时间”做对比。就可以计算出变速器改变比例。我们再修改 Time.timeScale的值就可以还原本身速度
(时间戳为毫秒)
获取本地时间
使用“靠谱助手”模拟器的加速器测试,可以发现Time.time、Time.unscaledTime速度都会被改变。我们游戏中有可能会用到Time.timeScale,而他会改变Time.time的频率。所以我们用Time.unscaledTime来做参考
private static double _time = 0; private static float _delayTime = 1; private static void UpdateLocalTime() { if (_time > 0) { _delayTime = (float) (Time.unscaledTime - _time); } else { _delayTime = gapTimeConfig; } _time = Time.unscaledTime; } public static float delayTime { get { return _delayTime; } }
获取服务器时间
private static double _preServerTime = -1; private static double _serverTime = -1; private static float _delayServerTime = 1; private static WWW www; private static IEnumerator GetHtmlServerTime() { www = new WWW("http://192.168.1.7/time.php"); yield return www; if (!string.IsNullOrEmpty(www.error)) { yield break; } SetServerTime(Convert.ToDouble(www.text)); } private static void SetServerTime(double time) { _serverTime = time; if (_preServerTime > 0) { _delayServerTime = (float) (_serverTime - _preServerTime) / 1000; } else { _delayServerTime = gapTimeConfig; } _preServerTime = _serverTime; }
计算加速度比例
float speedRate = delayTime / delayServerTime; float speedScale = Mathf.RoundToInt((1 / speedRate) * 10) / 10f; // 10主要是为了排除通信时间
我们自定义一个HTime用来修改 timeScale
如果要修改timeScale,就使用我们自己定义的HTime.timeScale
private static float _timeScale = 1; public static float timeScale { get { return _timeScale; } set { _timeScale = value; setTimeScale(); } } public static void setTimeScale() { Time.timeScale = Mathf.Clamp(_timeScale * speedScale, 0f, 100f); }
HTime
using UnityEngine; using System.Collections; using System; public class HTime { public static bool isAntiAccelerator = true; public static int gapTimeConfig = 2; private static DateTime dateTime1970 = new DateTime(1970, 1, 1, 0, 0, 0); public static double timeStamp { get { return (DateTime.UtcNow - dateTime1970).TotalMilliseconds; } } private static double _time = 0; private static float _delayTime = 1; private static void UpdateLocalTime() { if (_time > 0) { _delayTime = (float) (Time.unscaledTime - _time); } else { _delayTime = gapTimeConfig; } _time = Time.unscaledTime; } public static float delayTime { get { return _delayTime; } } public static void CheckUpdateBegin() { UpdateLocalTime(); } public static void CheckUpdateEnd(Int32 s, Int32 ms) { UpdateLocalTime(); SetServerTime(s * 1000 + ms); if (isAntiAccelerator) { setTimeScale(); } } private static void SetServerTime(double time) { _serverTime = time; if (_preServerTime > 0) { _delayServerTime = (float) (_serverTime - _preServerTime) / 1000; } else { _delayServerTime = gapTimeConfig; } _preServerTime = _serverTime; } public static IEnumerator Check() { while (true) { UpdateLocalTime(); yield return GetHtmlServerTime(); yield return new WaitForSeconds(timeScale > 0 ? gapTimeConfig / timeScale : gapTimeConfig); if (isAntiAccelerator) { setTimeScale(); } } } private static double _preServerTime = -1; private static double _serverTime = -1; private static float _delayServerTime = 1; private static WWW www; private static IEnumerator GetHtmlServerTime() { www = new WWW("http://192.168.1.7/time.php"); yield return www; if (!string.IsNullOrEmpty(www.error)) { yield break; } SetServerTime(Convert.ToDouble(www.text)); } public static float delayServerTime { get { return _delayServerTime; } } public static float speedRate { get { return delayTime / delayServerTime; } } public static float speedScale { get { return Mathf.RoundToInt((1 / speedRate) * 10) / 10f; } } private static float _timeScale = 1; public static float timeScale { get { return _timeScale; } set { _timeScale = value; setTimeScale(); } } public static void setTimeScale() { Time.timeScale = Mathf.Clamp(_timeScale * speedScale, 0f, 100f); } public static void Reset() { _delayTime = gapTimeConfig; _delayServerTime = gapTimeConfig; setTimeScale(); } }
测试
using UnityEngine; using System.Collections; using UnityEngine.UI; using System; public class TimeInfo : MonoBehaviour { public Text text; private string info; public Toggle fangToggle; public Toggle appToggle; public Slider slider; public InputField minInput; public InputField maxInput; public Text currText; void Start () { fangToggle.isOn = HTime.isAntiAccelerator; StartCoroutine(HTime.Check()); } void Update () { info = ""; info += string.Format("Time.timeScale = {0} \n", Time.timeScale); info += string.Format("Time.time = {0} \n", Time.time); info += string.Format("Time.unscaledTime = {0} \n", Time.unscaledTime); info += string.Format("Time.deltaTime = {0} \n", Time.deltaTime); info += string.Format("Time.unscaledDeltaTime = {0} \n", Time.unscaledDeltaTime); info += string.Format("Time.smoothDeltaTime = {0} \n", Time.smoothDeltaTime); info += string.Format("Time.fixedTime = {0} \n", Time.fixedTime); info += string.Format("Time.fixedDeltaTime = {0} \n", Time.fixedDeltaTime); info += string.Format("Time.timeSinceLevelLoad = {0} \n", Time.timeSinceLevelLoad); info += string.Format("Time.realtimeSinceStartup = {0} \n", Time.realtimeSinceStartup); info += string.Format("Time.frameCount = {0} \n", Time.frameCount); info += string.Format("Time.captureFramerate = {0} \n", Time.captureFramerate); info += string.Format("HTime.timeStamp = {0} \n", HTime.timeStamp); info += string.Format("HTime.gapTimeConfig = {0} \n", HTime.gapTimeConfig); info += string.Format("HTime.delayTime = {0} \n", HTime.delayTime); info += string.Format("HTime.delayServerTime = {0} \n", HTime.delayServerTime); info += string.Format("HTime.speedRate = {0} \n", HTime.speedRate); info += string.Format("HTime.speedScale = {0} \n", HTime.speedScale); info += string.Format("HTime.timeScale = {0} \n", HTime.timeScale); text.text = info; slider.minValue = Convert.ToSingle(minInput.text); slider.maxValue = Convert.ToSingle(maxInput.text); currText.text = slider.value + ""; HTime.isAntiAccelerator = fangToggle.isOn; if (appToggle.isOn) { HTime.timeScale = slider.value; } } public void Open() { gameObject.SetActive(true); } public void Close() { gameObject.SetActive(false); } }