+1 vote

From what I gathered from reading this:

http://godotengine.org/qa/4746/how-would-you-setup-structure-project-with-focus-scripting

is that its best to have a hierarchical approach and have the more complex code at root. I'm about to start working on script that I expect to be rather large, most likely at least 400 lines and I have multiple questions before I get started with it.

This script is going to be effecting and managing a lot of different things through a singular mechanic I've been working on.

Is there a certain line count that generally speaking scripts should be kept under before causing problems? (I understand that it depends on the complexity, which is why I'm saying generally speaking.)

Is putting something complex and possibly large into a global script a bad idea or on the contrary would it be beneficial to do so? The question above eluded to me that it might be a good idea. Especially for something that is going to globally effect multiple objects.

What platform is the most difficult to port too. My plan was the usual windows, ubuntu, android, ios? (My bets on ios but I'm somewhat biased against them)

Lastly I'd like some advice on my overall approach that I've come up through research and reading through as many of this sites articles as I can. Also as per advice from Zylann and multiple others here: http://godotengine.org/qa/4620/best-practices-question

My approach now that my defining mechanic is done is to version this as a base for other platforms instead of having to regress back to account for unique needs, than from there I was to have a loading scene and make each level a scene with everything besides static objects that don't soak up much memory being instanced in categorically, player, enemies, collectibles, scripted objects ect. If a level ends up being too large to load from the loading scene instance it in from a point where it will be loaded before the player can get to it. Maybe using visual distraction and animations to delay the player appropriately. Each main level will have a boss and my plan was to make them mechanically unique and somewhat complicated so I was thinking on making those there own scene thats loaded before hand. This is going to be a 2d and as of yet I'm sure what the overhead is going to be like or if preloading at checkpoints is going to even be necessary. Advice on that specifically would be nice. Besides all that my approach is to do art and sounds last on a per level basis. Normally (unless being aggravating and trying to get best practice scripts out of people more experienced than myself to improve my own code and learn =P) I tough things out but at this point now that my games main mechanic is working with ugly blue blocks I'd rather start this as prepared as possible instead of slogging uphill blindly with mud in my boots. If you read all this, thank you in advance and apologies for the range and brevity of these questions.

in Engine by (57 points)

2 Answers

0 votes

As a general rule, a script that is thousand-lines-long and doing multiple things is bad, because it's hard to decouple things, it can lead to unrelated-things bugs and cause trouble if you are working in a team. If you can split functionality, it is better to have several scripts focusing on specific logic. Unless you are alone and you're comfortable with large files :p
But even alone, if you come back one month later you'll wonder, "where the hell did I implemented this thing? What the fuck is this script doing?"

In my game I have such a script, but this is because 75% of it is running inside _fixed_process() for complex physics interaction, and it has debug code to monitor if everything is going well. At least, I managed to separate camera management on the camera node, because it's not related to physics and can work on its own. At the moment I have to keep the big script on the root node because it's a KinematicBody2D, I can't change it easily. If it becomes a problem, maybe I could create classes in separate files, instantiate them on the attached script, then forwarding events to them, actually reproducing a "component" approach, kind of. Or have child nodes, which is nice to have in the editor, but only if it makes sense from a designer point of view. If it's pure programmer logic, better have it hidden :p

If levels are big, you can load them (or parts of them) asynchronously: http://docs.godotengine.org/en/latest/tutorials/engine/background_loading.html

I only tested Windows 7, Windows 10 and Android export yet, they work well with no bugs at all. HTML5 is buggy, but sometimes kinda works. iOS is hard to test because I'd need a Mac. Apple is so annoying.

I'm developing a game myself, and I'm curious about possible approaches too so I don't have answer to everything. Experience in other engines/frameworks can help.

Edit: I see you added globals to your tags. Avoid global states. As much as you can. Use the hierarchy, references, have everything in a scope. I use globals only for stateless static functions or nodes that will be there for the whole program execution, not just game and menu, so... not that much :p

by (27,603 points)
edited by

I see. So far the only thing I have in global is related to my camera for scaling which seems to tie in with what your talking about.
So I'll avoid adding anything to global if possible unless it becomes necessary.
If I find anything out meaningful in this seemingly endless journey of stuff to learn in game design lol I'll make sure to share and discuss.
And yeah apple sucks but sadly they have a huge user base. Personally I'm android for life.

0 votes

The length of a class is not really an issue, but it can be a sign that you are breaking the single responsibility principle. Another sign that you may be using object orientation incorrectly is this:

This script is going to be effecting and managing a lot of different
things through a singular mechanic I've been working on.

Now I am not the object orientation police, so I don't care which principles you are following and which you aren't, but there are concrete disadvantages to breaking certain rules.
In this case I think you are writing procedural code rather than object oriented code. If you don't know, a procedure is a sequence of commands that alter the state of their environment. A function on the other hand receives an input and returns a result but doesn't change anything. The idea of object orientation is to have something in between. A class method may change the object it belongs to but it shouldn't affect anything else. Having a class affect the data of another class directly is what you call "breaking encapsulation".
Now when I hear a class name like "...Manager" or a phrase like "it manages ..." then my alarm bells ring, because it more often than not means that the code isn't structured like several objects that interact with each other (like a soccer game where the players interact) but more like a "person" sitting on top of a bunch of inanimate objects doing their work (like a chess game where the pieces are moved by players that aren't part of the game).

The disadvantages of code like that are:
1. Lack of encapsulation often leads to dependencies. If your "players" are so "dumb" that they only function if there is a manager that tells them what to do then the players and the manager are tightly coupled and changes in either of them will probably necessitate changes in the other.
2. Classes with names like "...Manager", "...Controller" or "...Behavior" often lead to huge classes that break the single responsibility principle. For example there is a Unity tutorial that contains a "BoardManager" class. Quick - tell me three properties of a Board. Now tell me three properties of a BoardManager. Were you able to answer both questions equally well? Probably not. So names with an unnecessary appendix like "...Manager" lead to a less understandable class structure. The consequence of that is that when programmers don't know where to put some new functionality they might be able to tell whether it should be part of a Board or not, but more often than not there's no problem putting it into a BoardManager class, because while a Board is clearly not responsible for interactions between the figures on it the BoardManager may be, after all he manages all that's related to the board.

So to sum it up: long classes are fine as long as they only contain code that belongs to one single class. Come up with a class name like "...Manager" and you may just be trying to find a shortcut around proper object orientation.

by (1,114 points)

In fairness I was going to called it generator instead of manager =P
I'll change my approach and do some more research into OOP. Thanks for the info.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.