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

Godot 4.1.1中实例化函数生成过多对象问题求助

解决砍树系统生成过多倒下树木的问题

问题根源

你的核心问题是每个基础树木节点上都挂载了这份脚本。当你用射线选中一棵树时,场景中所有挂载该脚本的树都会检测到射线碰撞(ray.is_colliding()对所有脚本实例来说结果都是true),当点击次数达标后,每棵树的脚本都会执行spawn_trees函数,导致生成的倒下树木/树桩数量等于场景中未砍伐的基础树数量。

解决方案

方案1:将砍树逻辑移到全局/玩家节点(推荐)

把砍树逻辑集中在单一节点(比如玩家节点或全局树管理节点)上,避免多份脚本重复执行:

extends Node3D

var tree_fallen = preload("res://Assets/Trees/pine_tree_fallen.tscn")
var tree_stump = preload("res://Assets/Trees/pine_tree_stump.tscn")

@onready var ray = get_node("Head/Camera3D/TreeHitRay")

var clicks = 0
var current_target_tree: Node3D = null

var timer = Timer.new()

func _ready():
    timer.wait_time = 0.5
    timer.one_shot = true
    add_child(timer)

func _process(_delta):
    current_target_tree = null
    # 仅识别射线命中的树木(需给所有基础树添加"Tree"分组)
    if ray.is_colliding():
        var collider = ray.get_collider()
        if collider.is_in_group("Tree"):
            current_target_tree = collider.get_parent()

    # 仅在有有效目标且计时器停止时响应攻击
    if Input.is_action_just_pressed("Attack") and timer.is_stopped() and current_target_tree != null:
        clicks += 1
        timer.start()
        if clicks == 3:
            clicks = 0
            spawn_trees(current_target_tree)

func spawn_trees(target_tree: Node3D):
    var main = get_node("/root/World/Stage/Trees/TreeByproducts")
    var tree_global_pos = target_tree.global_position
    
    target_tree.queue_free()
    
    # 生成倒下的树
    var fallen_tree = tree_fallen.instantiate()
    main.add_child(fallen_tree)
    fallen_tree.global_position = tree_global_pos
    fallen_tree.rotation.x = randf_range(2.0, 5.0)
    fallen_tree.rotation.z = randf_range(2.0, 5.0)
    
    # 生成树桩
    var stump = tree_stump.instantiate()
    main.add_child(stump)
    stump.global_position = tree_global_pos

关键修改点:

  • 将脚本移到玩家节点下,仅运行一份逻辑
  • 新增current_target_tree变量,只记录当前被射线命中的树木
  • 通过分组判断确保只响应树木对象(需在编辑器给基础树添加Tree分组)
  • 攻击逻辑仅在存在有效目标时触发,避免多脚本重复执行

方案2:在原脚本中添加自我判断

如果不想移动脚本,可在每个树木的脚本中添加判断,仅当射线命中的是自己时才执行逻辑:

func _process(_delta):
    if ray.is_colliding():
        var obj = ray.get_collider()
        var obj_local = obj.get_parent()
        
        # 新增:仅当命中的树是当前脚本所在节点时才继续处理
        if obj_local != self:
            return
        
        if Input.is_action_just_pressed("Attack") and timer.is_stopped():
            clicks += 1
            timer.start()
            if clicks == 3:
                clicks = 0
                spawn_trees(obj_local)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 20:25:16