コンテンツ
バグ内容
画面外のクリックや処理落ち(あってはならない)などで床がずれるバグがある。
5年前にも起こることがあるとは認知していたが原因を探すより実装の優先が先のため放置していました。
原因
原因は床を動かすスクリプトの中にあった。
↓床を作るスクリプト
public class WallCreater : MonoBehaviour {
public List<GameObject> WallObjects;
public float wallWidth;
public int firstCreateNum;
public static int WallNum;
private int counter = 0;
// Use this for initialization
void Start () {
//初回に一定数生成
for(int i=0;i<=this.firstCreateNum; i++)
{
Instantiate(WallObjects[i% WallObjects.Count],new Vector3(0.0f,0.0f,-i*this.wallWidth), Quaternion.identity);
WallNum = i;
}
}
// Update is called once per frame
void Update () {
//数が定数より減っていれば生成
if (firstCreateNum > WallNum)
{
Instantiate(WallObjects[counter % WallObjects.Count], new Vector3(0.0f, 0.0f, -this.firstCreateNum * this.wallWidth), Quaternion.identity);
WallNum++;
counter++;
counter %= WallObjects.Count;
}
}
}
↓床を動かす
public class WallMove : MonoBehaviour {
public float confSpeed;
public static float Speed;
public float confDeletePosZ;
public static float DeletePosZ;
// Use this for initialization
void Start () {
//床を動かす速度を設定
if(this.confSpeed >= 0.0f)
{
Speed = confSpeed;
}
if (this.confDeletePosZ >= 0.0f)
{
DeletePosZ = confDeletePosZ;
}
}
// Update is called once per frame
void Update () {
//床を動かす
transform.Translate(0.0f,0.0f,Speed*Time.deltaTime);
//閾値を越えたらオブジェクトを削除
if(transform.position.z > DeletePosZ)
{
Destroy(gameObject, 0f);
WallCreater.WallNum--;
}
}
}
挙動としては
- 床を一定数生成
- インスペクタで設定されたSpeed値をUpdateで動かす
- 一定の位置を越えたら削除
- 床が一定数未満なら新しく生成
となっている。
全体で見たら床を動かすだけならこれで十分だが
Update内で床を動かすときこのようにしていた。
transform.Translate(0.0f,0.0f,Speed*Time.deltaTime);
特にこれを使用しているのが問題だった
Time.deltaTime
リファレンスは
https://docs.unity3d.com/ScriptReference/Time-deltaTime.html
Description
The interval in seconds from the last frame to the current one (Read Only).
When this is called from inside MonoBehaviour.FixedUpdate, it returns Time.fixedDeltaTime.
deltaTime inside MonoBehaviour.OnGUI is not reliable, because Unity might call it multiple times per frame.
これは前回のフレームから今回のフレームまでかかった時間のため、環境によって毎回違う。
通常は問題ないが
床を作るスクリプトのUpdateで床を生成している処理と合わせると。
この過程でアプリが止まるとずれてしまう
- 一定の位置を越えたら削除
- 床を作るスクリプトがUpdateで床を生成
- ここでアプリの処置が停止か遅延!!!
- 床を動かすスクリプトがUpdateで床を移動させる この時前回のフレームから今回のフレームまでかかった時間をSpeedで乗算されるので 非常に大きな値で移動する
- 「床を作るスクリプトがUpdateで床を生成」の床が初めて床を動かすスクリプトが Updateで処理落ち前の値で移動する
つまり
生成されたものと
すでに生成されている床が
処理落ちした瞬間だけ移動量が大幅に違うことになる。
解決方法
そもそも論になるが
Time.deltaTimeは面倒な前回のフレームから今回のフレームまでかかった時間を計測してくれているので非常に便利なものではあるが、
ここに関してはTime.deltaTimeを使用しなくてもよい
その他問題
床がずれるバグのほかに
処理に関してあまり非効率なやり方をしているので見直す必要がある。
その件に関してはまた次回
コメントを残す