Are global scripts good for behaviour?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By SanchezSDario

Hi! first of all sorry if I can’t explain myself well, english is not my language but I’ll do my best, plus I’m a student of college, this question is based on a proyect of study, keep this in mind at the time to answer me.
As the title says I’m using global scripting for certain behaviour that is recurrent between nodes, for example Movement. I have so many nodes that do move that I wish to modularize that movement in one script to make every node that moves can call a function move in that script that resolves that logic, that function will be prepared to handle every node that moves, supose that I have a car and a person, they will call a moving function in a global script that resolves movement and it will properly move one or another using parameters or states in the nodes that are calling.
I just want to know if this is good, I mean performantly or a good practique in GDScipt… Remember that this is a project of study, certains things are permitted but I wish to know all the opinions that you have.

:bust_in_silhouette: Reply From: MysteryGM

Using global behavior like this is really bad design, it maybe sounds good in theory but always breaks apart in practice.

Take the move example you have. Different types of movement is different. For example with a character you will maybe want them to slowdown when walking up a slope and remain walking strait up.
enter image description here
A vehicle will only slow down if the slope is very steep, but will always be angled along the slope.
enter image description here
This is already 2 objects moving differently as more objects gets added in the worse this gets.

In a local design if the character stops moving but the vehicle drives around we know that the characters walking code is where the problem is located.
In a global script so many values depend on each other that a butterfly effect could happen, where the player stops moving because the vehicle is tweaking the speed.

There is millions of other problems, like cesspools when object pooling because the values can’t reset without breaking everything.
Loading doesn’t reset all the global variables leading to exploits, the S.T.A.L.K.E.R games where full of these.

Global design is a bad practice simple as that and is better left for only a few minor things in any project.

I see… and how about having scenes that haves a simple Node with a script wich resolves the logic? imagine this example but instead a global script this will be a scene wich I load on the scripts of the person and the car… I want to know if things like this could be do, because there’s a lot of mevement that are similar between them. I want something like entity-component-system, there’s a way to do it in Godot?

SanchezSDario | 2018-10-07 13:37

Godot uses the inheritance approach, as do most modern engines and languages.

For example, you start by making a top class for the hierarchy. We call this first class Pawn all the objects that can move are Pawns.

In the Pawn class we create the func Move() and now all the pawns can move.

In GDscript the extends part tells us where the class is derived from. So to make my vehicle and character I make 2 new scripts.
Vehicles extends Pawn and so it can Move()
Characters extends Pawn and so it can Move()
enter image description here
The advantage of this system is that it floods down, unlike a global system where the vehicles could effect the character, here each stands on it’s own.

Now consider these two problems. First none of the objects can move:
enter image description here
When we look at this structure it is easy to see that the Pawn is where the bug is.
Now what if only the vehicles stopped moving:
enter image description here
Again, easy to find the bug. Because the flow of code can go only one way. Unlike a global system where each object can impact each other.

The best yet is that you can override the functions inherited. For example if one child has to change move we do it like this:

#Start to overwrite it
func Move(): 
   Var DoSomething = 0
   #Then we call the old move like this
   .Move()

Now because we aren’t just overwriting but also calling the old function, we actually extend how the old function worked.
If you don’t call the old function then you are just overwriting it with a completely new function.

This is a nice clean way to make games.

MysteryGM | 2018-10-07 17:31