Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MultiScript and "overlapping" method names #8546

Closed
eon-s opened this issue Apr 26, 2017 · 19 comments
Closed

MultiScript and "overlapping" method names #8546

eon-s opened this issue Apr 26, 2017 · 19 comments

Comments

@eon-s
Copy link
Contributor

eon-s commented Apr 26, 2017

Godot version: 3 master

Issue description:
MultiScript has some inconsistent way in which it works with "overlapping" methods.

Some methods like _init and _process are called on every script, while others like _ready, _enter_tree and name_your_function are called only on the first script where it is defined.

This makes not possible to do common things like initialize variables on secondary scripts when the node enters the tree, also not possible to make a single function call affecting all the scripts, reducing the usability of MultiScript.

I would prefer to have everything called on every script, if I do $Node.foo(), have ScriptA.foo() and ScriptB.foo() executed.


And what if foo() returns a value? I have no idea...

I wonder if will be needed some kind of keyword before func to control the way multi-methods are called (call all, just the first, override, and things like that).

Or maybe a multi version of call, a multi_call that returns an array of results (but the problem with enter tree and ready persist).

Steps to reproduce:

  • Make two scripts with _init, _ready, enter_tree, _process and another function
  • Check the method calls, notice on which scripts are called each.
@karroffel
Copy link
Contributor

The problem is that it's impossible to have multiple scripts on one object. So what I'm doing is create a dummy object for every script that just call()s the real object.

_init gets called when the script instance gets created, so that happens on every script (because I attach them to an object).

call() stops after the first script that implements that method, notification and call_multilevel call it on every script. So that's where this behavior is coming from.

I agree, it should be more consistent, but the return value problem is a real problem

@akien-mga
Copy link
Member

IMO calling the same function name on all scripts is a no go. By itself this problem makes me wonder if it's worth it at all to reintroduce MultiScript.

I think it should not be allowed to define the same function name in sibling scripts. The parser should raise an error if it happens. Callbacks like _init, _ready or _draw are specific to the node, and not to its script, so it shouldn't be necessary to call them in each script. If all sibling scripts have a _draw call, what's the draw order?

All in all this is raising quite some complexity. How does member var scoping works in MultiScript? Do all scripts share a same scope as if it were one file, or are they handled as separate classes?

@volzhs
Copy link
Contributor

volzhs commented Apr 26, 2017

now I understand why @reduz doesn't want it.
how does unity handle this?
as I remember, it's something like get_node(path).get_component(script_name).func_name().
(don't want to search it...)

edit: I think I misunderstood what OP said about anyway...

@eon-s
Copy link
Contributor Author

eon-s commented Apr 26, 2017

@akien-mga if I want to update all the variables on a node, I will need to call update functions on all the scripts, if I don't know which scripts are there, I won't know which functions update each script (a script can access another script variable but defeats MultiScript purpose, I think).

The scope seems to be shared but (now) the first script sets the variable and methods (tested with export too), but is strange, some may expect the last script overrides the first 🙃

@Zylann
Copy link
Contributor

Zylann commented Apr 26, 2017

@volzhs in Unity scripts are completely separated objects that must be called explicitely (gameObject.GetComponent<Foo>().SayHello()), but they share the same GameObject through a gameObject property (note: nothing inherits GameObject, everything is done through components). Special functions such as Update, FixedUpdate or OnGUI are called by the engine on all scripts defining the method. No inheritance, no multicall wizardry. Their execution/call order doesn't matter, unless specified in project settings. Sometimes (for image effects) their order in the component list is used, for the OnRenderImage I think but I'm not sure.

@eon-s
Copy link
Contributor Author

eon-s commented Apr 26, 2017

The "class fusion" nature of multiscript is the problem, another thing would be if is implemented as a kind of interface or polymorphism but making the extra scripts pure Object (no ready, no process, just regular variables and methods).

@hubbyist
Copy link

hubbyist commented Apr 27, 2017

Can't multi scripts be implemented as traits like in php and bind to parent script via for example "Inherits" keyword? This will solidify override order and double calls for _ready and other functions may be resolved this way. But this may need more complex script handling as well.

@mablin7
Copy link
Contributor

mablin7 commented Apr 29, 2017

I think this whole feature is unnecessary. If you start using Godot, coming from Unity, you may want something like components, but as soon as you understand the engine's design you'll realize, there is no need for this.
But if we really want to implement this, I think we should go with Unity like components, while keeping the current script system. So, for example, each object could have a list of scripts (besides the original single script), maybe as @eon-s said attached to other objects or some special helper class.
But that's almost the same as adding additional nodes with scripts to your original node.

@ProbDenis
Copy link
Contributor

There is one use case where I think a feature like this would make sense. When you write an EditorPlugin that adds custom node types, the instanced nodes all share the original script, and you can't just add a new script like you would do with the built-in node types. Of course there are many ways around this, but at least this is a case where I would like to have the ability to add a second script.

@karroffel
Copy link
Contributor

It was just a test. Some users want to try it out regardless, but I'm okay with removing it again

@reduz
Copy link
Member

reduz commented Apr 29, 2017 via email

@Zireael07
Copy link
Contributor

instead of just using children nodes...

Which is more performant though, children nodes or multi script? Even if the node is just a dummy Spatial or Position, I guess it takes memory, doesn't it?

@Zylann
Copy link
Contributor

Zylann commented Apr 29, 2017

@Zireael07 you can use Node, which is the dummyest node you can create in Godot ;) it will always take a bit of memory though

@mablin7
Copy link
Contributor

mablin7 commented Apr 29, 2017

Although the multi script might really be faster, I don't have any numbers, and in my opinion it just doesn't worth the extra hassle, and primes that comes with it.

@DriNeo
Copy link

DriNeo commented Apr 30, 2017

I would like to ask a question because I am curious. What is the difference between the multiscript feature and the current ability to load script files in your node script ? I apologize if the answer is obvious.

@karroffel
Copy link
Contributor

@DriNeo If you load a script file in your script then a second script can't easily all methods on that. If you use a multiscript then you're merging multiple scripts.

So you can have one script that handles signals for physics (in an Area or a PhysicsBody) while other scripts do something completely different

@DriNeo
Copy link

DriNeo commented Apr 30, 2017

Thanks.

@karroffel
Copy link
Contributor

Closing with the removal of the multiscript module.

@starry-abyss
Copy link
Contributor

What if the new inline inspector (https://twitter.com/reduzio/status/997078709847834624) allowed nodes in the same way as resources? If all NodePath variables were also shown inline.
I.e. add children nodes with scripts and allow them to be shown in the inspector, and not just in the scene tree. They are then usable with $component1, $component2, etc, while the appearance is similar to Unity's.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests