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
novamute
Jul 5, 2006

o o o
Those are all totally reasonable. The only thing that I think might prompt a change away from any particular one of those technologies is how you're planning on doing your hosting. If it's very small audience expected, you can probably live on a free plan on Heroku or something. AWS isn't going to be free after a year, even if you still have very little usage. Which platform you end up hosting on can affect what options you have for back end

Adbot
ADBOT LOVES YOU

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I was pondering how the Unreal Engine might handle some stuff I'm currently doing in Unity. What might it have for?

1. Embedding Python code for level/game scripting--not for main game logic.
2. Saving and loading game state without having to basically save every aspect of the world.
3. 2d GUI stuff with some kind of DOM like you see with WPF.

I'm having to do a lot more C/C++ stuff these days and I haven't touched my Unity doodles in so long that I was wondering if it would be worth switching. I was hoping to do it without blowing some months on trying it out only to drop it.

Raenir Salazar
Nov 5, 2010

College Slice

Rocko Bonaparte posted:

I was pondering how the Unreal Engine might handle some stuff I'm currently doing in Unity. What might it have for?

1. Embedding Python code for level/game scripting--not for main game logic.
2. Saving and loading game state without having to basically save every aspect of the world.
3. 2d GUI stuff with some kind of DOM like you see with WPF.

I'm having to do a lot more C/C++ stuff these days and I haven't touched my Unity doodles in so long that I was wondering if it would be worth switching. I was hoping to do it without blowing some months on trying it out only to drop it.

I work a bit with unreal in my day job, I'm by no means an expert though.

1. I'm not exactly sure of the distinction you're drawing between scripting and game logic; but in any case Blueprints are a fairly lightweight means of quickly prototyping and iterating on your game mechanics. And you can typically convert them by hand to C++ for better performance and easier maintenance once you're satisfied.

2. I run away and hide from our level management/save state code, but my impression is something somewhere at some point needs to save your data to disk if you want the ability to save/load. I know we use some kind of level/asset streaming, maybe that's what you're looking for?

3. Unreal afaik has the same kind of/similar UI layout for its 2D UI (Unreal calls them "widgets"); I dislike it as you need to use a special editor tool the Widget Reflector to actually debug them in your game as they don't show up in the scene hierarchy. So regarding DOM stuff I think you need to buy/find a Unreal asset package thingy like with Unity if you don't want to implement your own solution.

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

Rocko Bonaparte posted:

I was pondering how the Unreal Engine might handle some stuff I'm currently doing in Unity. What might it have for?

1. Embedding Python code for level/game scripting--not for main game logic.
2. Saving and loading game state without having to basically save every aspect of the world.
3. 2d GUI stuff with some kind of DOM like you see with WPF.

I'm having to do a lot more C/C++ stuff these days and I haven't touched my Unity doodles in so long that I was wondering if it would be worth switching. I was hoping to do it without blowing some months on trying it out only to drop it.

Python isn't great as an embedded lang. You'll need to do the lifting yourself either way (unless there's a project from someone similar who made an integration with python). Not even sure the cleanest way to do it; named pipes maybe?

Neither unity nor unreal really solve save/load for you. But you probably shouldn't serialize the full world state for everything? I guess it depends on how much of the world is subject to change. Usually people use a more abstract model of the world and then synchronize the state of real objects against that.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Thanks for the responses. Using Python for some additional scripting is my goofy specific thing. To answer about how, I would be using it for, say, NPC scripting, interactions, and various triggers. It's very particular and peculiar.

It looks like I'd be porting all of my stuff over, which is probably not worth the time. The code is pretty decoupled but I imagine even the game serialization would wind up having a similar interaction with Unreal that it has with Unity. Still, it would be taking a ton of C# and sending it to C++. It just sounded like "serious" game developers were having a blast with Unreal over Unity so I was wondering if I was missing out on something.

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

Rocko Bonaparte posted:

Thanks for the responses. Using Python for some additional scripting is my goofy specific thing. To answer about how, I would be using it for, say, NPC scripting, interactions, and various triggers. It's very particular and peculiar.

It looks like I'd be porting all of my stuff over, which is probably not worth the time. The code is pretty decoupled but I imagine even the game serialization would wind up having a similar interaction with Unreal that it has with Unity. Still, it would be taking a ton of C# and sending it to C++. It just sounded like "serious" game developers were having a blast with Unreal over Unity so I was wondering if I was missing out on something.

There are more "serious" game devs working in Unity than work in Unreal. But both engines are a frightening mix of great and terrible.

sailormoon
Jun 28, 2014

fighting evil by moonlight
winning love by daylight


I've currently implemented rollback netcode with a central, authoritative server (wooh!). I'm running into issues where if players have zero input delay, the other players see them "teleport" to their locations once the clients receive the update.

Below is an example, assuming a 6 tick round-trip time (3 ticks to server, 3 ticks to clients) and both the client and server running at 60TPS.

1. Server is on T.
2. Client is enforced to always be simulating N steps ahead of its last known server frame. Let's assume it's hard-coded to T+3.
3. Client sends input at T+3 to "jump".
4. Server receives input at its T+3, simulates it, and sends it to other clients.
5. Other clients receive the T+3 input at T+6. The clients roll-back to the T+3 frame and simulate back to T+6 with the corrected input.

Step 5 causes us to lose drawing T+3, T+4, and T+5 accurately so it can look like the player "teleports" to their T+6 position. One way to solve this would be to add an input delay of 3 (client sends at T+3 for T+6), but I don't think this would scale well for clients with differing round-trip times and the input delay can feel rather bad.

How is this problem typically solved? I've watched the Overwatch + Rocket League rollback netcode talks and the great videos from Net_ on YouTube, but nothing mentions how to handle smoothing out this portion.

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

sailormoon posted:

I've currently implemented rollback netcode with a central, authoritative server (wooh!). I'm running into issues where if players have zero input delay, the other players see them "teleport" to their locations once the clients receive the update.

Below is an example, assuming a 6 tick round-trip time (3 ticks to server, 3 ticks to clients) and both the client and server running at 60TPS.

1. Server is on T.
2. Client is enforced to always be simulating N steps ahead of its last known server frame. Let's assume it's hard-coded to T+3.
3. Client sends input at T+3 to "jump".
4. Server receives input at its T+3, simulates it, and sends it to other clients.
5. Other clients receive the T+3 input at T+6. The clients roll-back to the T+3 frame and simulate back to T+6 with the corrected input.

Step 5 causes us to lose drawing T+3, T+4, and T+5 accurately so it can look like the player "teleports" to their T+6 position. One way to solve this would be to add an input delay of 3 (client sends at T+3 for T+6), but I don't think this would scale well for clients with differing round-trip times and the input delay can feel rather bad.

How is this problem typically solved? I've watched the Overwatch + Rocket League rollback netcode talks and the great videos from Net_ on YouTube, but nothing mentions how to handle smoothing out this portion.

Blend from where you are to where you're going. This will roughly look like the animations playing faster than you'd normally expect.

more falafel please
Feb 26, 2005

forums poster

leper khan posted:

Blend from where you are to where you're going. This will roughly look like the animations playing faster than you'd normally expect.

This. Alternatively, you can speed up the actual animations, but if your animation system isn't set up for that, it might be more work.

sensitivepigeon
Dec 4, 2016

I'M SENSITIVE ABOUT IT, OK?
Hey all, I hope this is an alright place to ask for a point in the right direction. Even the simple answer of "learn and Google X" is very helpful

I made a mockup from a tutorial I followed using phaser3, socket.io, Javascript of a card game. Basic stuff like "button press deals 5 cards to each player from expandable deck", "opponent can't see your hand", "cards can be placed in the drop zone (well, I messed up the part where they render there for player B)

I was wondering if anyone could provide some advice on getting into game logic. Stuff like a very, VERY simplified hearthstone mechanics. Bigger number wins. Taunt mechanic. Blah blah. Making a basic card logic framework.

Super newbie but I'm extremely driven to learn this stuff, might look ok on baby's first portfolio too if I can actually figure mechanics. Trouble is, I might be going about this the wrong way entirely because Google isn't my friend atm. Is there a better way to accomplish this kind of browser based card game?

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

sensitivepigeon posted:

Hey all, I hope this is an alright place to ask for a point in the right direction. Even the simple answer of "learn and Google X" is very helpful

I made a mockup from a tutorial I followed using phaser3, socket.io, Javascript of a card game. Basic stuff like "button press deals 5 cards to each player from expandable deck", "opponent can't see your hand", "cards can be placed in the drop zone (well, I messed up the part where they render there for player B)

I was wondering if anyone could provide some advice on getting into game logic. Stuff like a very, VERY simplified hearthstone mechanics. Bigger number wins. Taunt mechanic. Blah blah. Making a basic card logic framework.

Super newbie but I'm extremely driven to learn this stuff, might look ok on baby's first portfolio too if I can actually figure mechanics. Trouble is, I might be going about this the wrong way entirely because Google isn't my friend atm. Is there a better way to accomplish this kind of browser based card game?

Figure out what you're trying to make before you make it. Paper prototypes are really useful here, especially for things like a card game that are already physically analogous.

After you figure out what you're trying to build.. build it. Keep the model independent of your view, then write the view against the model. Start with the more foundational things then move to more complex additions after you have something that works. Remember vanilla is an additive to ice cream, the bare bones game may not be extremely fun.

A browser game is just a single page app. Deconstruct everything into the data, process on the back end, and forward the data to the view.

If you're looking for frameworks, I like Phoenix. This book goes over explicitly building out a multiplayer tic tac toe game.

https://www.amazon.com/Functional-Web-Development-Elixir-Phoenix/dp/1680502433/ref

This is my favorite book on game design.

https://www.amazon.com/Art-Game-Design-Lenses-Third-dp-1138632058/dp/1138632058

sensitivepigeon
Dec 4, 2016

I'M SENSITIVE ABOUT IT, OK?

leper khan posted:

Figure out what you're trying to make before you make it. Paper prototypes are really useful here, especially for things like a card game that are already physically analogous.

After you figure out what you're trying to build.. build it. Keep the model independent of your view, then write the view against the model. Start with the more foundational things then move to more complex additions after you have something that works. Remember vanilla is an additive to ice cream, the bare bones game may not be extremely fun.

A browser game is just a single page app. Deconstruct everything into the data, process on the back end, and forward the data to the view.

If you're looking for frameworks, I like Phoenix. This book goes over explicitly building out a multiplayer tic tac toe game.

https://www.amazon.com/Functional-Web-Development-Elixir-Phoenix/dp/1680502433/ref

This is my favorite book on game design.

https://www.amazon.com/Art-Game-Design-Lenses-Third-dp-1138632058/dp/1138632058

thank you, i appreciate your advice! i actually went to the "Figure out what you're trying to build part" and started from the beginning because of your post. i did some art assets and im doing the base before i do any coding at all and having a good time!

thank you sm!


(also i wanted to share the asset style of what im doing. all the cards look like this essentially, still working on refining them. if anyone wants to talk about it it would be cool you can PM me)

TIP
Mar 21, 2006

Your move, creep.



currently bashing my head against the wall trying get some unity assets to work together

I'm using the active ragdoll system called Puppetmaster and while it works fine with their included model, every single character I own completely fails the same way

I set up the ragdoll and it looks fine



and I can test it and the ragdoll works fine

then I add the active ragdoll system and this happens when I press play



googling around I managed to find someone with the same issue and the developer's response was this:
It is because of the model's bones are not oriented right. Colliders can't be rotated in Unity so they take the rotation of the gameobject they are attached to. If you select any of those arm bones, you'll see they are not pointing towards the next bone like they should. This can only be fixed in the 3D app that was used to create the model. If you do not have access to that, a workaround would be to add child gameobjects to each ragdoll part and move the colliders over to those. Then you can rotate those children to fix it.

I... don't know what to do with this. I tried contacting the people who made the model to ask them to point their bones in the right direction but I have not heard back. I get the idea of adding child objects and using those to rotate the colliders, but I have no idea how to tell what direction the bone is pointing to correct it. I did try moving the colliders to child gameobjects and manipulating them that way but I'm working somewhat blind and nothing I did seemed to actually change anything.

I bought some more characters in the asset store from a different company and they have the exact same problem.

I'm hoping one of you has dealt with this issue and has a clearer explanation of how to fix it.

TIP
Mar 21, 2006

Your move, creep.



I think I have made some progress on the problem

I figured out that the character assets came as FBX files that I can import into blender and edit, and once I did that it was pretty clear the issue with the bones and how to fix them

however, now I'm stuck on properly exporting an FBX to unity

I'm not super versed on blender and it's kinda driving me crazy

when I import the FBX it automatically puts all the contents into a group in my scene, then if I select that group and choose to export only selected the group screws up the hierarchy and unity can't find anything on import

if I just select the top level stuff inside the group it doesn't export anything lower in the hierarchy so seemingly I have to open up and select every little thing in the file in order to export with the correct structure

however, when I import that into unity it breaks a bunch of stuff and the models won't render anymore :bang:

I can't even manage to import an FBX and export it without modifying anything and get it to work


anyone know what I'm screwing up here in my process of importing and exporting FBX files with rigged characters?

I feel like I'm inches away from solving this

Mr Shiny Pants
Nov 12, 2012

Tip posted:

I think I have made some progress on the problem

I figured out that the character assets came as FBX files that I can import into blender and edit, and once I did that it was pretty clear the issue with the bones and how to fix them

however, now I'm stuck on properly exporting an FBX to unity

I'm not super versed on blender and it's kinda driving me crazy

when I import the FBX it automatically puts all the contents into a group in my scene, then if I select that group and choose to export only selected the group screws up the hierarchy and unity can't find anything on import

if I just select the top level stuff inside the group it doesn't export anything lower in the hierarchy so seemingly I have to open up and select every little thing in the file in order to export with the correct structure

however, when I import that into unity it breaks a bunch of stuff and the models won't render anymore :bang:

I can't even manage to import an FBX and export it without modifying anything and get it to work


anyone know what I'm screwing up here in my process of importing and exporting FBX files with rigged characters?

I feel like I'm inches away from solving this
Try this: https://github.com/EdyJ/blender-to-unity-fbx-exporter

Otherwise be sure to select armature during export.

TIP
Mar 21, 2006

Your move, creep.



Mr Shiny Pants posted:

Try this: https://github.com/EdyJ/blender-to-unity-fbx-exporter

Otherwise be sure to select armature during export.

hey, thanks, I did eventually manage to get importing/exporting to work properly by converting fbx to gltf2

I ended up discovering that the issue in puppetmaster could be fixed by enabling an option for characters with translational animations

I hadn't even tried it because my issue was happening with no animator at all

Beefeater1980
Sep 12, 2008

My God, it's full of Horatios!






sensitivepigeon posted:

thank you, i appreciate your advice! i actually went to the "Figure out what you're trying to build part" and started from the beginning because of your post. i did some art assets and im doing the base before i do any coding at all and having a good time!

thank you sm!


(also i wanted to share the asset style of what im doing. all the cards look like this essentially, still working on refining them. if anyone wants to talk about it it would be cool you can PM me)



These are cool. Do they all have the same colour theme or are there different “suits” or what have you?

Mr Shiny Pants
Nov 12, 2012

Tip posted:

hey, thanks, I did eventually manage to get importing/exporting to work properly by converting fbx to gltf2

I ended up discovering that the issue in puppetmaster could be fixed by enabling an option for characters with translational animations

I hadn't even tried it because my issue was happening with no animator at all

GLTF Export is good, it will even do PBR maps. Glad you got it fixed.

Beefeater1980
Sep 12, 2008

My God, it's full of Horatios!






I have a question about sensible / industry-standard architecture for branching dialogue trees and whether I’m making a terrible design decision that will bite me in the rear.

I’m working on a project that includes a CYOA component. The game engine I’m using is Godot, which so far seems relatively user friendly if a bit particular.

I had intended to use Ink for the CYOA segments but it’s proving too much of a pain to make it play nice with Godot (there is a plug-in that I cannot for the life of me make work). So I am patching together my own solution using a SQLite database. I have two tables:

1 - Paragraphs (Unique ID, Text)
2 - Choices (Unique ID, paragraph that spawns it, paragraph the choice leads to, field for effect on each variable, flags for story events)

So basically my program, when executed, loads text from the starting paragraph, looks up the choices that belong to that paragraph, and then when the user selects one of the choices, does it all over again (and processes any changes to stats / sets any relevant flags)

This *works*, but I can see it becoming massively hard to track and manage over time as paragraphs and choices multiply. What’s the smarter way of doing this? E: I am certain there is a very obvious one that isn’t occurring to me and it’s driving me crazy.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Your structure seems fine, it sounds like what you need is better tools for working with it.

For example, you could write a converter that takes Ink's data files and converts them to your format, then use all the Ink tooling to actually do the writing.

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

Beefeater1980 posted:

I have a question about sensible / industry-standard architecture for branching dialogue trees and whether I’m making a terrible design decision that will bite me in the rear.

I’m working on a project that includes a CYOA component. The game engine I’m using is Godot, which so far seems relatively user friendly if a bit particular.

I had intended to use Ink for the CYOA segments but it’s proving too much of a pain to make it play nice with Godot (there is a plug-in that I cannot for the life of me make work). So I am patching together my own solution using a SQLite database. I have two tables:

1 - Paragraphs (Unique ID, Text)
2 - Choices (Unique ID, paragraph that spawns it, paragraph the choice leads to, field for effect on each variable, flags for story events)

So basically my program, when executed, loads text from the starting paragraph, looks up the choices that belong to that paragraph, and then when the user selects one of the choices, does it all over again (and processes any changes to stats / sets any relevant flags)

This *works*, but I can see it becoming massively hard to track and manage over time as paragraphs and choices multiply. What’s the smarter way of doing this? E: I am certain there is a very obvious one that isn’t occurring to me and it’s driving me crazy.

From my view, I'd need a reason to not just use inkle. I'd just port that to whatever other thing I need.

E: someone already did that for you https://github.com/ephread/inkgd

Beefeater1980
Sep 12, 2008

My God, it's full of Horatios!






Thanks guys, Ink it is.

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 need to be working more on promoting my game. Thing is, I have neither the time nor energy to really give that task the attention it deserves. Who should I talk to about exchanging money for promotional work? Specific goals:

- Build community
- Increase word of mouth
- Get press and streamer attention

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
If you try to embed Ink on some way, double check that the actions you add for your scripting work as expected. I got bit by that in Unity and had to completely drop it since they made it clear they had no intention to support that kind of bedding.

Fuschia tude
Dec 26, 2004

THUNDERDOME LOSER 2019

TooMuchAbstraction posted:

I need to be working more on promoting my game. Thing is, I have neither the time nor energy to really give that task the attention it deserves. Who should I talk to about exchanging money for promotional work? Specific goals:

- Build community
- Increase word of mouth
- Get press and streamer attention

Sounds like you want to find a social media manager, marketing/brand manager, or virtual assistant. Obviously, games are a specialized field so you want someone with experience here, and ideally they have connections to journalists or the like.

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

Fuschia tude posted:

Sounds like you want to find a social media manager, marketing/brand manager, or virtual assistant. Obviously, games are a specialized field so you want someone with experience here, and ideally they have connections to journalists or the like.

Sounds about right. Do you have any suggestions for how to go about doing this?

Chainclaw
Feb 14, 2009

My current side project is a racing game for the Sega Genesis. I've spent a few months stuck, trying to figure out how I want to edit tracks. After a lot of musing on it, I realized the easiest track editor would be to just use an SVG file to define the curve for the track.

I wrote up a few blog posts for it here. There are also builds available to download if anyone feels like driving around what's not much of a game yet.

Part 1: Ideas I didn't like, and experimenting with SVG files
https://joejoejoejoe.itch.io/roguerider/devlog/340008/track-editor

Part 2: Proof of concept
https://joejoejoejoe.itch.io/roguerider/devlog/340639/track-editor-part-2

Part 3: Meta data- Spawn location, checkpoints. Visual clean up and gameplay logic tracking.
https://joejoejoejoe.itch.io/roguerider/devlog/341164/track-editor-part-3

Part 4: Cat
https://joejoejoejoe.itch.io/roguerider/devlog/341725/cat-track

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've identified a category of bugs in my game that's caused by Unity's order of execution not being consistent between the editor and builds. It basically looks like this:

- In Awake and/or Start, objects subscribe to my global publish/subscribe system. This happens in inconsistent order.
- When events are published to the system, it iterates through the list of subscribers using a dictionary (that maps subscriber to the callback to invoke on that subscriber). This also happens in an inconsistent order (iteration order over dictionaries is not guaranteed), though I'm not sure how much impact it has
- Sometimes, the subscribers implicitly assume that things happen in a specific order, and that works out in the editor, but not in builds (or hypothetically vice versa, but then I usually fix it when it doesn't work for me).

I like the system I made, because it is extremely short on boilerplate. Subscribers just do something like GlobalPubSub.Subscribe<SpawnGroupEvent>(this, OnSpawnGroup), where `this` is literally any object, and OnSpawnGroup is a function that takes a `SpawnGroupEvent` instance as its sole parameter and returns nothing. In particular, there's no requirement that anything implement an interface; so long as your callback has the right signature, you're good to go.

It's easy to use, so I use it a lot (there's currently exactly 256 calls to GlobalPubSub.Subscribe, a nice round number :v:). Buuuut it's not readily amenable to retrofitting into something that can be ordered. Because the system operates on `object`s, I don't think there's any data associated with the subscriber object, that GlobalPubSub can access, that would provide a consistent iteration order. It seems like I'll have to change the signature somehow to achieve this. Which sucks, because there's 256 uses of it.

I could see changing the signature on Subscribe to also require the caller to provide a sorting key, which would be used to enforce consistency in call order. Let's assume the key is a string, for the sake of argument. The above example would become instead e.g. GlobalPubSub.Subscribe<SpawnGroupEvent>(this, OnSpawnGroup, "TripodController") (I feel safe hardcoding the string because two instances of the same class subscribing to the same event definitely should not care about order of execution between them). But now I'm left with how to structure the subscriber registry inside of the pub/sub system, such that I can efficiently add, remove, and iterate through subscribers. It gets invoked a lot, so performance matters.

Currently, that registry is a Dictionary<Type, Dictionary<object, object>>. It maps event types (such as SpawnGroupEvent) to dictionaries mapping the subscriber object to the callback to invoke. I guess instead I'd need, say, a Dictionary<Type, SortedList<string, object>> in addition? That is, map event type to <sort key, object> pairs. I'd need to provide my own comparer, to permit duplicate keys in the SortedList. Then when an event is published, I'd iterate through the subscribed objects in order of their sort keys, and invoke their callbacks using the first dictionary.

(And yes, I'm aware that sorting by e.g. numbers would be more efficient, and I'll probably end up doing that; strings have the advantage that I can just type in the class name as the sort key, and get something guaranteed unique within my code. I guess I could sort by e.g. "TripodController".GetHashCode())

This all sounds like a bit of a mess, so I'd love to hear if someone else has a better suggestion.

novamute
Jul 5, 2006

o o o
With a fairly small set of subscribers you could do the opposite and explicitly iterate over them in a random order when not in a build which hopefully should let you uncover and fix the problems.

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

novamute posted:

With a fairly small set of subscribers you could do the opposite and explicitly iterate over them in a random order when not in a build which hopefully should let you uncover and fix the problems.

I know that Go, the programming language, does this, and it's very helpful if you have a robust test system in place, which I do not. As such, I'd rather have a system where order-of-execution errors are either consistently revealed or consistently hidden, so long as it doesn't change between editor and builds.

KillHour
Oct 28, 2007


Normally callbacks would be handled by a list or array of consumers for each producer. If your events are types, I'm not sure why you need the nested dictionary? Presumably, OnSpawnGroup would just call every registered function mapped to it, in the order of the array/list. You could sort that array/list every time you add something, but I would think it makes more sense for things that happen in a specific order to have different callback events. So, for instance, if you have OnSpawnGroup do two things that need to happen in order, I would have OnSpawnGroupStart and OnSpawnGroupEnd or whatever.

Edit: It occurs to me that you might have the second dictionary because you need two objects in the value field so a <Type, Object[]> wouldn't work. In which case, you should use tuples.

KillHour fucked around with this message at 02:03 on Feb 3, 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 dictionary in the first registry could be replaced by a list of tuples, it's true. Tuples are kind of a pain to use in C# though, and List<Tuple<object, object>> is worse IMO than Dictionary<object, object> while gaining nothing in terms of enforced ordering. Remember that the order of execution (in the current implementation anyway) derives at least in part from the order in which Unity sees fit to awaken various gameobjects. It's fundamentally not something I have control over.

Adding different events to enforce order of execution is a non-starter because I don't know that I'm relying on order of execution until something goes wrong (which might happen only in builds). The goal here is to avoid shipping bugs, and I need an architecture that supports that goal.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
When you start nesting multiple levels of collections like this, it's good to take a step back and think about whether defining some new classes would make things clearer or simplify some implementations.

For example, if you defined an EventManager class that handled dispatching an event to a set of observers, and made the dictionary in your top-level registry just a Dictionary<Type, EventManager>, that would separate those concerns and allow you to focus on them individually.

You could also define a RegistrationRecord struct that encapsulates the listener and function to invoke (and sort key, if you choose to go that route) and simple have the EventManager hold a single List<RegistrationRecord>. When dispatching events, just iterate the list and call the functions - when adding or removing listeners (relatively rare in comparison), iterate the list until you find the right spot to insert or listener to remove. You only have a small number of listeners so it's not a big deal.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I have vague, visceral memories of having to give the initial MonoBehaviour callbacks less and less agency and just assume I am eating a frame of Update() before everything has met everything else. In practice, it can suffice to have one subsystem just track that you have gone a whole cycle and flag that it is okay to assume all the plumbing is in place.

For all the moon beams I like to ride, I just had all my subsystems vulnerable to that temporality problem stuffed into a single subsystem controller whose temporality I could rigidly control. If I needed moon beams then I'd be looking at the independent agents stating dependencies like you would get in a dependency injector object graph. At that point I would really need to put down the bong.

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

Jabor posted:

When you start nesting multiple levels of collections like this, it's good to take a step back and think about whether defining some new classes would make things clearer or simplify some implementations.

For example, if you defined an EventManager class that handled dispatching an event to a set of observers, and made the dictionary in your top-level registry just a Dictionary<Type, EventManager>, that would separate those concerns and allow you to focus on them individually.

You could also define a RegistrationRecord struct that encapsulates the listener and function to invoke (and sort key, if you choose to go that route) and simple have the EventManager hold a single List<RegistrationRecord>. When dispatching events, just iterate the list and call the functions - when adding or removing listeners (relatively rare in comparison), iterate the list until you find the right spot to insert or listener to remove. You only have a small number of listeners so it's not a big deal.

Yeah, this is fair. The current code is definitely at the limit of nested generics, in terms of what I'm comfortable dealing with. Thanks!

Rocko Bonaparte posted:

I have vague, visceral memories of having to give the initial MonoBehaviour callbacks less and less agency and just assume I am eating a frame of Update() before everything has met everything else. In practice, it can suffice to have one subsystem just track that you have gone a whole cycle and flag that it is okay to assume all the plumbing is in place.

For all the moon beams I like to ride, I just had all my subsystems vulnerable to that temporality problem stuffed into a single subsystem controller whose temporality I could rigidly control. If I needed moon beams then I'd be looking at the independent agents stating dependencies like you would get in a dependency injector object graph. At that point I would really need to put down the bong.

I use Unity's builtin callbacks as little as possible, and I explicitly turn off its UI event system if I possibly can.

I'm looking for an architecture where I don't have to know in advance which stuff is vulnerable to order-of-execution bugs. I want to just enforce a consistent ordering on everything, regardless of whether it's necessary, but with a minimum of fuss.

KillHour
Oct 28, 2007


TooMuchAbstraction posted:

The dictionary in the first registry could be replaced by a list of tuples, it's true. Tuples are kind of a pain to use in C# though, and List<Tuple<object, object>> is worse IMO than Dictionary<object, object> while gaining nothing in terms of enforced ordering. Remember that the order of execution (in the current implementation anyway) derives at least in part from the order in which Unity sees fit to awaken various gameobjects. It's fundamentally not something I have control over.

Adding different events to enforce order of execution is a non-starter because I don't know that I'm relying on order of execution until something goes wrong (which might happen only in builds). The goal here is to avoid shipping bugs, and I need an architecture that supports that goal.

Oh, so your issue isn't that dictionaries aren't inherently ordered, it's that you don't know what order the events get registered in because you might have multiple events getting registered in the same frame. You still don't want to use a dictionary because even if you can guarantee the order in which they're added, you can't guarantee the order in which they're retrieved. A list would solve that issue. The other, unrelated issue, is you need to guarantee your events get registered in a particular order.

Unity does have a built-in way of doing that: https://docs.unity3d.com/Manual/class-MonoManager.html

Here's what I would do - I would pick some arbitrarily high number like 1000 and say anything below that is manually ordered and anything above that is automatically ordered. Then I would create an editor script to manually populate every monobehavior that has your event signature but isn't already in the script execution order by appending it to the end with a time of [oldHighestTime + 10] or something. Then instead of registering each instance to some big central list that needs to be periodically reordered, register each instance to the class itself through a static list and call each list in the order the class registered itself on startup. Since they all run in a given order, they should have registered themselves in that order. That will guarantee you run through all callbacks on class X then Y then Z, even if some were added in later frames.

The other option is to, as you said, keep each script type in a nested list and iterate through that like a jagged array. You would probably want a Dict<Type, List<List<(object, object)>>> (or Dict<Type, List<(object, object)>[ ]> since the size of the outer list is determined by the number of classes and should be static) and a Dict<Type, int> to index the outer list, but it seems kind of unwieldy and you would need some sort of solution for deterministically populating the indexing dict anyways.

Edit: And in C# 7 and up, Tuples became way more convenient: List<(object, object)>. Adding a value to a list is also faster than adding a value to a dictionary, if that matters. Searching a dictionary is faster, but it sounds like you're just iterating over it in order.

Double Edit: I assumed we were trying to avoid reordering the callbacks, but if not, Jabor probably has the simplest solution conceptually.

KillHour fucked around with this message at 05:48 on Feb 3, 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
Well, I've made a pleasant discovery: if you pass an `object` into a function, that function can get its name via object.GetType().Name. So I can use that (or rather, its hashcode) to enforce ordering, without having to change the signature of the Subscribe method.

Otherwise, I think we've covered all the various remotely sane ways to impose order internally. Thanks for the assistance, folks!

TooMuchAbstraction fucked around with this message at 18:09 on Feb 3, 2022

chglcu
May 17, 2007

I'm so bored with the USA.

TooMuchAbstraction posted:

Well, I've made a pleasant discovery: if you pass an `object` into a function, that function can get its name via object.GetType().Name. So I can use that (or rather, its hashcode) to enforce ordering, without having to change the signature of the Subscribe method.

Otherwise, I think we've covered all the various remotely sane ways to impose order internally. Thanks for the assistance, folks!

Didn’t see it mentioned, but you could also create attributes that specify dependencies and get those from the type and use them for ordering.

Minorkos
Feb 20, 2010

Anyone have experience regarding what the best way to clean up an old Unity project is? I have a project that I want to use as a base for my new project, but I don't want to build on top of it with all the old vestigial files it has accumulated, as the project is like 3 years old.

I was thinking of creating a blank new project and import scenes into it while fixing any dependencies, but I don't know if there is a much easier way

Adbot
ADBOT LOVES YOU

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 have a report from one of my Linux playtesters that they're unable to use the mouse to freely look around (I have a standard orbital camera that's controlled by the mouse). Specifically, they're saying that they can rotate some, but eventually the camera stops moving. The game works fine with a gamepad. It sounds to me like there's something wrong with how Unity locks the mouse cursor on their operating system, so the mouse is hitting the edge of the window and then not being tracked any more.

Does this sound plausible? How would y'all recommend fixing it? There's evidently some way to reset the mouse cursor using Win32 forms DLLs, but I have no idea if that works on Linux properly.

In any case, I'm kinda shooting in the dark here. I should probably ask them to send in a feedback report so I at least know what their specific setup is...but regardless of that information, I don't have a Linux setup to test on.

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