【Godot4】TextureProgressBarが早く減る!stepの初期値が罠だった
2026-11-13
Godotで時間とともに減るゲージを作ったところ、同じコードでもTextureProgressBarだけ想定より早く減ってしまいました。
本記事では、stepの初期値による丸めが原因であることを、ProgressBarとの比較と実行ログで確認し、対処法を紹介します。
環境
- Godot4.7
- GDScript
具体例
- Control
- ProgressBar
- TextureProgressBar
上記のようなシーンを作成し、適切なsizeとpositionを設定します。
TextureProgressBarには任意の画像を設定してください。 TexturesのProgressだけ設定すれば最低限動きます。

シーンを実行したら二つのバーを最大にします。 その後、3秒間かけてvalueを減らしていきます。
スクリプトは親のControlに設定します。
extends Control
@onready var progress_bar := $ProgressBar
@onready var texture_progress_bar := $TextureProgressBar
func _ready() -> void:
progress_bar.value = progress_bar.max_value
texture_progress_bar.value = texture_progress_bar.max_value
func _process(delta: float) -> void:
progress_bar.value -= progress_bar.max_value * delta / 3.0
texture_progress_bar.value -= texture_progress_bar.max_value * delta / 3.0
動画では、上に配置したProgressBarが3秒かけてだんだんゲージが減っていたのに対して、 下に配置したTextureProgressBarが3秒より早くなくなってしまいました。
⚠️注意 TextureProgressBarが減らない場合
高FPSの環境では、1フレームの減算量が小さくなり、丸めによって値が変化しない場合があります。
本記事では「想定より早く減る現象」を再現するため、プロジェクト設定から最大fpsを60に制限してください。
その際にプロジェクト設定の高度な設定をONにしないと最大fpsを設定できないので注意してください。


問題点
先ほどのように3秒間でなくなるはずが、TextureProgressBarが3秒より早くなくなってしまいます。
これはTextureProgressBarが継承しているRangeのStepの値に原因があります。
Stepは0より大きい時、valueの値はmin_value+N*stepの形で表される値に丸められます。
例:min_valueが0.1でstepが0.2の場合、valueは 0.1、0.3、0.5 のような値をとります。
ProgressBarでの初期値は0.01でTextureProgressBarでの初期値は1.0です。
このstepの影響を調べたいと思います。
先ほどのプログラムの_process()を以下のように変更します。
func _process(delta: float) -> void:
print("delta: ", delta)
print("sub value: ", texture_progress_bar.max_value * delta / 3.0)
print("value: ", texture_progress_bar.value - (texture_progress_bar.max_value * delta / 3.0))
progress_bar.value -= progress_bar.max_value * delta / 3.0
texture_progress_bar.value -= texture_progress_bar.max_value * delta / 3.0
print("true value: ", texture_progress_bar.value)
4つのprint命令を追加しました。
それぞれ、deltaは経過時間、sub valueはその_process()でtexture_progress_bar.valueを減らす値、valueはstepの処理が入る前の値、true valueはstepの処理が行われた後の値を表しています。
実行時のログの一部を次の表に示します。
| delta | sub value | value | true value |
|---|---|---|---|
| 0.01666666666667 | 0.55555555555556 | 40.4444444444444 | 40.0 |
| 0.01666666666667 | 0.55555555555556 | 39.4444444444444 | 39.0 |
| 0.02071733333333 | 0.69057777777778 | 38.3094222222222 | 38.0 |
deltaには前のフレームからの経過時間が入るので多少の変動があるが大体1/60秒です。 stepが0より大きい場合、代入した値はstepで決まる刻みに丸められます。今回の step は 1.0 なので、計算結果の 39.444… が 39.0 になります。毎フレーム、この丸め後の値から再び減算するため、誤差が積み重なります。
実際に減らさなければならない値は0.555程度なのに40.0から39.0のように1.0も減らしてしまっています。 この誤差が積み重なり、想定した3秒より早く減ってしまっていました。
解決方法
大きく分けて二つの解決方法があります。
stepの値を小さくする
足し引きする値に対してstepが大きいので誤差が大きくなっています。
なので誤差が気にならない程度にstepの値を小さくすると、丸めによる誤差を抑えられます。
TextureProgressBarのstepを0.01にした結果です。
経過時間から計算して、丸め誤差の蓄積を防ぐ
stepの誤差が入っているvalueを使用しているのが問題なのでvalueを使わない計算方法にしましょう。
extends Control
@onready var progress_bar := $ProgressBar
@onready var texture_progress_bar := $TextureProgressBar
var elapsed_time = 0.0
func _ready() -> void:
elapsed_time = 0.0
progress_bar.value = progress_bar.max_value
texture_progress_bar.value = texture_progress_bar.max_value
func _process(delta: float) -> void:
elapsed_time += delta
progress_bar.value -= progress_bar.max_value * delta / 3.0
texture_progress_bar.value = texture_progress_bar.max_value - (texture_progress_bar.max_value * elapsed_time / 3.0)
スタートから経過した時間を記録するelapsed_timeを新たに追加し、それを使って値を計算します。
この方法でも表示値はstep単位に丸められますが、その値を次の計算に使わないため、誤差が積み重なりません。
まとめ
TextureProgressBarのstepの初期値は1.0なので誤差が大きく出てしまう可能性がある。
stepを小さくして丸めによる誤差を抑えるか、経過時間から値を計算して丸め誤差の蓄積を防げば良い💯