我正在用 react-native 开发游戏,主游戏 View 还必须包含倒计时。在这里,我将其简化为只有一个数字表示。
我写了一个简单的自定义钩子
useTimer
主要是为了检查时序波动使实际时间偏离目标的程度。
import { useState, useEffect, useRef } from "react";
const useTimer = (ms, tick) => {
const [time, setTime] = useState(ms),
[started, setStarted] = useState(false),
ref = useRef(),
stop = () => {ref.current && clearInterval(ref.current)},
start = time => {
time && setTime(time)
setStarted(true)
};
useEffect(() => {
if (!started || time <= 0) { stop() return stop}
ref.current = setInterval(() => setTime(t => t - tick), tick)
return stop
}, [time, started])
return { time: (time / 1e3).toFixed(2), start, stop }
};
export default useTimer;
然后裸体View
import React from 'react'
import { StyleSheet, View, Text, Pressable } from 'react-native'
import useTimer from './../hooks/useTimer'
import {FIFTYTHREE, tick} from './../constants'
/**
* as u might suspect FIFTYTHREE value is 53
* then tick is 10, yes 10
*/
const Timer = () => {
const {start, stop, time} = useTimer(FIFTYTHREE * 1e3, tick)
return <View>
<Pressable onPress={() => start()}>
<Text>{time}</Text>
</Pressable>
</View>
};
export default Timer
然后我在模拟器中启动它,几秒钟后一切似乎都很好,
感觉有些不对劲,速度很慢,所以我把手机放在一边,粗略地测量一下
1分34秒!!!
这个倒计时非常精确(公差可以达到±1%)对游戏来说至关重要
众所周知,本地
setTimeout
和 setInterval
遭受波动(主要是过度),总结起来,这解释了延迟,这与 tick
值成反比;tick
更改为 100
毫秒,让倒计时在 59
秒内完成,这是向前迈出的一大步......但仍然远离所需的约束。tick
设置为 500
毫秒(真的不可接受)并且需要 55
秒才能达到零。
我做的下一次尝试是使用我很久以前写的 setInterval 的自校准版本,
var t = 53e3,
tick = 10,
start = +new Date,
end,
i = interval(() => {
t -= tick;
if (t <=0) {
end = +new Date;
console.log(end-start)
i.clear();
}
}, tick).run();
我在控制台中到达这里
53001
因此现在我可以合理地从等式中排除间隔问题,tick
值严格相关,并且肯定会影响 react-native。
此外听起来合理的是,设备规格和资源也将同意扭曲测量并使其绝对不确定。这就是为什么我开始怀疑没有办法在 react-native 中有一个好的解决方案,但我宁愿使用 swift 转向 ios 适当的开发。
我想知道是否有人在 react-native 中遇到并可能解决了类似的问题,或者唯一的方法是否真的是转移到 Xcode。