Author Topic: Shrugger! Unity!  (Read 163356 times)

Offline x4000

  • Chris McElligott Park, Arcen Founder and Lead Dev
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 31,651
Re: Shrugger! Unity!
« Reply #15 on: August 05, 2013, 10:03:33 am »
Regarding OOP, the general process is this:

1. Set up a separate file, with a class definition in it.  Put various properties and methods on that class.
2. Instantiate that class as an object as much as you need to, in order to store your data.

From a 10,000 foot overview, that is all OOP is.  You define classes with methods and properties that are well-organized and which make sense to a human reading them, and then you make 0-n objects out of those classes. 

These are not scripts or attached to your existing GameObjects unless you want them to be.  Though you need some way of indexing all of this non-script data.  You can either do that with the Singleton design pattern (you can google that) or a class with static properties that provide those ongoing references.  Or you can put the ongoing references on your camera or some other always-exists GameObject in your unity game.  But I personally prefer using a Singleton class.

In terms of the specifics of OOP, there are obviously more things than just the 2 above, but those are the basic outline of everything else you could do.  For instance, other things you might do:

A. Set up sub-classes of higher-order classes.  Either an abstract parent class (google "abstract classes" in C#), or a regular parent class that has some virtual methods, or just a regular parent class.  Books on basic OOP make a big deal out of the ability to do these sorts of things, and it is powerful, but they carry it to an extreme degree in their examples, frequently.  Most of the actual libraries in actual commercial software (the .NET libraries themselves) don't have too extreme of inheritance going on.

B. You can set up various metadata classes that contain information about all the types of objects of X.  Think of this like an encylopedia: each instance of the BlockObjectTypeData class might have all the properties associated with a BlockObjectType enum value, and then you have a BlockObject class whose instances are the actual working data about your current scene.  But rather than duplicating all that info from BlockObjectTypeData, which can be substantial, they just reference it instead.  Way more efficient on RAM, and initialization time.

Among many other things you can do, but honestly it's easy to over-engineer OOP apps just as much as any other kind of app.  Following the KISS principle is generally best.  But I can't recommend learning about Design Patterns any more highly, as that often has loads of great architectural ideas.
Have ideas or bug reports for one of our games?  Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,251
Re: Shrugger! Unity!
« Reply #16 on: August 05, 2013, 10:52:53 am »
One of the patterns I want to get into using is the decorator pattern.  Just because it's so damn useful (from a completely non-code perspective).

Problem is I have no idea how to go about doing it.  Closest I've come is Minecraft's block/item code which looks like a decorator pattern, but it actually isn't.

Eg. you can do new BlockType(1, Material.STONE).setResistance(10.0F).setUnlocalizedName("MyBlock").setHardness(2.0F);
Which is how to create objects with properties in the decorator pattern.

Internally, for Minecraft, all this does is this:
Block b = new BlockType(1, Material.STONE);
b.resistance = 10.0F;
b.unlocalizedname = "MyBlock";
b.hardness = 2.0F;

(or putting those function calls in the constructor, etc. etc.)
Those properties are technically protected, but functionally it's the same thing.  The fact that those setter functions return the block itself isn't actually relevant.  Block classes are treated as singletons, but they aren't forced to be singletons (i.e. you can instantiate a second copy if you want to for whatever reason--comes up a few times, like glowstone lamps, which are instantiated with a different light value and different block ID, even though it could have been done with metadata).

Unlike the decorator pattern which actually takes an object passed in, adds methods and properties (so it becomes a more or less unique class), and returns the resulting object.

As an example using AI War, you could have a base Ship class and decorate it with the Repairer class.  Now it's an engineer.
Take the same Ship, decorate it with a Weapon class, now you've got a basic fighter.
Take the Ship class and decorate it with Regenerator (implies ImmuneToRepair) and Melee.  Now it's a Vorticular Cutlass.

Now you only need classes for the various functionality rather than unique classes for each ship type (or a bloated base class that has options for everything; ie. isRegenerator, isMelee, isRadarDampening, etc).

This lets us do cool things like:

Ship s = new Ship().Regenerator().Repairer().Teleporter();

For an entirely different kind of engineer without having to write any new code.
« Last Edit: August 05, 2013, 10:59:58 am by Draco18s »

Offline Shrugging Khan

  • Hero Member Mark III
  • *****
  • Posts: 1,217
  • Neinzul Y PzKpfw Tiger!
Re: Shrugger! Unity!
« Reply #17 on: August 05, 2013, 03:06:58 pm »
Interesting enough, that stuff. I can see rather plainly that there's a lot of work, both in theoretical learning and in trial-and-error ahead of me. Thanks for the explanations; I'll report back as soon as I've some successes or new failures to tell of  :D
The beatings shall continue
until morale improves!

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,251
Re: Shrugger! Unity!
« Reply #18 on: August 05, 2013, 04:00:53 pm »
both in theoretical learning and in trial-and-error ahead of me

One never stops learning. ;)

