实例化对象有一个问题。
一方面,对于一个场景中的一个弹丸,我有以下脚本:
extends KinematicBody2D
var speed = 200
var life_time = 2
var life_spawn = 0
func _physics_process(delta):
var collision = move_and_collide(Vector2.UP * delta * speed)
life_spawn += delta
if life_spawn > life_time:
queue_free()
pass另一方面,我在另一个场景中使用了以下脚本:
extends KinematicBody2D
func _physics_process(delta):
if Input.is_action_pressed("ui_accept"):
createLaser()
pass
func createLaser():
var laser = preload("res://scenes/space_ship/laser/Laser.tscn")
var left_fired_laser = laser.instance()
var right_fired_laser = laser.instance()
var left_cannon = get_node("Cannons/left_cannon").get_global_position()
var right_cannon = get_node("Cannons/right_cannon").get_global_position()
left_fired_laser.position = Vector2(left_cannon.x, left_cannon.y)
get_parent().call_deferred("add_child", left_fired_laser)
right_fired_laser.position = Vector2(right_cannon.x, right_cannon.y)
get_parent().call_deferred("add_child", right_fired_laser)
pass问题是对象被实例化了很多次。即使我放了一个put ()函数。如果我将该函数放入该函数,则该对象等待实例化,但它仍然会被实例化很多次。
发布于 2021-08-09 06:29:41
多少次和多久一次?
你说:
问题是对象被实例化了很多次。
但多少次才算多呢?
我会回答想到的案子。另外,其中一些也可以结合起来。
如果这个答案没有涵盖您想要的内容,…你需要更具体一些。通过展示这一点,希望您能够考虑到以下工具来解决这个问题:
在is_action_just_pressed.
is_action_pressed之间选择Timers (实际对象或与delta).
Timers).
的timeout信号)
说到信号,下面的所有方法都不需要对实例有任何特殊的了解(除了它是一些Node2D)。您可以向实例添加自定义信号,并连接到它们,以了解何时可以创建更多实例。
您可以做的另一件事是保存对实例的引用来询问它们(例如,您可以使用is_instance_valid)。但是,下面我介绍了一种使用tree_exited信号的方法,我认为这种方法更通用。
您还可以使用call方法跟踪来利用AnimationPlayer。例如,如果需要将实例添加到动画的特定框架中。
每输入一次
只要按下输入,此代码就会执行每个物理帧:
func _physics_process(delta:float) -> void:
if Input.is_action_pressed("ui_accept"):
createLaser()如果只想在按下输入时实例第一个物理帧,请使用is_action_just_pressed
func _physics_process(delta:float) -> void:
if Input.is_action_just_pressed("ui_accept"):
createLaser()每隔一次
我们可以使用与子弹寿命相同的临时计时器策略:
var instance_period:float = 10.0
var instance_elapsed:float = 0.0
func _physics_process(delta:float) -> void:
instance_elapsed += delta
if Input.is_action_pressed("ui_accept") and instance_elapsed > instance_period:
createLaser()
instance_elapsed = 0.0只有一次
如果您只想要一个,我们可以持有一个布尔变量来知道我们是否已经安装了:
var did_instance:bool = false
func _physics_process(delta:float) -> void:
if Input.is_action_pressed("ui_accept") and not did_instance:
createLaser()
did_instance = true只有固定的次数
您可以使用整数倒计时:
export var yet_to_instance:int = 10
func _physics_process(delta:float) -> void:
if Input.is_action_pressed("ui_accept") and yet_to_instance > 0:
createLaser()
yet_to_instance -= 1我使它成为一个导出变量,这样您就可以从检查面板中编辑它。
*这种方法与“每次输入一次”(即使用is_action_just_pressed)很好地结合在一起。此外,当数字为1时,您也可以将“只有一次”视为特例。
充电次数
这是一种将临时计时器与固定次数的概念结合起来的特殊方法:
var recharge_period:float = 10.0
var recharge_elapsed:float = 0.0
export var max_to_instance:int = 10
onready var yet_to_instance:int = max_to_instance
func _physics_process(delta:float) -> void:
if Input.is_action_pressed("ui_accept") and yet_to_instance > 0:
createLaser()
yet_to_instance -= 1
# recharge_elapsed = 0.0
recharge_elapsed += delta
if recharge_elapsed > recharge_period:
if yet_to_instance < max_to_instance:
yet_to_instance += 1
recharge_elapsed = 0.0这样,您可以创建的实例数量最多会增加加班时间。如果您想要阻止该数字在有输入时增加,可以取消注释# instance_elapsed = 0.0。你可以把它想象成自动重新装载。
这种方法与“每次输入一次”(即使用is_action_just_pressed__)很好地结合在一起。或者用“每隔一次”(即临时时间)来限制实例率。
最多是活着的数量
我们将连接到tree_exited信号以更新计数:
const laser = preload("res://scenes/space_ship/laser/Laser.tscn")
export var max_to_instance:int = 20
func _physics_process(delta:float) -> void:
if Input.is_action_pressed("ui_accept") and max_to_instance > 0:
createLaser()
func createLaser() -> void:
createLaserFrom($Cannons/left_cannon)
createLaserFrom($Cannons/right_cannon)
func createLaserFrom(cannon:Node2D) -> void:
var fired_laser = laser.instance()
max_to_instance -= 1
fire_laser.connect("tree_exited", self, "laser_exited")
get_parent().add_child(fired_laser)
fired_laser.global_position = cannon.global_position
func laser_exited() -> void:
max_to_instance += 1这种方法与“每次输入一次”(即使用is_action_just_pressed__)很好地结合在一起。或者用“每隔一次”(即临时时间)来限制实例率。
https://stackoverflow.com/questions/68707012
复制相似问题