Search Unity

2 smaller scripts vs one large script

Discussion in 'General Discussion' started by SamohtVII, Jun 20, 2019.

  1. Billy4184

    Billy4184

    Joined:
    Jul 7, 2014
    Posts:
    6,025
    Sure, to some extent yes, but I provided some examples of how it is very difficult to separate them. It's hard to conceptualize something as one thing and portray it as another.

    Unless I'm missing something, statements like 'OOP is bad' are not referring to a matter of taste. So far there have been a number of them in this thread, and very little in the way of argument as to why this is the case.

    I'm not some kind of OOP fanatic, just like everyone else I'd love to be able to neatly abstract everything away into some mathematical formula that doesn't exist in any particular spatial dimension, and just have everything pop out at the right time. In fact it would probably work well with non-game stuff to some extent, as well as stuff that operates very consistently in games, but it would not aid in the ability to craft those parts of the experience of a game that need to be engineered just so.
     
  2. Almost every single time I try to write down the same frickin' statements when this comes up. Maybe I will just refer to google next time, it's a little bit stupid to go through this over and over. So I usually am trying to give some reason why I think that.
    But we are on a forum, obviously everyone is giving their own opinion, no one here holds the Sorcerer's stone in their pocket and no one is spitting pure gold. So none of us can tell the absolute truth about anything.
    And honestly, I'm not interested in people who try to do that. I'm laughing at them usually.

    So, I think OOP is bad (for serious game development). And I gave my reasons before (see abstraction -> virtual look-up tables, encapsulation -> data fragmentation, jumping around in the code with no good reason, cache misses left and right, unneeded memory read all the time, etc). You do with this information whatever you want. If you look into that, that's great, if you dismiss it, that's also okay. As I said, everyone's mileage vary. If OOP works for you and you don't have problems which cripple down your game, you don't develop for mobiles to burn through the battery, no problem.
    When you hang up on the first real bottleneck, you will research this whole "what's happening in the computer when I say X" when the time comes, until then don't fix what's working for you unless you're interested in other techniques.

    Also some people stick to the first technique they learn excessively because of the familiarity. (I'm not saying you're one of them, I have no idea)
    They learn something and they somehow feel if they get some practice in other ways, that somehow would mean that their first stuff they learned was a waste of time. But in reality, you're much better developer (both computer software and also game developer as well) if you know more techniques. You can employ more, you can solve more problems on more ways and ultimately you can create sometimes hopeless sometimes awesome mutant solutions to desecrate every known principle and maybe invent something new.
     
    Last edited by a moderator: Jun 26, 2019
    vakabaka, Billy4184 and angrypenguin like this.
  3. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    A bit of both? I kept experimenting with different things, and that's the one that has most consistently worked. To begin with the "many small components" thing was an effect rather than a cause, but it has definitely informed my "philosophy" going forward. It's also just one part of the overall way I do things. Just "make small components" on its own will not make your code better.

    On that, no technique I've tried is perfect. Every one of them has limits and shortfalls. I've struck on a combination that, so far, works really well for me and the teams I've worked in on the type of projects I typically do.

    One of the important parts of my overall approach is to not be married to any one particular tool or approach or methodology. As previously mentioned, be aware of many and use what is best in a given scenario. As a result, I think that most arguments that one tool is inherently "bad" and people should therefore use some other tool instead is fundamentally flawed, because we do not need to stick to one tool for all jobs! (I'm referring to the video a few posts back, not @Lurking-Ninja's thoughts on OO.) It's just folly to try to pick one tool / approach / method as being the best for all possible situations.

    There's a good reason that tradespeople carry both hammers and screwdrivers in their toolboxes. The same principle applies here! There are huge benefits to being flexible, knowing multiple tools and using the right one for the right job.

    I appreciate plenty of the points made in the video a few posts back, but it strikes me that the problems raised seemed (I skipped a chunk, so please correct me if I'm wrong) to arise from dogmatically applying OO ideals whether or not they were beneficial in a particular scenario. The proposed solution involved selectively applying a different technique. If the author was as willing to be selective about OO principles they may very well find that they didn't run into its limitations quite so often.

    Obviously you can't control how well other people use a particular tool, which also seemed to be a major point in that video - he often talked about problems he finds when looking at other peoples' code and trying to work with it. It did leave me wondering how often he's worked on large projects in teams applying his proposed solutions in order to find its own real-world limitations.
     
  4. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    So I can't address all the points against the video I linked "why oo is bad". But here's what I will say.

    I've been writing code for decades. I am more fluent in code than I am in natural language and I've written more code than I have written natural language. All in all, over the last few decades I've spent more time talking to computers than I have with people.

    I no longer follow more than the most fundamental OO concepts. I use some basic encapsulation, and try to organize code such that I can find stuff where I expect stuff to be.

    More procedural systems (like, for example, Unity's old GUI system) can also be a nightmare to work with, and having functions scattered between seemingly random namespaces sucks more than well organized OO. It's simply harder to find what you're looking for and harder to conceptualize when the namespacing of various functions are poorly organized.

    But this comparison isn't fair. Unity's old GUI system is ... less than ideal. A hodgepodge of stuff evolved and bandaged together over years and years of iteration.

    I've seen other more procedural systems that managed to evolve more cleanly, so I don't think that procedural code necessarily leads to code decay, but I'd believe it that more procedural code decays faster than OO code on the average.

    That said, I also believe that if we had spent the last twenty years as an industry building a set of best practices and tools to fend off bad procedural code the way we have for OO code, the industry as a whole would be in a better place and code in general would be easier to write, maintain and modify.

    Has anyone reflected on the sheer quantity of work done to bandage problems working with OO?
     
    GarBenjamin likes this.
  5. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    I've noticed people wildly disagree about what OOP means. For example I've seen, I think here on Forums, people claim that automatic getters/setters makes a class encapsulated, and thus OOP. These are the classes with "public age { get; set; };" for every variable. Whereas a traditional OOP coder sees those the same as all public vars - everything is fully exposed and advertised, the same as in 1980.
     
    angrypenguin likes this.
  6. Well, this is a half-truth. With setters, you have control at least, with public variables, you don't. But yes, blindly replace variables with getter/setters alone doesn't make anything proper.
     
  7. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    The problem with these forums is the skill levels of ppl are so crazy wide that it's very hard to discuss anything code related.
     
  8. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    We seem to have come to the same basic views of these things. I used to write about these things on here about the layers and layers added over the years to solve problems they created earlier... an ongoing thing. And also making the entire software development process more time consuming and expensive as a result. I also believe in the core principles and ditched all of the other stuff.

    On the general idea of OO vs a more procedural approach we can look at things and "see" objects and collections of those objects and the methods necessary to work with those objects bundled inside the objects. We can also look at the same things and "see" data, collections of data and processes (functions) necessary to work with that data bundled into managers.

    So I guess maybe that is really the deciding factor with how a person chooses to develop... just how a person prefers to view it all. And there is really no right or wrong but for me personally I think a lot of the OOP and "best practices" stuff has been taken to such extremes where... I will just say it doesn't surprise me to see many of us start to question it all.
     
  9. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    Doing one big script is a lot easier.

    Right up until someone else needs to read it.

    Small scripts take a little more time but are worth it in the long run.
     
  10. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Well... yeah, but like I've said a few times, I don't blame the tool for the problem. Whether it's a question of OO vs. some other paradigm, or Unity vs. some other engine, or using vs. ignoring access modifiers, or events vs polling, or one language vs. another, at some point a human made a decision about what tool to use.

    If they picked poorly then that doesn't make the tool "bad".

    - - -

    Similarly, a lot of talk on topics like this one seems to ignore the fact that projects and requirements and designs change. A decision that made perfect sense when it was made could well turn into a liability later, at no fault of either the tool or the people who made the decision. I certainly can't tell what will happen in the future, at best I can guess based on prior experience.

    Who has worked on a thing that started as a nicely designed, clean and simple piece of code, and then slowly turned into a monster as design changes were made one after the other over an extended period? No one change was worth scrapping the current implementation, but in hindsight the sum of the changes absolutely would have warranted that...

    At some point I had an attitude shift with my programming. Rather than just making stuff work as intended and then getting grumpy when the requirements change, I try to design my code in ways that support such changes. In one of my experiments on this I made a match 3 game where I could change almost any aspect of the game logic by writing a trivial drop-in replacement class and then swapping one Unity component with another. As a result I could, and did, make whole new game modes in less than half an hour, while being completely confident that it wouldn't interfere at all with existing functionality. If I'd taken the "simple" approach of just implementing the game logic in one class I very much doubt that either of those things would have been true. The up-front complexity would have been lower, and the code would have been less "fragmented", but the work arising from changes would have been larger and more error prone.
     
    Billy4184 likes this.
  11. Deleted User

    Deleted User

    Guest

    In general I've learned that when anything is controversial, there is not a solid black or white side to the issue...
     
  12. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    That's a neat example since it shows guessing vs. planning. You can imagine someone making the first ever line-matching game. A double array of ints for each color would be fine - that even leaves room for extras like -1=solid, and 100+=special item. If it was done OOP-style, which is often over-engineered, the ints would instead be a GridSpace class (holding a single int) with a bool isTappable() { return true; } function and so on.

    But now we know that spaces in line-matching games have gunk and webs to clear, or can hold roving monsters... , and are often not tappable. Now it's just common sense to make a class for each space, with a real "bool isTappable()" function. Our original coder now seems like a genius. Except OOP/over-engineering is about not knowing. That coder probably added support for things no line-matching game has ever wanted: multi-space pieces, multiple-stats (color and shape and size) and partial matches (colors match, but not shapes), a way to make 2+ move sequences before it reacts, non-adjacent moves... .

    On one end you've got test-driven-development, which says you can never plan ahead for something you haven't committed to adding now. Past that is adding support for things you'll probably add in version 2 if version 1 sells well enough. More so is guessing what you may want to add. Then at the other end is the extreme OOP style that says to make everything an Interface and class and message without even thinking about whether you'll need it for later.
     
    SunnySunshine and angrypenguin like this.
  13. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    That experiment grew from the experience of working for clients or managers, where often the start of a project was really simple and the end was a pain, for reasons already captured perfectly by The Oatmeal.

    I spent some time experimenting with various ways to minimise the risk posed by late-project changes. In doing this I was happy to slow things down at the start a bit, because that's where we have good visibility to deal with things - we know what our initial design is, and/or we know what our client or manager thinks they need. However, once the implementation meets real users we have no idea what will happen, and I had plenty of experential evidence that this is where stuff gets increasingly slower, trickier, and more error prone...

    I'm pretty pragmatic, and I'm all for taking the simplest approach. However, I want the simplest approach to the whole project, not just the bit at the start where we have good visibility.
     
  14. kburkhart84

    kburkhart84

    Joined:
    Apr 28, 2012
    Posts:
    910
    Add to this the fact that it doesn't take long for you yourself to not be the same person, in other words you yourself will soon enough not remember the code you wrote and it won't matter that its you instead of another person. Depending on the person this process could take weeks but some people depending on how much coding they are doing only take a couple days and they no longer remember code and require commenting and organization to cope.
     
  15. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    That seems like a decent explanation of the basics of OOP thinking: things which you strongly suspect will change can be made into classes and interfaces, which makes them easier to change. The longer the code will be in service, and the more types of places it will be used, the more you suspect things will need to be changed.

    But "client work" is difficult and squishy. We can cut that out (not really) if we say proper OOP is about making everything a class with an abstract interfaces. That's how you get these vastly overcomplicated programs which make people complain about OOP.

    One thing I've found is that you tend to get better at asking. I worked with a guy who emphasized the value of having a client agree to as much as possible. There would still be changes later, but fewer, since you considered a lot more things, and the client understood that asking for changes was non-trivial.
     
  16. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    Technically, 1 script vs. several means nothing.You have can the exact same code in a single script or split into several. But answers like this are probably assuming the scripts are being written in a very simple intro-to-unity way.

    Basic intro to Unity say to make a script for each type of gameObject. Your Ball script will probably have public setColor, public setMoveStatus and so on. Then the main script will have a link to it and call ball1.setColor(...). In OOP terms, you naturally get communicating objects. Meanwhile, using a single script in simple Unity fashion is more likely to do everything directly: "if(ready) { ball.GetComponent<Renderer>().material.color=new Color(1,0,1); ..." and so on, cut and pasted.

    It doesn't have to work that way. A single script could have a setBallColor function, or ever a nested Ball class. With several scripts, each could directly and messily change someone else's components. But if you learned from the Unity docs, that's not very natural.

    "Use several scripts" is probably saying to write a class for each major type of gameObject. And, sure, do that, and a mono behavior on it is a simple way.
     
  17. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044

    Grid{ public GridSpace GetGridSpace( x, y ); }

    This is already a problem because GridSpace isn't real encapsulation and you have extra classes. The worst of both worlds.

    Grid{ private int[][] _Spaces; public bool IsTappable( x, y ); }

    This gets you closer to actual encapsulation and avoids over engineering.

    A lot of the problem with "OO" is that people pick "single responsibilities" that are at too low a level of granularity, and they end up with too many classes. "Single responsibility" isn't a bad idea, but what constitutes a "responsibility" is subjective, and too often people err on the side of micro responsibilities.
     
    SunnySunshine likes this.
  18. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    This is why people make fun of OOP. We could use a double-array of a "stuff in this space" class just fine. But we just _have_ to make another class holding the array. Then we just _have_ to hide the actually useful class inside, which involves writing more do-nothing pass-through functions (things like: bool isTappable(x,y) { return G[x,y].isTappable(); } are called pass-throughs, since all they do is pass-through your request to the real function).
     
    Lurking-Ninja and SunnySunshine like this.
  19. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    If the pass through code is helpful, who cares? If the pass through code isn't helpful, why are you writing it? That's an example of dogmatically sticking to theoretical ideals rather than picking the right tool for the job.

    You talk as if classes are a problem in and of themselves. Why do you feel that's the case?

    I agree if you're talking about useless classes that don't do anything. But if we're talking about classes that genuinely serve some purpose (whether that purpose is functional or structural) who cares how many there are?

    This is definitely something useful to think about. A "responsibility" is not a "task", and it's quite possible to get the two mixed up.

    However, it's also contextual. As in my match 3 experiment, if I were aiming for the simplest implementation of a fixed design my responsibilities would have been very different to how I viewed them with my aim of maximising flexibility. I'm not going to dig up the code at the moment, but I vaguely remember the responsibilities being things like "spawning of new blocks" and "determine what blocks to move based on user input". Those are pretty fine grained responsibilities, because I wanted to be able to cleanly plug in replacement implementations of those responsibilities in the Unity Editor. If I'd been going for implementation of a fixed design I could have had far fewer classes, with broader responsibilities like "implement the game's rules".
     
    frosted likes this.
  20. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    In terms of the number of classes and the responsibilities, I think it's important to keep in mind that this should not be a fixed quantity. What we want to do is keep in mind our human limitation.

    40 classes are pretty easy to mentally keep track of.
    400 classes are not.

    The level of granularity we select should scale with the scope we need to manage.

    Imagine that we're approaching a match 3 game as a standalone project and compare it with a match 3 as a one off mini game in a larger project.

    "Spawning of new blocks" is probably a reasonable level of granularity when "which blocks you spawn" is a real consideration to the project, like in the case of a match 3 game as standalone. In the mini game example, you probably don't care as much, and the spawning of new blocks could probably be a couple lines of code in a function.

    In general though, I would probably err on the side of a simple rule:
    - If I can replace a class with a delegate, it should usually just be a delegate.
     
  21. Billy4184

    Billy4184

    Joined:
    Jul 7, 2014
    Posts:
    6,025
    I don't think it's a question of keeping everything in your head all at once, it's a question of being able to trace the right script quickly from the way the classes and files are organized.

    You could say the same thing about methods - if every class has 5 methods you already have 200 methods to keep track of. But you don't need to because the class provides an intermediate level of organization.

    I think the key is to provide levels of granularity that are at the right points that you don't need to keep a ton of information in your head at any particular one.
     
    angrypenguin likes this.
  22. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    As the scope increases - assuming you are responsible for the entire scope - you will need to switch between bits and subsystems fairly regularly. There's real fatigue needed in dealing with lots and lots of stuff, especially when that stuff treats granular details as important.

    Just to revisit the material example.

    Is "Selecting which blocks to spawn" an important detail, something that deserves its own infrastructure (in the form of interface or class hierarchy)?

    Some of the considerations:
    - How much code does it take? Is it a two liner, or 50 lines?
    - In practice, how often did it actually change? Did we have more than 2 implementations?
    - In practice, did separating it into its own responsibility add labor or remove labor?

    I would argue that if we had 2 or fewer implementations, we added labor by separating that into its own responsibility.

    I would further argue that if we intentionally wrote code that only added labor, we wrote bad code (and I think that this is a point where I really leave the majority of developers, as I don't think most take this into serious consideration w regards good/bad code).
     
  23. Billy4184

    Billy4184

    Joined:
    Jul 7, 2014
    Posts:
    6,025
    Well I pretty much agree about being suspicious of breaking classes into smaller ones, but that's not so much because of the number of classes per se and more about the fact that you need to come up with a clear identity for the new class. For me, there's a point where I start struggling to create an individual identity for a class that I can intuitively and immediately understand. Like, I know what its function is technically, but not really how to describe it to someone simply. I think that's (or maybe a bit before that point) where it becomes damaging to break classes up any further, because the mental path through the different levels of granularity gets faded and lost in the weeds.

    Another thing I've noticed lately, having used a lot of Unity Events in my space kit renovations, is that the kind of events that you use to communicate between two classes is also a sign of how healthy the split between them is. If the delegates are clear and simple and don't depend on a lot of different variables (or, similarly, pass one variable that contains too much information), then it's a sign they should be fused together.
     
  24. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    You can only know the answer to this in hindsight. There is no way to know at design time how much your design will change in the future.
    I agree with the bolded entirely. In fact, I'd be willing to call it "bad code" in plenty of cases even if it wasn't intentional. The value of our code is not in the code itself. The value of our code is in what can be done with it. This means that the optimal course of action is always the one that achieves the desired results with the minimum labor.

    Complication arises from a few areas.
    - We don't know what the future desired state will be.
    - There are often hidden aspects of the desired state. (For instance, we probably all want our stuff to be 'secure' as is relevant in its context, but we can't always be aware of all possible vulnerabilities.)
    - We don't always know what the minimum labor approach is, particularly when problem solving / research is involved.
    - Not all humans think or do things the same way, which is a valid consideration. The optimal answer may well change from person to person or team to team.
     
  25. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Assuming that all of those classes are in fact useful, why does it matter? Either way you've got the same amount of functionality you need to keep track of. It's about how well organised it is, not arbitrary numeric limits.

    Do keep in mind that I'm not suggesting classes are the only way to organise code. Yet another matter of "pick the best tool for the job".

    Furthermore, again assuming things are useful and well organised, once you look at any one of those classes I'd rather whatever is clearest and easiest to understand, regardless of size. If a particular problem is well represented with few classes then great, that's what I want, but by the same token if it's better represented as a larger number of smaller classes then that's what it should be.

    The same deal goes for whatever organisational unit you're using, whether it be OO or not.
     
  26. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    I agree 100% with all of these points.

    The biggest one being that we need to guess what the desired future state is. Worse than that even, we need to guess on what our likely path to the future state is.

    The truth is, software development is closer to risk management than engineering. We're usually dealing with some degree of unknown, and its not uncommon for us to be dealing with large degrees of unknown.

    The amount of unknown is exacerbated when learning is also required, as often, we need to build systems that we've never built before, dealing with tech or problems we've never worked with before.

    I don't think, necessarily that you can for example, look at some code and determine objectively if the code is good or bad on its own. And that our collective belief as developers, that you can objectively look at code and say "good" or "bad" is myopic at least.

    To be honest, that's I think the end of that line of discussion. If you want to keep discussing the subject, lets use some actual examples and look at different types of implementations.
     
  27. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    They do matter though. At the end of the day classes are named elements in a project that are functionally different from methods. The IDE enforces this, as does convention (files being 1-1 with classes, generally speaking).

    Realistically, classes are our primary organizational tool, not folders, methods, namespaces or anything else.

    400 names is hard to remember and difficult to navigate through.
    40 names is very manageable for anyone.

    At a certain point, you even start to simply run out of common english words to use in naming. You start to need to build more and more compound names in order to differentiate. Eventually hitting points where you need to use 3-4 word compound names in order to differentiate different elements.

    This is as arbitrary as the fact that most people can remember 3 numbers, but have difficulty remembering 9. In general, people's brains start to hit limits, and keeping track of hundreds of things is much harder than keeping track of dozens.
     
  28. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    C# lets you nest classes inside of other classes and namespaces. All of the old advice applies fine: if one class uses 4 others, nest them inside of it. If you need 6 classes to handle one sub-system, put them all in the same namespace. A Unity drawback is that you can't do that with monobehaviors.

    Namespaces in C# are clunky, since you think "namespace" but have to use a static class. And the using's and includes are awkward, but the new "using static" probably helps. Basically, use C++ for a while to see how things should work, then you can fake that pretty well in C#. An example of nested classes: it's common to have many classes named Node, inside whatever class uses them. PlanetGraph.Node, Inventions.Node and so on. You'll even see examples with an enginePart class as a "bad" example. It's inside the Engine class, so just name it Part.
     
  29. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,203
    The following code is completely valid for me (Unity 2019.1). Is there something I'm missing? Are you referring to having the MonoBehaviour nested and not being able to attach them to GameObjects through the editor?
    Code (csharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace Test
    6. {
    7.     public class Foo : MonoBehaviour
    8.     {
    9.         private void Start()
    10.         {
    11.             Debug.Log("Foo!");
    12.         }
    13.     }
    14. }
    Because you can add them through code.
    Code (csharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace Test
    6. {
    7.     public class Foo : MonoBehaviour
    8.     {
    9.         private class Bar : MonoBehaviour
    10.         {
    11.             void Start()
    12.             {
    13.                 Debug.Log("Bar!");
    14.             }
    15.         }
    16.  
    17.         void Start()
    18.         {
    19.             Debug.Log("Foo!");
    20.  
    21.             gameObject.AddComponent<Bar>();
    22.         }
    23.     }
    24. }
    It just looks a little odd in the Inspector.

    upload_2019-7-1_22-52-29.png

    upload_2019-7-1_22-53-34.png
     
    Last edited: Jul 2, 2019
    frosted, bobisgod234 and angrypenguin like this.
  30. warrencwwong

    warrencwwong

    Joined:
    Aug 17, 2018
    Posts:
    25
    I prefer two smaller scripts, mainly because of easier scrolling.
     
  31. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    Yes, that's all. To be clear with a real example, say we want our edges and nodes to be inside the graph class, but also be on the prefabs:

    Code (CSharp):
    1. // arrg! we can't add Node or Edge scripts through the editor
    2. public class InventGraph : MonoBehaviour {
    3.   public class Node : MonoBehaviour { ... }
    4.   public class Edge : MonoBehaviour { ... }
    5.   ...
    6. }
    Maybe in the future we could go to AddComponent->Script and search for InventGraph.Node, which would solve even this small problem (I thought that might be possible now, but turns out not).
     
  32. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,203
    Just came up with a workaround using MenuItem thanks to an idea from a downvoted post on Stack Overflow. Anything that is in the Component root menu shows up in the Add Component dialog. With a little work I bet I could find a way to achieve it with an editor script.

    Code (csharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5.  
    6. namespace Test
    7. {
    8.     public class Foo : MonoBehaviour
    9.     {
    10.         public class Bar : MonoBehaviour
    11.         {
    12.             void Start()
    13.             {
    14.                 Debug.Log("Bar!");
    15.             }
    16.  
    17.             [MenuItem("Component/Nested/Bar")]
    18.             public static void AddMe()
    19.             {
    20.                 Selection.activeGameObject.AddComponent<Bar>();
    21.             }
    22.         }
    23.  
    24.         void Start()
    25.         {
    26.             Debug.Log("Foo!");
    27.  
    28.             gameObject.AddComponent<Bar>();
    29.         }
    30.     }
    31. }
    upload_2019-7-2_14-32-34.png
     
    Last edited: Jul 2, 2019
    frosted likes this.
  33. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    That's such a filthy dirty hack.... I kinda wanna try it. :D

    I also didn't know you could addcomponent on a nested class like in your first post - is that a new feature, or just black magic?
     
  34. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,203
    To be honest I have no idea. Yesterday was the first time I tried nested MonoBehaviours. :p
     
    frosted likes this.
  35. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    Hmmm...that [MenuItem} trick works -- you can add a nested Monobehaviour class through the editor. Testing: it appears in the Inspector along with public variables; and they stick when you leave and come back. I haven't checked when you close and reopen.

    BUT, the script name and the Enabled checkbox are greyed-out. In 99% of cases this won't matter, but it looks scary, like something is going to break later. But a class is a class. And I've written scripts where the MonoB came first, followed by non-nested classes after it. No problems there. The rule is only so dragging knows your intentions, after all.
     
    Ryiah likes this.
  36. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    I have in the past been able to add a component to something and then make some change that invalidated it (from memory, changing the class name without the filename or vice versa) and everything was fine until I restarted the Editor.
     
    Ryiah likes this.
  37. MrArcher

    MrArcher

    Joined:
    Feb 27, 2014
    Posts:
    106
    Actually the presence of the tick box is due to the monobehaviour functions in the class - there's a list here. Here's an example of a child monobehaviour having it:



    Logging for the above classes showed the monobehaviour functions running as normal. I'd imagine there'd be significantly more overhead to doing this than writing them as pure classes, but hey, a tool for every job.

    EDIT: Just restarted the editor and the child class has bugged out. Ignore what I just said :p
     
  38. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    This is a bit of pain for refactoring. We have hundreds of in game items, a refactor could potentially invalid all of those prefabs.
     
  39. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    As long as you change the class and the file name (via the Editor) at once it still works. I didn't know that until recently, though, and certainly wouldn't try it without having recently committed my work.
     
  40. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    If I remember correctly there is also a problem with changing namespace names
     
  41. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    Huh. I just tried that and mine was fine. A nested monoB with only "public int y;", used the Component Menu [MenuItem] trick to attach it to a gameObject, changed y to 27, quit Unity, restarted, and it was still there with y=27.

    I was also partly wrong about the missing enabled checkbox. The second line, with the script name, is greyed out, but it's always greyed out for every script. But for a nested MonoB the script name is missing. Unity also sometimes gives a non-error error: "The script cannot be checked because it does not exist", which I assume keys off of that missing script name.

    I don't think the renaming thing is an issue for nesting. Unity can bug out saved Inspector values when you rename any script. And, I've never done this, but can't you just grab copies of the meta-files and fix the names there?