Offline x4000

  • Chris McElligott Park, Arcen Founder and Lead Dev
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 31,651
Re: Shrugger! Unity!
« Reply #19 on: August 05, 2013, 04:17:55 pm »
We do the equivalent of the decorater pattern via flags and other properties on our centralized typedata classes.  It would let us build customized cross-class ships if we felt like it, but instead we use that to make our actual new ship classes in expansions and so forth.  Similarly something like AddTeleporter() would be fine if you wanted to group a set of values sets into one call.
Have ideas or bug reports for one of our games?  Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,251
Re: Shrugger! Unity!
« Reply #20 on: August 06, 2013, 09:21:49 am »
We do the equivalent of the decorater pattern via flags and other properties on our centralized typedata classes.  It would let us build customized cross-class ships if we felt like it, but instead we use that to make our actual new ship classes in expansions and so forth.  Similarly something like AddTeleporter() would be fine if you wanted to group a set of values sets into one call.

Similar to Minecraft, yeah.

Offline Shrugging Khan

  • Hero Member Mark III
  • *****
  • Posts: 1,217
  • Neinzul Y PzKpfw Tiger!
Re: Shrugger! Unity!
« Reply #21 on: August 07, 2013, 03:18:44 pm »
So I've been merrily working on, making little cubic and spherical and cylindrical things chase and eat each other. Fun times!

Now that that particular bit of natural selection is working, I've been trying to get onto the whole OOP train as you two suggested, and I've hit the first major roadblock.

WTF am I supposed to start with?
I don't even understand what kind of file to create and work with. I've got a light grasp of OOP with Java, but that doesn't translate too easily into Unity.

So, really, just a simple question: What kind of file(s) do I create in order to start experimenting?
The beatings shall continue
until morale improves!

Offline x4000

  • Chris McElligott Park, Arcen Founder and Lead Dev
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 31,651
Re: Shrugger! Unity!
« Reply #22 on: August 07, 2013, 03:45:50 pm »
In Javascript or C#?

In JS I have no idea.  In C#, you will be creating some .cs files.  Those will be class files automatically if they are not scripts attached to gameobjects.
Have ideas or bug reports for one of our games?  Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,251
Re: Shrugger! Unity!
« Reply #23 on: August 07, 2013, 03:54:03 pm »
You can do the same thing in JS.  Just be aware that unless it is a class that somehow inherits MonoBehaviour, you won't be able to attach the script to an object at all.

Which for most things is fine, you just have to be aware of it.

Offline Shrugging Khan

  • Hero Member Mark III
  • *****
  • Posts: 1,217
  • Neinzul Y PzKpfw Tiger!
Re: Shrugger! Unity!
« Reply #24 on: August 07, 2013, 05:08:24 pm »
I've been using nothing but c# ever since you argued so strongly in favour of it ;)

So I just use those .cs files and those are equivalent to a class?
The beatings shall continue
until morale improves!

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,251
Re: Shrugger! Unity!
« Reply #25 on: August 07, 2013, 05:10:17 pm »
Yep!

Offline Shrugging Khan

  • Hero Member Mark III
  • *****
  • Posts: 1,217
  • Neinzul Y PzKpfw Tiger!
Re: Shrugger! Unity!
« Reply #26 on: August 28, 2013, 03:35:25 am »
Awwwright!

So I spent almost all my free time (read: non-social, non-play time) tinkering around, and I do think I've learned a lot. A bit too late for an OOP-centred exam that I will almost certainly have to repeat, but absolutely in time for Unity!

Now, next question.

Are there any rules (of thumb), guidelines, formulas, tests or general considerations regarding HOW I organise my objects and information? As in, when do I fill Objects with countless attributes and methods, and when would I better keep those within separate sub-objects and attach them to whatever Object has need of them? When is it smarter to store information in individual objects, and when is it smarter to store it in a single super-object? Is it generally best to minimise the number of layers of objects and sub-objects, or does it not usually matter how deep that rabbit hole goes?

And so on, and so on...any help is dearly appreciated, of course.  :)
The beatings shall continue
until morale improves!

Offline x4000

  • Chris McElligott Park, Arcen Founder and Lead Dev
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 31,651
Re: Shrugger! Unity!
« Reply #27 on: August 28, 2013, 06:59:03 am »
That's more of a taste/design question than a technical one, so grains of salt with my answer. But my approach is basically:

