You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Godot 4中Array添加元素覆盖旧值问题及原理、优化疑问

Godot 4数组append元素被覆盖问题解析

问题场景

我解决了Godot 4中的一个问题,但不理解原理:向Array执行append操作时,最后添加的值会覆盖数组中所有已有元素。

原代码

var myBus=BusinessType.new()

func _on_load():
   for i in businesses_json.get_data():
    
    myBus.name=i.name
    print ("showint previous array after name:")
    for j in Global.businesses:
        print (j.name)
    myBus.location=i.location
    print ("adding "+myBus.name)    
    Global.businesses.append(myBus)
    print ("now the global array is:")
    for j in Global.businesses:
        print (j.name)

原代码运行输出

showint previous array after name:
adding first
now the global array is:
first
showint previous array after name:
second
adding second
now the global array is:
second
second
showint previous array after name:
third
third
adding third
now the global array is:
third
third
third
number business = 3

修改后的代码(将实例化移到循环内)

func _on_load():
   for i in businesses_json.get_data():
    var myBus=BusinessType.new()
    myBus.name=i.name
    print ("showint previous array after name:")
    for j in Global.businesses:
        print (j.name)
    myBus.location=i.location
    print ("adding "+myBus.name)    
    Global.businesses.append(myBus)
    print ("now the global array is:")
    for j in Global.businesses:
        print (j.name)

修改后运行输出

showint previous array after name:
adding first
now the global array is:
first
showint previous array after name:
first
adding second
now the global array is:
first
second
showint previous array after name:
first
second
adding third
now the global array is:
first
second
third
number business = 3

疑问

  • 为何在每次循环中重新定义变量能解决问题?
  • 这是不是类似指针的引用机制?
  • 每次循环实例化对象会不会消耗更多内存?
  • 有没有更优的实现方式?

问题解析与解答

1. 为什么移到循环内就能解决问题?

因为Godot中的自定义类实例属于引用类型。循环外创建的myBus是同一个对象,每次循环只是修改这个对象的name和location属性,然后将该对象的引用添加到数组中。数组里所有元素指向的都是同一个对象,所以最后所有元素显示的都是最后一次修改的属性值。

把实例化代码移到循环内后,每次循环都会创建一个全新的BusinessType对象,修改新对象的属性后再添加到数组,数组里的每个元素都指向不同的独立对象,自然不会互相覆盖。

2. 是不是类似指针的引用机制?

没错。Godot的引用类型变量存储的是对象在内存中的引用(逻辑和指针类似),而非对象本身的副本。当你把myBus添加到数组时,数组存储的是这个引用,而不是对象的克隆体。因此修改原对象的属性,数组中引用指向的对象也会同步变化。

3. 每次循环实例化会不会消耗更多内存?

正常业务场景下完全无需担心这点内存消耗。你本来就需要创建对应数量的BusinessType对象来存储不同的业务数据,这些内存占用是合理且必要的。只有当需要创建上万级甚至更多的对象时,才需要考虑用对象池复用实例,但这种场景在普通Godot项目中极少出现。

4. 更优的实现方式

可以给BusinessType添加带参数的构造函数,简化循环内的代码逻辑:

# 在BusinessType类中添加构造函数
func _init(new_name: String, new_location: String):
    name = new_name
    location = new_location

# 循环中直接实例化并赋值
func _on_load():
   for i in businesses_json.get_data():
    var myBus = BusinessType.new(i.name, i.location)
    Global.businesses.append(myBus)

这样代码更简洁,逻辑更清晰。另外如果不需要调试打印,建议删除循环内的print语句,提升运行效率。


内容的提问来源于stack exchange,提问作者Easy Cap

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 10:05:12