|
|
|
|
Attention |
Topic was automatically imported from the old Question2Answer platform. |
|
Asked By |
random_char |
I’m trying to create a character, which consists from different body parts (body, head, arms, legs etc). There can be different types of same body part, e.g. normal arms, wooden arms, metal arms. The idea is to modify character parameters based on the type of each body part (lets say metal arms allow to pick heavy objects but reduce jumping height). I have a following setup (for simplicity lets just use character and arms entities)
BaseCharacter
scene with BaseCharacter.gd
script
BaseArms
scene with BaseArms.gd
script
MetalArms
scene with MetalArms.gd
script. MetalArms
scene inherits BaseArms
scene, same for scripts, MetalArms
inherits BaseArms
Next, I want to instance character body parts from code (so later they can be changeable at runtime). I’ve got some programming background and at first I’ve decided to use Dependency Injection (DI). With DI I just modify character _init
to have _arms: BaseArms
parameter and then can create characters passing needed arms, which all inherit BaseArms.gd
. That works just fine but only with scripts. Is there a way to use some kind of DI with scene instancing? Since if arms have not only behavior attached (scripts), but also some appearance (like BaseArms
scene has Sprite
and AnimationPlayer
child nodes), then it doesn’t work like that. I’ve tried to resolve this issue by preloading body parts and instancing them in Character
’s _init
method, but then I have hard time using their behavior.
So the questions are:
- Can I instance scenes with their scripts (which inherit some base scenes and scripts) in another scenes and have access to both scene nodes and script properties/methods
- Is there a way to use DI like principle to instance scenes?
- If I use scene instancing like the following, how to get the attached scene script?
we are in character script, say _init method
var arms_scene = preload("res://MetalArms.tscn")
self.add_child(arms_scene.instance())
self.arms = arms_scene.script? how to get this to work
Thanks a lot!
|
|
|
|
Reply From: |
magicalogic |
When you instance a scene from code you get access to all its properties and methods.
For instance if you instance an arm which has property length
and method hold()
, you can access them as arm.length
and arm.hold()
. In short the script is part of the scene so with access to the scene you have access to the script (in terms of properties and methods).
How is that done via code?
To instance a scene I have to
var a = preload("res://src/Entity/BodyParts/SomeArms.tscn").instance()
a.do_arm_stuff()
This doesn’t work.
If I do
var a = SomeArms.new(...)
a.do_arm_stuff()
This works, but I cannot access a scene object. Can You please provide a code snippet to show how You do instancing of a scene to access its properties and methods also?
random_char | 2021-05-09 08:58
var arm = preload("res://arm.tscn").instance()
arm.do_something()
magicalogic | 2021-05-09 09:02
hmmm, weird, I receive an error with this approach
Invalid call. Nonexistent function 'do_something' in base 'Node2D'.
A note: though it may be caused by class declaration in related scripts - apparently not, still receiving this error
random_char | 2021-05-09 09:08
That was just an example which you should replace with your own methods.
magicalogic | 2021-05-09 13:06
Yes, I’ve changed the names. Seems like I’ve missed somewhere script and scene connection -__
Anyway, apparently it is not possible to solve my initial problem, but thanks to You I’ve found a suitable working solution just for now
random_char | 2021-05-09 21:20
|
|
|
|
Reply From: |
random_char |
Ok, for all who wonder, this is what seems to work and what cannot be done:
- It’s impossible (or really obscure) to call
_init
during scene creation in code, so lets just create simple init
method to mimic its behavior. Ofc you’ll need to keep track of this by yourself now
- Create a base scene and attach a base script to it (e.g.
BaseArms.tscn
and BaseArms.gs
). Make needed inherited scenes, attach new scripts, which inherit the base script (e.g. MetalArms.tscn
with MetalArms.gd
which inherit BaseArms
scene and script respectively). I don’t know if this is necessary, but i’ve also changed MetalArms.tscn
root node type to MetalArms
(it will appear in Nodes list if you set class_name
of your scripts)
- When you need to create body part scene, use something like this (say this is part of character script which has
arms: BaseArms
property
self.arms = preload(...).instance()
self.arms.name = "Arms"#to allow access to child node as $Arms
self.arms.init(...)
self.add_child(self.arms)