Вопрос по ООП, экземпляр моего класса, при его создании и добавлении в дерево должен являться сценой (композицией нод), а не одной нодой
Как сделать так, чтобы экземпляр моего класса, при его создании и добавлении в дерево являлся сценой (композицией нод), а не одной нодой. (моя реализация кажется мне слишком костыльной)
То-есть проблема моей первой реализации состоит в том, что я создаю объект класса через var entity = Entity.new(аргументы для _init()), он успешно создаётся в памяти, весь скрипт срабатывает, а потом я добавляю этот объект в дерево add_child(entity) - он создаёт ноду CharacterBody2D, которую расширяет мой класс, а тк она не является Entity.gd - то не имеет его функционала (такая реализация бесполезна, ибо я просто создаю в памяти нужный мне объект, а в дереве появляется жопа)
Тогда я решил сделать опять же var entity = Entity.new(аргументы для _init()), он успешно создаётся в памяти, весь скрипт срабатывает, а потом я добавляю этот объект в дерево add_child(entity.preloaded_scene.instantiate() #preloaded_scene - это preload("res://scenes/entity.tscn"), такая реализация работает, но проблема в том, что я получаю в памяти два объекта entity, а в дерево добавляется только второй. Я хз как я написал этот костыль, но дубликат возникает из-за того, что когда я подгружаю сцену, корневой нодой которой является нода типа Entity.gd а при её добавлении в памяти создаётся ещё один объект Entity.gd, который уже и указывает на визуализированную сцену в дереве, в то время как изначальный объект теряется в памяти. (вот пока что такая у меня реализация, буду рад, если кто-то подскажет как мне убрать это лишнее звено в виде изначального объекта)
Возможно все проблемы в моей реализации класса Entity.gd:
extends CharacterBody2D
class_name Entity
var preloaded_scene = preload("res://scenes/entity.tscn")
var _name: String
var speed: float
var hp: int
var max_hp: int
var label; var label_hp; var collision
func _ready():
print("сцена добавлена в дерево")
label = $Label
label_hp = $Label_hp
collision = $CollisionShape2D
label.text=_name
label_hp.text="{cur_hp} / {max_hp}".format({"cur_hp": hp, "max_hp": max_hp})
func _init(_name_of_entity: String = "Entity", speed_of_entity: float = 200.0, hp_of_entity: int = 20):
print("объект создан")
_name=_name_of_entity
hp = hp_of_entity
speed=speed_of_entity
max_hp=hp
Ответы (1 шт):
Если вам нужно, чтобы наследуемые объекты имели все параметры базового, то предлагаю следующий вариант:
Наследование объектов
- Создаем базовую сцену с желаемой структурой, от которого будут наследоваться.
- Задаем параметры.
Параметры, которые будут меняться у наследуемых объектов, задаем через export
(Export Properties).
@export var _name: String = "Entity"
@export var _speed: float = 200
@export var _max_health: int = 100
var _health: int
Не забываем про объекты сцены.
@onready var sprite: Panel = $Sprite
@onready var collision: CollisionShape2D = $Collision
@onready var name_label: Label = $Name
@onready var health_label: Label = $Health
- Пишем логику инициализации сцены.
func _ready() -> void:
self._health = self._max_health
self.name_label.text = self._name
self.health_label.text = "HP: %d" % self._health
# Для наглядности вывожу данные о сцене
print("Сцена `%s` добавлена в дерево" % self._name)
print("- Speed: %d" % self._speed)
print("- HP: %d\n" % self._health)
Полный код (entity.gd):
class_name Entity extends CharacterBody2D
@export var _name: String = "Entity"
@export var _speed: float = 200
@export var _max_health: int = 100
var _health: int
@onready var sprite: Panel = $Sprite
@onready var collision: CollisionShape2D = $Collision
@onready var name_label: Label = $Name
@onready var health_label: Label = $Health
func _ready() -> void:
self._health = self._max_health
self.name_label.text = self._name
self.health_label.text = "HP: %d" % self._health
print("Сцена `%s` добавлена в дерево" % self._name)
print("- Speed: %d" % self._speed)
print("- HP: %d\n" % self._health)
- Теперь, когда нам нужно создать наследуемую сцену, делаем это через
Instantiate Child Scene
(иконка цепи).
Выбираем базовую сцену, от которой наследуемся.
- Если нужно изменить параметры какого-либо объекта сцены, выбираем нужный и нажимаем на
Make Unique
.
Например, если нужно изменить размер коллизии, то выбираем объект CollisionShape2D
.
Нажимаем на стрелку вниз и из выпадающего списка выбираем Make Unique
.
Итог
Результат.
Вывод:
Сцена `Entity` добавлена в дерево
- Speed: 200
- HP: 100
Сцена `Player` добавлена в дерево
- Speed: 500
- HP: 200
Сцена `Enemy` добавлена в дерево
- Speed: 100
- HP: 50
Дерево сцены:
┖╴Playground
┠╴Entity
┃ ┠╴Collision
┃ ┠╴Sprite
┃ ┠╴Health
┃ ┖╴Name
┠╴Player
┃ ┠╴Collision
┃ ┠╴Sprite
┃ ┠╴Health
┃ ┖╴Name
┖╴Enemy
┠╴Collision
┠╴Sprite
┠╴Health
┖╴Name
Как по мне, такой подход к созданию экземпляров сцены подходит для быстрого создания статических объектов. Например, если игра в жанре "выживание", таким объектом будет предмет, который может подобрать игрок (например, камень, палка и т.д.).
Советую вам ознакомиться с системой компонентов (ссылка на статью)