1. If it is all once conceptual thing (a "game entity" for instance) it has a single class with all of its mutable data on it.
2. If it is conceptually different ("background tiles" for instance) I don't try to mash those in to the former.
3. If it is a common property shared between all objects of a sub type, then I have a single instance of a "typedata" class type that is paired with an enum value (so one instance of game entity typedata for each game entity type).
4. Worker methods that talk about many of the object type at once (find a game entity, alter many at once, etc) go on some larger central classes (for instance a Game or World class).

This leads to large class files, which is why not everyone will agree. But it also leads to less confusion about where things are, and shorter intellisense calls. Dog.collarbuckle rather than pet.dog.collar.buckle or what have you.

Those are my opinions, but I do not feel anyone who disagrees is "wrong" in any sense. It all boils down to what most matches your mode of thinking. As long as it is clearly and consistently organized (ie you have some simple rules and follow them consistently), you're good to go.
Have ideas or bug reports for one of our games?  Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,251
Re: Shrugger! Unity!
« Reply #28 on: August 28, 2013, 09:53:14 am »
Are there any rules (of thumb), guidelines, formulas, tests or general considerations regarding HOW I organise my objects and information? As in, when do I fill Objects with countless attributes and methods, and when would I better keep those within separate sub-objects and attach them to whatever Object has need of them? When is it smarter to store information in individual objects, and when is it smarter to store it in a single super-object? Is it generally best to minimise the number of layers of objects and sub-objects, or does it not usually matter how deep that rabbit hole goes?

I'm going to have a slightly different approach than X here, but largely speaking the two of us think alike.  I've gotten tons of helpful code and theory from him and Keith.

Anyway.

1) Avoid God Objects.  A "god object" is a single class or instance that Know Everything.
2) Avoid public properties where possible, only expose what needs to be exposed.
3) Likewise don't cross reference if you can avoid it.  The main game class will know about the Player and the Dungeon, both of which will know about the main class, but the Dungeon shouldn't know about the Player and vice versa.  (Possibly bad example, but its the best I can come up with on short notice).  Inevitably you'll find exceptions even when you were certain that A shouldn't need to know anything about B.*
4) Class inheritance!  Extends!  Implements!  Glorious features.  public class Player extends GameObject implements IMovable {}
(GameObject here being a generic class, not Unity's GameObject class, which is static and can't be extended)

As a generic suggestion, go get Minecraft Forge source (and Eclipse to run it), poke around with Minecraft's internal structure a bit.  Get a feel for how the code is organized.  Its by no means perfect, but having spent several months modding I picked up a few habits that I rather like, just due to the organizational benefit.  I also fell in love with Eclipse, though I haven't had the time to set it up as a generic IDE for Unity or Flash (the version of MonoDevelop for Windows that ships with Unity is garbage).  It's Refactoring tools are lovably amazing.  Want to rename a class?  Right click, refactor -> rename, bam.  Anywhere it's been used in your entire project now use the new name.  I would love to have that power for the Flash game I'm working on.  I'd like to rename RewardItem to ItemReward, just so that when I try to type a var as RewardItem I don't have to scroll down through Reward00 through Reward50 to get to it (or typing out "RewardI").


*My dungeon floor objects should never need to know anything about the player, after all, this is just the walkable map and some other objects!
* Draco18s implements shadows
Code: [Select]
public function onEnter() { //run when the player first enters the floor.
if(main.currentMapID <= 10) {  //no shadows below floor 10
shadows.visible = false;
}
else if(main.currentMapID < 40) {  //deepending shadows until 40, 40+ full dark
a = (main.currentMapID - 11) / 30;
shadows.alpha = a;
}
* Draco18s implements the torch so that the player can see in deep shadows
Crap.  Floor needs to know about the player now....
Code: [Select]
//shadows less dark if the player has the torch
if(shadows.visible && main.player.flags.hasTorch) {  //hackney reference to the player
shadows.alpha /= 3;
}
« Last Edit: August 28, 2013, 09:59:22 am by Draco18s »

Offline Shrugging Khan

  • Hero Member Mark III
  • *****
  • Posts: 1,217
  • Neinzul Y PzKpfw Tiger!
Re: Shrugger! Unity!
« Reply #29 on: September 06, 2013, 05:35:48 am »
Alright, so at the moment I have one StartScript that spawns GameObjects and attacheds various scripts to them, a ListsScript that contains a number of Lists pointing to all the spawned GameObjects and their sub-scripts, with different lists for different script types.

This has ended me up with glorious lines like
Code: [Select]
this.gameObject.GetComponent<ObjectScript>().mainSYS.GetComponent<ListsScript>().objectList.Remove(thisObject.gameObject.GetComponent<ObjectScript>);A bit hard to read, I must say.

How bad or normal is this?
I've begun to add direct pointers to scripts, lists and objects in the scripts to simplify things, but I'm not sure how stylistically sound or technically efficient this is.
The beatings shall continue
until morale improves!