Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Lork
Oct 15, 2007
Sticks to clorf

blastron posted:

Glad you figured that out! Learning all the little buttons you need to click is probably the hardest part about Blueprint.
Thanks. And yeah, a lot of this stuff is not really conducive to being puzzled out the way you can kinda get away with doing in a written programming language - you're best off being told about it. In this case it was the list/array thing that screwed me, since I wasted my time trying to investigate lists instead of looking into the documentation on arrays. For whatever reason I had it in my mind that an array is supposed to have a predetermined size, but I guess that's specific to certain programming languages and each one does it differently.

Adbot
ADBOT LOVES YOU

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

Lork posted:

Thanks. And yeah, a lot of this stuff is not really conducive to being puzzled out the way you can kinda get away with doing in a written programming language - you're best off being told about it. In this case it was the list/array thing that screwed me, since I wasted my time trying to investigate lists instead of looking into the documentation on arrays. For whatever reason I had it in my mind that an array is supposed to have a predetermined size, but I guess that's specific to certain programming languages and each one does it differently.

Lol arrays aren't even arrays in all programming languages.

Phigs
Jan 23, 2019

Yeah, arrays are arrays are arrays: they do always have fixed length. What a programming language actually gives you when you ask for an array differs. Or differs depending on how you ask for an array.

Catgirl Al Capone
Dec 15, 2007

Phigs posted:

Yeah, arrays are arrays are arrays: they do always have fixed length. What a programming language actually gives you when you ask for an array differs. Or differs depending on how you ask for an array.

yeah under the hood anything that is or wraps an array is fixed length, sometimes languages or libraries just abstract and hide the process of reallocating a new larger one and copying everything over and call that "dynamic length".

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

Catgirl Al Capone posted:

yeah under the hood anything that is or wraps an array is fixed length, sometimes languages or libraries just abstract and hide the process of reallocating a new larger one and copying everything over and call that "dynamic length".

And then there's php

KillHour
Oct 28, 2007


Catgirl Al Capone posted:

yeah under the hood anything that is or wraps an array is fixed length, sometimes languages or libraries just abstract and hide the process of reallocating a new larger one and copying everything over and call that "dynamic length".

An array in JavaScript has an ambiguous implementation as defined by ECMAScript, but V8 dynamically chooses a fixed-length array or a hash-table dictionary depending the size. I think a lot of high level languages do the same thing.

Edit: https://github.com/nodejs/node/blob/49342fe6f2ca6cedd5219d835a0a810e6f03cdd7/deps/v8/src/objects/js-array.h#L120

KillHour fucked around with this message at 19:44 on Sep 9, 2022

BabelFish
Jul 20, 2013

Fallen Rib

Lork posted:

Active objects. An array wouldn't cut it because I need to add to the list at runtime, but even so, how would I go about making it anyways? When I try to make an array in the variables menu the only options seem to be various predefined types, none of which include blueprint classes.

Edit: Never mind, I figured it out. Instead of explicitly making an array variable, I was actually supposed to make a variable of the type I wanted, then right click the little colored dot next to it to turn it into an array of that type. Also apparently you can add to Blueprint arrays at any time, so that's solved as well.

Yeah, Unreal's wrapper on arrays, TArray offer a bunch of useful functionality, including dynamic resizing.

KillHour posted:

An array in JavaScript has an ambiguous implementation as defined by ECMAScript, but V8 dynamically chooses a fixed-length array or a hash-table dictionary depending the size. I think a lot of high level languages do the same thing.

Edit: https://github.com/nodejs/node/blob/49342fe6f2ca6cedd5219d835a0a810e6f03cdd7/deps/v8/src/objects/js-array.h#L120

Every time someone brings up old arrays in JavaScript, it reminds me of this talk.

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
The next time you worry about the implementations of your game mechanic, remember that none of your users will care as long as the art is good enough:

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

KillHour posted:

An array in JavaScript has an ambiguous implementation as defined by ECMAScript, but V8 dynamically chooses a fixed-length array or a hash-table dictionary depending the size. I think a lot of high level languages do the same thing.

Edit: https://github.com/nodejs/node/blob/49342fe6f2ca6cedd5219d835a0a810e6f03cdd7/deps/v8/src/objects/js-array.h#L120

