在Godot中实现下载更建议使用HttpClient,它不是控件。主要是在其它线程中进行下载,在_process()中显示进度。保存时使用 file.store_buffer。
原始代码如下,可以进一步优化或变为公共功能调用。这样就实现了通过Web下载游戏包(进行升级)
UI很简单,一个控件显示文字,一个控件显示进度。
下载主体部份在官方有示例。
extends Node2D
var thread: Thread
var currentSize :int
var totalSize :int
var updateInfo :String
func _process(_delta):
$ProgressBar.value = currentSize
$ProgressBar.max_value = totalSize
$Text.text = updateInfo
if currentSize == totalSize and totalSize!=0:
OS.delay_msec(500)
LoadPCK()
# 保存文件
func save(filename,content):
var file = FileAccess.open(filename, FileAccess.WRITE)
file.store_buffer(content)
# 下载pck
func downPCK():
print("下载Pck文件")
var http = HTTPClient.new()
var err = http.connect_to_host("127.0.0.1",7000)
assert(err==OK)
# 等待,直到解决并连接为止
while http.get_status() == HTTPClient.STATUS_CONNECTING or http.get_status() == HTTPClient.STATUS_RESOLVING:
http.poll()
updateInfo = "连接服务器..."
OS.delay_msec(100)
assert(http.get_status() == HTTPClient.STATUS_CONNECTED) # 检查该连接是否已成功完成。
var headers = [
"User-Agent: Ease/1.0 (Godot)",
"Accept: */*"
]
err = http.request(HTTPClient.METHOD_GET, "/down/first.pck", headers)
assert(err == OK)
while http.get_status() == HTTPClient.STATUS_REQUESTING:
# 只要正在处理请求,请一直保持轮询。
http.poll()
updateInfo = "请求数据包..."
assert(http.get_status() == HTTPClient.STATUS_BODY or http.get_status() == HTTPClient.STATUS_CONNECTED)
#print("response? ", http.has_response()) # 网址是否有返回
#if http.has_response():
#headers = http.get_response_headers_as_dictionary() # 获取头信息
#print("code: ", http.get_response_code()) # 显示响应代码
#print("headers: ", headers) # 显示头信息
# 获取HTTP内容
if http.is_response_chunked():
print("响应被分块")
else:
# 或者只是简单的内容长度
totalSize = http.get_response_body_length()
print("返回长度: ", totalSize)
# 这个方法对两者都适用
var rb = PackedByteArray() # 将保存数据的数组
while http.get_status() == HTTPClient.STATUS_BODY:
http.poll()
# 获取块
var chunk = http.read_response_body_chunk()
if chunk.size() == 0:
pass
else:
rb = rb + chunk # 附加到读取缓冲区
updateInfo = "下载中... %d / %d KB" % [currentSize/1024, totalSize/1024]
printt(currentSize,totalSize)
currentSize = rb.size()
if currentSize == totalSize:
save("./first.pck",rb)
# 载入pck资源文件
func LoadPCK():
var HavePCK = false
var dir = DirAccess.open(".")
if dir:
var files = dir.get_files()
for file in files:
if file.get_extension() == "pck":
HavePCK = true
ProjectSettings.load_resource_pack(file)
if HavePCK:
if ResourceLoader.exists("res://framework/scenes/launch/launch.tscn"):
get_tree().change_scene_to_file("res://framework/scenes/launch/launch.tscn")
return HavePCK
func _ready():
thread = Thread.new()
if !LoadPCK():
thread.start(CheckPCK)
func CheckPCK():
downPCK()
func _exit_tree():
thread.wait_to_finish()
要注意的是:因为下载时间可能比较久,服务端需要设置好超时时间。否则将导致不能完全下载就断开的情况。