Search Unity

Am I going overkill with script entities?

Discussion in 'Scripting' started by GIBurrito, Jan 26, 2015.

  1. GIBurrito

    GIBurrito

    Joined:
    Jan 14, 2015
    Posts:
    9
    Background: (Skip this paragraph unless you're just bored)
    B.S. in Computer Science. Trained in OOP as much as universities do these days. Most of my real-world programming experience is in robotics, using ROS in C/C++, and industrial control/automation with LabVIEW. Generally all of the software systems are comprised of a few, larger constructs. I first heard about Entity/Component frameworks about a year ago and took a quick gander at Unity and some more basic frameworks I could combine with SDL/Allegro myself. TL;DR: I'm just getting started with ECS and am looking for a bit of a critique on my initial attempts.


    My current design:
    I'm working on a top-down 2D spaceshooter. One of the possible mechanics of the game is to land on planets and create research outposts to gain new abilities. Basic abilities include thrust forward, induce some drag, torque left, and torque right. This is accomplished, for a human player, via two script components: ShipMovement and BasicPlayerPiloting. ShipMovement accepts input on the two axis in the range of [-1, 1] and applies forces to the rigidbody based on the ship's characteristics. BasicPlayerPiloting takes input from the Input class (WASD/Joystick) and applies them to ShipMovement. The idea is that once I get to AI, I can create a BasicAIPiloting script to generate the axis inputs instead of player input. My current design includes further components for more advanced control.

    Two more scripts for automated torque control are AdvancedPiloting and AdvancedPlayerPiloting. AdvancedPiloting is responsible for accepting a heading enumeration, forward, backwards, left, and right relative to the velocity, and generating the torque control input for the ShipMovement component. AdvancedPlayerPiloting then accepts input in the form of IJKL and generates the appropriate enum value to apply to the AdvancedPiloting. Again, the plan is to then have AI script(s) that can generate values for the AdvancedPiloting component as my navigation control gets higher and higher level.

    This is all well and good. It works. I can create a navigable ship by attaching the ShipMovement component. I can make it a player controlled ship by attaching the BasicPlayerPiloting component. This feels much cleaner than my first attempt that involved a separate PlayerController entity that required being assigned a reference to the ship that required control; it matches the feel I have of ECS thus far. My former attempt would have required different variables to track the current state/level of piloting and then selectively execute different input conversions based on those states and availability; why not let Unity handle that via components for me?

    My concern is that as the game continues to grow I'll start running into script overload. What heuristic do you apply when balancing complexity of your components? When working in Unity do you always find breaking up into separate components as much as possible as the better choice? Perhaps the biggest question is if you had to inherit this project would it annoy the hell out of you or would you appreciate the design?
     
  2. User340

    User340

    Joined:
    Feb 28, 2007
    Posts:
    3,001
    What is "script overload"? I've never heard of this expression before.
    No. I've written games with 1 script before. It all depends on how large of a game you anticipate it becoming. Small/Casual game, one script is fine. AAA game with dozens of menus, players, enemies, and scenes then modularization is a must.
    Based on what you've described, no I would be very happy inheriting a project like yours. You divided your scripts up logically, and you care about your dependencies. Who wouldn't enjoy that?
     
  3. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Maximize reusability / minimize code written. This generally leads to tiny components.

    I have done that too, but it wasn't fine. I was inexperienced, and was working alone. It would have been better to have had someone with more insight help me to not go that route; I didn't need to live through it to see how poor of a choice it was. Advice would have been better than the inefficient use of time, managing those large scripts. If you write a game with one script, you don't get as much done as you should before you die.
     
    Last edited: Jan 27, 2015
  4. GIBurrito

    GIBurrito

    Joined:
    Jan 14, 2015
    Posts:
    9
    Script overload: More effort into managing scripts/components than the effort of separating the concerns. Completely subjective.
     
  5. GIBurrito

    GIBurrito

    Joined:
    Jan 14, 2015
    Posts:
    9
    So you would always/generally prefer 100x 10-20 line scripts over 10x 100-200 line scripts? I think my concern that was some of my scripts were getting unnecessarily small.
     
  6. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Not "as much as possible", but definitely as much as is appropriate to preserve the Single Responsibility Principle.

    Monolithic scripts or classes are generally considered a bad idea, and I'd recommend avoiding them like plague.

    The amount of code in a script isn't really an issue and shouldn't be a primary consideration. Many best practices do result in smaller code files as a side effect, but that's not their purpose.
     
    Kiwasi and TonyLi like this.
  7. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    That's more likely to come from monolithic/integrated-responsibility scripts than it is to come from separation of concerns. Adding some GetComponent<ScriptAddressingOtherResponsibility>() calls into your code is simple. Deciding that you really want the movement functionality you wrote into MonolithicPlayer.cs to be used in MovingWallSegment.cs and Enemy.cs... not so much.

    Edit: If you're separating concerns in a way that ends up costing you more time than it's saving you then I suggest that you're not separating them very effectively. You're likely either separating too much (one responsibility being broken up over multiple classes where it's not necessary), making classes too inter-dependent, or not separating data from functionality that operates on that data where appropriate.
     
    Last edited: Jan 27, 2015
    Jessy likes this.
  8. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Also, there's a fairly worthwhile discussion of exactly this topic in this recent thread, which I recommend giving a read.
     
    GIBurrito likes this.
  9. GIBurrito

    GIBurrito

    Joined:
    Jan 14, 2015
    Posts:
    9
    Thanks penguin, that thread is asking the exact questions I was going for without being able to phrase it the way I wanted.

    I know reusability is the driving force and definitely see the benefit of some of it after watching all of the tutorial videos but some of the extent gone to feels silly to me sometimes. Which is exactly what ezjm in the other thread is saying.
     
  10. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Yeah, it can be a bit of a balancing act. Exactly where the balance should sit comes with experience, and should typically be based on the shortest path to completion for your current project (with variation, design changes, maintenance, etc. all taken into consideration).

    On one hand, you obviously don't want to re-implement everything by hand every single time you want to use it. On the other hand, you obviously don't want to do this either.
     
  11. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Don't be afraid to use RequireComponent generously when you have dependencies. This makes controlling scripts easier. I tend to use RequireComponent on an abstract base class for flexibility.
     
  12. GIBurrito

    GIBurrito

    Joined:
    Jan 14, 2015
    Posts:
    9
    I've always loved that xkcd comic as it's been one of the hardest habits for me to break when I was in school.
     
  13. Cpt Chuckles

    Cpt Chuckles

    Joined:
    Dec 31, 2012
    Posts:
    86
    you're doing what i've been thinking about doing for a long time. i've just been too lazy to work on a game though, but if i were, i'd be going the component-based route the way you are right now. in fact, i got inspired by looking at how the AngryBots demo was coded. it looks like they handle movement exactly the way you're handling it: a script for creating inputs, and a script for doing movements based on the inputs generated by the former. they have made an input script for the player and different AI input scripts, and one motor script. it sounds like you've got this component-based design paradigm down pretty well. unlike most of the tutorials i've seen, which do a ton of complex things with monolithic scripts that i think are horrendous.