lol the initial design rationale for javascript was "dude, i have to ship a language in two weeks, what's the literal minimum i can do to develop a programming language in two weeks?" This is why numbers are doubles and all functions are variadic.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Is Noesis still the way to go for a WPF-like, XAML-based GUI framework in Unity? I'm coming back to my project after a long break working on external parts. After up upgrade, everything with it is broken. It's running constructors when loading that previously were only run in game mode, and the new API to initialize it just crashes Unity. It was fickle even when I was first working with it. So I'm weighing how much I want to try to blast through that.

Regarding Godot, languages, and consoles, I think somebody found my goofy embeddable, asynchronous C#-based Python interpreter project and is trying to cram it into their Godot project. I use the REPL for that in Unity as my console and have a bunch of scripts running through it, but I consider anybody else trying to use it for anything to be crazier and stupider than me.

Analytic Engine
May 18, 2009

not the analytical engine
https://www.popsci.com/technology/moma-video-game-design-exhibit/



new MOMA show just dropped everybody and videogames could finally be art! It's still too early to tell but the East Coast critics are cautiously contemplating

Xerophyte
Mar 17, 2008

This space intentionally left blank

Analytic Engine posted:

https://www.popsci.com/technology/moma-video-game-design-exhibit/



new MOMA show just dropped everybody and videogames could finally be art! It's still too early to tell but the East Coast critics are cautiously contemplating

If MoMA is your arbiter of choice then video games were art at least 11 years ago.

KillHour
Oct 28, 2007


Sometimes I come across a video that is incredibly concise and useful for basically everything and this is one of them:

https://www.youtube.com/watch?v=YJB1QnEmlTs

The framerate independent lerp at the end blew my mind.

lord funk
Feb 16, 2004

KillHour posted:

The framerate independent lerp at the end blew my mind.

Yeah that was cool.

On a mega-project I've since shelved, I built my own UI in Metal from scratch. A big ++ was designing my own 'ramping' system, where any float value could be ramped using my own interpolation functions. It solved the problem of designing a UI where you want to make a nice animation, but your object didn't have the ability. Separating out the interpolation made it trivial to drop in animations all over.

Doing it in Swift made it really easy, as I'd just pass the interpolating function itself in as a parameter. It also make it really easy to add more kinds, like bouncing, or hopping, etc..

TooMuchAbstraction
Oct 14, 2012

I spent four years making
Waves of Steel
Hell yes I'm going to turn my avatar into an ad for it.
Fun Shoe
Related to lerps, two things:

First, this site has a collection of different easing functions, including the math behind them. Handy to know about.

Second, if you're in Unity, you can use AnimationCurve to make your own easing functions. Just draw whatever curve you want using the spline editor, then use AnimationCurve.Evaluate(t) to get your lerping parameter.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
A thing that's a mathematical pain to get right is when you want an easing by acceleration rather than duration, so like if you have four buttons flying in from the left and settling in a diagonal line, you don't want them to come in all already in a line (that looks poo poo) and you don't want an eased duration so the ones that go further go faster and they all stop at the same instant (not quite as poo poo but still poo poo), you really want a maximum acceleration (and maybe an initial velocity) so they come to a stop in the right place in a dynamic way and the motions all look natural.

You can do that on a frame-by-frame basis fairly easily but it tends to mean you have to do a "fix the slop" bit at the end. You can do the math properly which is a bit of work. Where it gets *really* worky is when you want things to fly into place on two axes - you can't do the axes independently because if the direction is at 30 degrees, doing independent axes makes it fly in a stupid-looking curve plus straight line at the end.

This is still not too bad really, but now consider the case where you want to change where the thing goes and you might do it while it's in motion - now if you do a standard lerp there'll be a "jerk" at the moment when you transition from line A to line B. To get a really clean result for that you want the inputs to the function to be starting velocity (2D), starting position, ending velocity, ending position, maximum acceleration.

My end result of this train of thought is some bonkers fuckery where the function's output is three curves each with a duration - the first curve is the shortest path that gets you so your velocity is parallel to your direction to your destination, then a curve that gets you to the speed and distance at which you have to start slowing, then a curve to the stopping point.

Tunicate
May 15, 2012

For the first two cases, why not just spawn them offscreen at the same distance from their ending points, give them all the same motion path, and just stagger when they start moving?

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Tunicate posted:

For the first two cases, why not just spawn them offscreen at the same distance from their ending points, give them all the same motion path, and just stagger when they start moving?
If it's always the same then yeah, you can manually tune it like that. But if the destinations are dynamically positioned (like the number of buttons depends on how many controllers are attached or something), or even if you just might want to change the layout a few times during development, then you're better off if you just mathed it properly in the first place.

Tunicate
May 15, 2012

roomforthetuna posted:

If it's always the same then yeah, you can manually tune it like that. But if the destinations are dynamically positioned (like the number of buttons depends on how many controllers are attached or something), or even if you just might want to change the layout a few times during development, then you're better off if you just mathed it properly in the first place.

Nah, i mean have the object start at ending_position.x-screenwidth, or something like that. Dynamic positioning if you change the design and move the ending position, but ultimately a fixed motion.

FuzzySlippers
Feb 6, 2009

I've been trying to figure out a smart way to do data templating in human editable files but I stumbled across jsonnet (unrelated to json.net which I already use lol). It does what I want which is
code:
{
  person1: {
    name: "Alice",
    thing: 1,
    thing2: "a",
  },
  person2: self.person1 { name: "Bob" },
}
becomes
code:
{
  "person1": {
    "name": "Alice",
    "thing": 1,
    "thing2": "a"
  },
  "person2": {
    "name": "Bob",
    "thing": 1,
    "thing2": "a"
  }
}
but jsonnet is way heavier weight than I need (I'd rather not have to run an app on a file to produce the end result json). This feels like a pretty standard problem, but I can't find anything probably because I'm using stupid language to describe it to google. Data templating? Data inheritance? Any pointers?

I know some really stupid manual ways to do it (some field that indicates the parent and then manually copy/replace the data) but I feel like there is probably a smart generic solution.

FuzzySlippers fucked around with this message at 09:17 on Oct 8, 2022

Ranzear
Jul 25, 2013

Might not be perfectly applicable but you'll get the gist: Stop trying to make that stuff human editable and instead export it from a human interface. Can be a bit fiddly, but literally a spreadsheet exported to json (that then nobody is allowed to touch) is the dream. Gives you data validation and defaults and everything too.

Ben Nerevarine
Apr 14, 2006

FuzzySlippers posted:

I've been trying to figure out a smart way to do data templating in human editable files but I stumbled across jsonnet (unrelated to json.net which I already use lol). It does what I want which is
code:
{
  person1: {
    name: "Alice",
    thing: 1,
    thing2: "a",
  },
  person2: self.person1 { name: "Bob" },
}
becomes
code:
{
  "person1": {
    "name": "Alice",
    "thing": 1,
    "thing2": "a"
  },
  "person2": {
    "name": "Bob",
    "thing": 1,
    "thing2": "a"
  }
}
but jsonnet is way heavier weight than I need (I'd rather not have to run an app on a file to produce the end result json). This feels like a pretty standard problem, but I can't find anything probably because I'm using stupid language to describe it to google. Data templating? Data inheritance? Any pointers?

I know some really stupid manual ways to do it (some field that indicates the parent and then manually copy/replace the data) but I feel like there is probably a smart generic solution.

My go to for stuff like that is YAML. Concise, minimal syntax, and supported pretty much everywhere (and you can usually find libraries that transform it to and from json if you really need json)

TooMuchAbstraction
Oct 14, 2012

I spent four years making
Waves of Steel
Hell yes I'm going to turn my avatar into an ad for it.
Fun Shoe
I use a spreadsheet, then export that to CSV and convert it to JSON for parsing by the game (mostly because I couldn't find a C# CSV parser that I liked). If you want to "inherit" from another record, you can just tell the sheet that e.g. "L1=K1", paste that across the row, then hand-edit the records you want to be different.

Though, spreadsheets don't work great if you have more complicated data than "key: scalar value".

Bongo Bill
Jan 17, 2012

Unserious suggestion: Dhall

FuzzySlippers
Feb 6, 2009

Yeah spreadsheets don't work because I'm defining spells/abilities with very elaborate configurations. This isn't like this spell does 10 dmg and another does 15 but like elaborate targeting information, effects, differing effects if a spell is overcast, etc. Part of this configuration data is that they can have a list of components which can be any number of classes inheriting from the base which all have their own configuration data. This is a 5e d20 adaptation so the spells/abilities can be very complex.

Currently I'm doing this through Unity scriptableobjects and elaborate inspector scripting and it suuuucks especially when I need to make large changes and I just want plain json. With how elaborate each object can be there is a *lot* of data that similar objects use that would be copied many times over that would make the file harder to use but also be a major refactoring headache.

For a while I was trying to build a little mini app to edit these and have it export json but making it sufficiently complex to work with the elaborate component composition was turning into too much of a sideshow.

Dhall looks fine if there was a c# or js library :shrug: YAML doesn't do inheritance as far as I can tell, and I've always found it more of a headache than json for large lists of data.

edit: for those curious the project is taking this 4e-ish 7drl and turning it into 5e-ish. My 4e-ish implementation tended to simplify spells greatly but I'm trying to capture some of the proper complexity of pnp spells which can get quite nutty.

FuzzySlippers fucked around with this message at 23:45 on Oct 8, 2022

TooMuchAbstraction
Oct 14, 2012

I spent four years making
Waves of Steel
Hell yes I'm going to turn my avatar into an ad for it.
Fun Shoe
I agree with Ranzear then -- making an app to help you edit the data is the way to go. Like, you'll have a bunch of small serialization puzzles to figure out as you go, but it'll be easier than trying to write the data files directly. Plus, whatever format you create, you'll have to deserialize it and make sense of it anyway to play the game.

For reference, this is the "app" I use to edit missions in Waves of Steel:



It's the Unity editor. I wrote an immediate-mode GUI panel that provides some helpers:



but a lot of the "app" is me just sticking stuff under a special gameobject (the "mission root"), which serializes itself when I click the Save button in that panel.

12 rats tied together
Sep 7, 2006

yaml doesn't call it inheritance but it does what you want, i think. python example

Python code:
Python 3.10.4 (main, May  7 2022, 11:53:57) [GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import yaml
>>> data = '''
... some_base: &base
...   dice: d8
...   number: 4
... something_else:
...   <<: base
...   number: 6
... '''
>>> yaml.load(data)
{'some_base': {'dice': 'd8', 'number': 4}, 'something_else': {'dice': 'd8', 'number': 6}}
the features are called, roughly "anchors, extensions, and aliases". including a few of them will get you something useful on google

FuzzySlippers
Feb 6, 2009

I'll check out those yaml features getting the proper terminology is a big help thanks.

I do currently have a big awkward Unity tool, but the serializing was a major headache and it made small changes to lots of files really annoying. I could check out the UI Elements stuff for inspector scripting which is supposed to be semi-ready for proper use and would make this tooling a lot less obnoxious.

Here's a nutty idea. What about using js files as the data? I've heard of doing that with lua but I despise lua and you'd think the concept would work fine with js (using Jint or something to evaluate and push it into c# land, maybe as ts so you get some IDE error checking?). So, an iceball wouldn't be templated on a fireball it would instead be a bit of code that says (pseudocode)
code:
var iceBallSpell = new SpellConfig(GetSpell(fireBall));
iceBallSpell.id = "IceBall";
iceBallSpell.Get<ActionFX>.Value = "iceStuff";
RegisterNewSpell(iceBallSpell); 

It is certainly more verbose though in a way that looks right to my brain more than json. You'd have some weird linearity coupling that could get awkward (order of import needs to be set and not change). Is that totally crazy? I haven't looked at how Jint works at all, but one could potentially replace special one-off components for weird spells with just straight delegates defined along with the spell. There's certainly plenty of weird pnp spells (very few are anything like my dumb ice ball example)

FuzzySlippers fucked around with this message at 00:48 on Oct 9, 2022

TooMuchAbstraction
Oct 14, 2012

I spent four years making
Waves of Steel
Hell yes I'm going to turn my avatar into an ad for it.
Fun Shoe
The danger of code-as-data is that you've built an arbitrary execution exploit into your game. But if you're confident that it can't be abused, then it does make it easy to structure data in weird ways.

Bongo Bill
Jan 17, 2012

SQLite databases can serve as a serialization format that can enforce arbitrary data integrity invariants. You can use either any SQLite client or a custom-made tool for editing the data.

FuzzySlippers
Feb 6, 2009

TooMuchAbstraction posted:

The danger of code-as-data is that you've built an arbitrary execution exploit into your game. But if you're confident that it can't be abused, then it does make it easy to structure data in weird ways.

Jint claims you can sandbox the js stuff entirely to prevent it from doing trickery with .net but I'm not enough of a js expert to know if you can wreak havoc with js in the sandbox even just by itself.

Though for that matter what stops someone from using the assembly hacking in something like Rimworld (since it has official workshop support) from going ham with .net anyway? It's not controlled api access

Ranzear
Jul 25, 2013

I'm a huge nesty-multipage-spreadsheet-to-json nerd but what you describe seems a little over the top even for raw json, which I suppose is why you asked.

Hand-editing such syntactical data is a huge no-no in my opinion. I personally beat this horse to death once and explicitly forbade anyone touching the JSON after export from spreadsheets. That's all a different issue about correctness and handling though.

I think this means you haven't distilled down your game system enough yet, and a need to break it even further down to simpler behaviors instead of coding whole spell classes, leaning heavily into limited/single responsibility design. Like: Every spell should just operate on a flat target list, and filling that target list is not the responsibility of the spell itself but a targeting class the spell simply asks for by name and maybe provides some ranges or angles. Resisting the damage type of a spell isn't the spell's responsibility, it should be some damage handling system that takes the amount and the type and just passes it to each target to figure out if it's resisted or not.

If you're just talking about, say, an 'arc' targeting class that takes a range and angle ('direction' would be a gameplay input), and you want 'range' and 'angle' to be templated into the data, I sorta understand what you're asking for now, but I'd sooner just make them generic arguments used on demand with safe defaults, sorta more like {target_class:"arc",target_param1:40,target_param2:1.047}. Hell, one could still name them 'range' and 'angle' and just as well ignore them when not applicable. It simply does not matter if one has a 'global' target that has 'range' and 'angle' defined because anyone reading and trying to change those is (ideally) poking around in the wrong place instead of the editor.

If just to say: Having to do crazy nested self-referential JSON with variable structure based on some kind of class hierarchy borders on code smell. You probably aren't making complex behavior available nearly as much as you're making simple behavior complex. Not being able to describe your spells with just a spreadsheet probably means you're packing too much behavior into each one, IMO.

FuzzySlippers posted:

elaborate targeting information, effects, differing effects if a spell is overcast, etc.

These sound like things that aren't an individual spell's responsibility. If 'overcasting' a spell is different enough to call out like this, just make a separate spell type to call instead.

How much are you just trying to keep 'extraneous' datapoints out of each spell? Leave those in and hide them in the editor instead.

Sab669
Sep 24, 2009

I have a really dumb question about Unity 2D where a sprite is "disappearing" for reasons I cannot determine.

I'm just starting out and am using the simple built in Sprites for my player character (which is a snowman). The PC is comprised of an empty game object which "contains" a few circles for the body/head and 1 eye. All of these objects have a value of 0 for the Z axis, except for the eye which is -1.

To make my snowman face left or right, I'm updating that root empty object like so:

code:
this.gameObject.transform.localScale = new Vector2(-1, 1);
(or positive 1 when appropriate)

The issue I'm having is that when I move, the circle that is the snowman's eye disappears. At first I thought, "Oh it's being hidden by the circle that is its head when I turn around because of the Z axis" but this doesn't actually seem to be the case. I tried putting a second circle in the exact location as the first one, but with an opposite Z axis value so that I'd have 2 eyes "sandwiching" the head -- however I don't see it when my PC rotates, though. Also when I turn around a second time (aka return to my normal orientation) the eyeball circle is still not visible, which doesn't make any sense to me?

If I 'inspect' the eye while demoing the game I see it's Z position actually remains at -1, which also surprises me. I figured it'd be flipping between positive & negative 1 as I move left and right...

TooMuchAbstraction
Oct 14, 2012

I spent four years making
Waves of Steel
Hell yes I'm going to turn my avatar into an ad for it.
Fun Shoe

Ranzear posted:

If you're just talking about, say, an 'arc' targeting class that takes a range and angle ('direction' would be a gameplay input), and you want 'range' and 'angle' to be templated into the data, I sorta understand what you're asking for now, but I'd sooner just make them generic arguments used on demand with safe defaults, sorta more like {target_class:"arc",target_param1:40,target_param2:1.047}. Hell, one could still name them 'range' and 'angle' and just as well ignore them when not applicable. It simply does not matter if one has a 'global' target that has 'range' and 'angle' defined because anyone reading and trying to change those is (ideally) poking around in the wrong place instead of the editor.

If just to say: Having to do crazy nested self-referential JSON with variable structure based on some kind of class hierarchy borders on code smell. You probably aren't making complex behavior available nearly as much as you're making simple behavior complex. Not being able to describe your spells with just a spreadsheet probably means you're packing too much behavior into each one, IMO.

Another potential cause of this kind of problem is an unwillingness to have "wide" data structures. Parts in my game are defined by a spreadsheet that goes all the way to column FM, which means there's close to 200 different part properties. A lot of these are used only in one part of the code, and basically amount to parameters passed to a function somewhere. I can readily imagine a spell-definition spreadsheet that has columns for range, arc length, radius, height, etc. even if each of those parameters is only used by relatively few spells. Is it ugly? Maybe, but it's simple and it works, and I'm willing to accept a lot of ugliness in exchange for that.

FuzzySlippers
Feb 6, 2009

The basic codebase is about 5 years old (I dunno how many lines but it's 3000+ individual cs files) and if anything is probably over-engineered :shrug: It's a custom non-strict ECS and all of these component elements that make up a spell are absurdly broken down into many small components like an Action template (which is a spell there's no actual spell class just an entity with a certain set of components) doesn't even just have a targeting component but a number of sub-components that the targeting system can use to properly configure the many different types of targeting. That very specificity is part of what is killing me because a spell could potentially have any number of the 200+ Action components and most have at least a few dozen and then every component has at least a few fields of configurable data but some have 10+.

You can see why there is not a spreadsheet wide enough to accommodate these components and their fields. There are however a lot of spells that share a lot of configuration data so why templating/whatever seems an obvious solution to make the important configuration elements of each spell more accessible. FWIW every open-source roguelike that has a similar level of ability/spell complexity I've found uses manually edited jsons that are absurdly long for every entry.

Trying to adapt these pnp mechanics sucks because in a pnp environment there is little uniformity since a dm can interpret nebulous rules. A spell cast at a higher spell slot may not just upgrade the damage but add an entire new set of mechanics. My earlier 7drl just ignored all the complex rule breaking spells and focused on the simpler damage stuff, but I'm trying to more properly adapt pnp rules for this rewrite.

If you've ever taken a look under the hood of a dnd-ish game you can see how this gets nutty and is a source of endless bugs. Pillars accomplishes this with some bad prefab abuse that must've been a real pain to deal with. Kingmaker seems a bit smarter and uses Scriptables with I think embedded components, but they must have some heavy-duty inspector scripting to make it sensible to deal with. They have a team though for that and there's just me here.

My main events System is actually modeled after Kingmaker where they have a clever RulesSystem that handles the absurd number of ways a basic rule can be modified by various spells/feats/etc which would make it a nightmare to handle manually and where I break from proper ECS towards an event style that allows individual exceptions to register themselves and specify their order when resolving various Rules type events (rolling, calculating damage, applying damage, etc). Kingmaker's style is a bit tidier than what I found in old Bioware games and such.

It might even be easier to completely abandon proper SRP and just make every bloody spell its own class since GentleRepose.cs can just manually handle its own idiosyncrasies without needing to turn everything into a series of generic components that its configured to use. As I recall that's basically what NWN did with their scripting engine.

FuzzySlippers fucked around with this message at 23:28 on Oct 9, 2022

Ranzear
Jul 25, 2013

Memetic aside: A bridge that only breaks at ten times it's rated load is under-engineered. A bridge that breaks at one pound over rated load is over-engineered. Neither reflects the amount of work involved, but the suitability of the result. Excessive investment of time can produce either, what matters is the bridge that gets built.

Every spell being it's own class (or at least sharing and inheriting in sensible ways) would be my expectation. Trying to make one giant monolithic spell behavior class with a bunch of flagging and options per spell signals the way of madness.

I come from rust land where a simple castable spell trait ensures those classes plug and play. Won't imagine the dispatch bingo otherwise.

I'm the future I'll come at this the other way, starting with an effect chain that gets spliced into by other chainable modifiers until everything is fully polled and assembled and only then resolved as a whole (or rolled back and resolved again as even more effects come from mid-resolve interactions). Still hypothetical but for turn based robot combat it'll work great. Could do the same to inject all sorts of silliness from any source in a deep character customization realm, but it relies on a whole lot of verbose tagging and registering.

I refuse to touch the cursed the land of Unity, so I can only be general. I think your best bet is to step back and better encapsulate each phase of the spell being cast, like targeting versus avoiding versus damaging, and make sure it's all compartmentalized on those bounds. Don't be afraid to say no to stuff like changing targets after damage assignment or other stuff that breaks the flow (or be ready to change parameters in some way and run the whole process from the beginning again like my effect chains).

At the same time, it's easy to just have a second spreadsheet with lists of action thingies per row and an identifier on the first column to refer to a set externally. It doesn't have to be a monolithic sheet. I'll throw together a demo in a few minutes.

Edit: Turns out the JSON exporting addon I used to use just refuses to work. Just quits at the permissions step. I'll have to give ir another whirl later, but this is the basic setup that makes a simple lookup into a separate sheet (which will be a separate json object) to be functionally an array. Permits reuse by listable key, etc. I used to do all this junk like five levels deep (populating sets of lists into categories that then populated a weighted set of categories ad nauseam). Basically: Export each sheet into it's own json object with cross-referencing keys. You can even do data validation on your object's columns against the listables keys and stuff.

Ranzear fucked around with this message at 06:24 on Oct 10, 2022

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I generally wondered what solutions people have proposed towards the temporality problems that come up with the purer compositional patterns like ECS or even just MonoBehaviours.

If you want something more specific, I started putting a lot of subsystems under one effectively global handle for managing subsystems. It's not really ECS though. A few of them manage things like a camera that I assign as a child of the object. I can then mess with this in the Unity Editor offline. The first problem is that some of these objects should be marked not to be destroyed between scenes (camera, player, essential objects some 3rd-party stuff likes to keep around). I can manage most of this in initialization of this global state on a MonoBehaviour on the global object, but the camera kicks in before that and starts to flag itself to not be destroyed when loading the next scene. I had to make the object inactive and activate it inside my global state.

So in each case so far, I've been able to explicitly do something to force the situation. However, it's the kind of thing that needs a comment to explain why and comes across as brittle. For my own personally stuff, I can live with this. The problem is that professionally I sometimes trip across this decoupled stuff and have the same temporality problems. Given those, I'd like to consider better ways to manage it, but I'm not really sure what there is.

Isometric Bacon
Jul 24, 2004

Let's get naked!
Order of execution is the biggest problem I come across in Unity.

In one of my main projects we control initialisation order by making all our controller classes static, which ensures their initialisation order is before anything is invoked by a MonoBehaviour.

Each class has a initialisation function, which are called by a static initialiser script that controls their order.

This approach has worked well, but I have a few problems with it, partly because it I find having everything static encourages us to constantly write systems that could be accomplished (and much more modifiable by non programmers) with component based systems. This is exacerbated by the fact our Devs come from non gaming/ WYSIWIG backgrounds, and don't think about non programmers.

The best compromise I've had is to then have mono behaviours be pointers that self register with the controllers, and invoke events on their creation and destruction. Then I push for additional 'behaviour' scripts that can be added to them that dictate how they behave to input.

However, since our controllers are all global static you can't access them in the inspector without writing a wrapper monobehaviour - typically things like wiring up simple logic for making UI buttons do something, or passing a prefab through to a controller means writing custom code for it.

I want to cut down on the amount of code that has to be managed and maintained - and now with systems like addressables allowing you to push content updates to users - as long as you don't recompile, it makes sense to define behaviours through the inspector.

For the next project we're working on, I'm strongly pushing for us to look at how Unity does its component based architecture and emulate that. I've also implemented an eventbus to ensure none of our controllers have direct references to each other for modularity. This has worked great for the most part, but order of execution is a nightmare. We're never guaranteed that one of our controller scripts awakes before a behaviour wants to register with it.

Here's something fun. In the hierarchy unity will execute code on children before their parent. This has caused no ends of drama.

To compromise this, we've had to have a generic dependencies script that any call for a controller is routed through, and if it doesn't exist yet, it creates it. Everything registers and sets themselves up in awake and start, but nothing is initialised until a scene ready event is dispatched - which occurs on the first fixed update, guaranteeing everything has executed their awake and start functions.

Ranzear
Jul 25, 2013

With the disclaimer that I have a raw and inexplicable hatred for ECS and OOP in general, I think it's inescapable in Unity or Godot without really breaking fundamental stuff in either. Even stuff like the scene camera being the child of a game object is intolerable to me but I understand it's just kinda normal compared to giving the camera a reference to update its position relative to (and I expect Unity to somehow break it anyway).

My ideal is more of an Entity+Tag+Behavior system. Sounds like ECS with extra steps, but ECS iterates entities to find components to execute behaviors while I want to flip that around and iterate behaviors to find entities (by tags in basically a publish/subscribe registration) that want to execute them. This is even still separate from the effect chains I mentioned in the prior post which are just a stack of interactions that might form one 'behavior' with multiple inputs or interrupts.

Tags work as both an 'invoke me for x behavior' and 'I am a potential target for x or y behavior'. Also an entity can have varying presence in different layers of the simulation, even different hitboxes for stuff like physics vs contact checks, and tags control those interaction layers as well.

This leads to, for lack of a better description, everything running as Magic The Gathering phases. New entities can be created at the start of a tick and still get registered and displayed and interact on the same tick, physics can be run well before any contact checks, damage and healing happens before any effects dependent on HP, etc. I think this is the approach to temporality you're asking for, even if it's not a useful concept outside of my experimental jank just yet. I think this is what your singleton achieves, moving behavior into a more concrete ordering, and is the proper use of one.


Unrelated: Y'all know what would be really cool? Multiwindow/multimonitor games. I can already do this with Vulkano/Winit and postulate like, 3rd person or retro RPG with inventory and dialogue and other UI stuff on a second monitor instead. Drag one's MMO-style subwindows out into actual windows and throw them wherever one likes. Forget minimaps, use my second monitor as a maximummap. Any other suggestions worth pursuing?

Adbot
ADBOT LOVES YOU

Chainclaw
Feb 14, 2009

Ranzear posted:

With the disclaimer that I have a raw and inexplicable hatred for ECS and OOP in general, I think it's inescapable in Unity or Godot without really breaking fundamental stuff in either. Even stuff like the scene camera being the child of a game object is intolerable to me but I understand it's just kinda normal compared to giving the camera a reference to update its position relative to (and I expect Unity to somehow break it anyway).

My ideal is more of an Entity+Tag+Behavior system. Sounds like ECS with extra steps, but ECS iterates entities to find components to execute behaviors while I want to flip that around and iterate behaviors to find entities (by tags in basically a publish/subscribe registration) that want to execute them. This is even still separate from the effect chains I mentioned in the prior post which are just a stack of interactions that might form one 'behavior' with multiple inputs or interrupts.

Tags work as both an 'invoke me for x behavior' and 'I am a potential target for x or y behavior'. Also an entity can have varying presence in different layers of the simulation, even different hitboxes for stuff like physics vs contact checks, and tags control those interaction layers as well.

This leads to, for lack of a better description, everything running as Magic The Gathering phases. New entities can be created at the start of a tick and still get registered and displayed and interact on the same tick, physics can be run well before any contact checks, damage and healing happens before any effects dependent on HP, etc. I think this is the approach to temporality you're asking for, even if it's not a useful concept outside of my experimental jank just yet. I think this is what your singleton achieves, moving behavior into a more concrete ordering, and is the proper use of one.


Unrelated: Y'all know what would be really cool? Multiwindow/multimonitor games. I can already do this with Vulkano/Winit and postulate like, 3rd person or retro RPG with inventory and dialogue and other UI stuff on a second monitor instead. Drag one's MMO-style subwindows out into actual windows and throw them wherever one likes. Forget minimaps, use my second monitor as a maximummap. Any other suggestions worth pursuing?

The problem with Entity Component Systems and entity systems with components is they share a lot of terminology but aren't really related.

What you're describing, with entities full of datas & tags, and a separate set of logic that operates on them, is actually a lot closer to what an Entity Component System is. The default entities and components in Unity are not at all an Entity Component System.

Yes, it's confusing and annoying that they're named so similar.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply