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
jizzy sillage
Aug 13, 2006

Does anyone know a rough and easy "importing JSON into Unity" guide?

I've got something working that will create Unity objects from data in a JSON file, but I'd like to have many objects in one file and turn those into a List<> of said objects.

edit: reading more, this seems like a more complex question than I'd originally thought, and people have made paid assets that solve it? I think this is a problem to come back to when I've learned more C#.

jizzy sillage fucked around with this message at 03:10 on Dec 19, 2018

Adbot
ADBOT LOVES YOU

jizzy sillage
Aug 13, 2006

Monoclinic posted:

I was working on this issue myself recently. Unity has a built-in JSON serializer, but I couldn't get that to work with my JSON file. Instead, I just used the free JSON.net for Unity asset (https://assetstore.unity.com/packages/tools/input-management/json-net-for-unity-11347). My JSON-parsing code was this:

code:
    void ReadJSON()
    {
        stuffDataPath = Application.streamingAssetsPath + "/stuff.json";		// set the path of the JSON file
        using (StreamReader r = new StreamReader(stuffDataPath))			// create a new StreamReader and point it to the JSON file
        {
            JsonSerializer serializer = new JsonSerializer();				// create a new JSON serializer
            stuff = (List<Stuff>)serializer.Deserialize(r, typeof(List<Stuff>));	// invoke the reader to deserialize the JSON file into the elements list
        }
    }
This requires use of System.IO and Newtonsoft.Json namespaces. As long as your Stuff object has properties that match the names of the fields in the JSON file, it will populate the list with the objects you have in there. In my case the JSON file was wrapped with [ and ], i.e. the whole thing was an array of json objects.

Okay, rad, I'll give it a shot later. Thanks very much.

jizzy sillage
Aug 13, 2006

Yeah, uh, holy poo poo. I only half learned what serialization even is today, so all of that is a long way down the line.

I have a JSON file that defines a bunch of items. I want to import that file, read it, and create a List<> containing those item definitions. I'd like the player (me) to be able to add new items to the bottom of the JSON file (while the game is closed) and have those then get added to the List<> of available items when the game is opened.

Currently the game doesn't exist, I'm just practicing a few different solutions to features I'd like to include (this one being the ability to add new items manually).

jizzy sillage
Aug 13, 2006

Wow, that's cool! Turns out I was getting pretty close to that solution, so thanks very much for laying it out :)

jizzy sillage
Aug 13, 2006

Is there a goon gamedev discord where I can ask short and stupid questions, like this one?

jizzy sillage
Aug 13, 2006

Great, thanks. I've joined, and will start asking stupid questions post haste.

jizzy sillage
Aug 13, 2006

And Unity is a C++ engine with a C# wrapping, right?

jizzy sillage
Aug 13, 2006

I'm doing a Bachelor of Software Engineering for games and that GDD would have failed our first year, first semester paper on game design.

Sorry bout it.

jizzy sillage
Aug 13, 2006

Since I was a dick in my last post I'll write something a bit more useful.

When I was younger I thought Game Idea Man was an actual job, probably from seeing things like "Sid Meier's Civilization" and assuming he was the guy with the plan and everyone just did what he said, like a god delivering fully formed games from on high to the unwashed masses.

I tried a few times to write out game concepts. I tried a few times to learn coding, art, and other things I thought I would need to make just enough of a game that an angel investor would throw money at to see it made reality.

Then I met a guy who also wanted to make games, and had ideas, and also knew some code. We talked and decided on a concept, and I wrote a terrible GDD for him to code from. I promised I'd learn to code and then I could help him. At last I was the ideas guy.

The project sucked. His code sucked, mine sucked worse. My GDD was guaranteed worse than yours. It was unfun. Nothing got made. He'd choose and design a system at random and show it to me in a whitebox environment. Eventually he got sick of me telling him that you couldn't just buy 20 different plug n play system assets from the Unity Store and Lego your way into a cool game, and said he wanted to work on it alone.

I left him to it, and later started going to the University I'm at now. Best decision of my life. Now I have a measure of all the things I don't know. I'm more grounded in reality. I don't have a billion dollars to hire a team to make my game, so I'm learning how to code and design games so I can get a job in industry, and continue to learn. Maybe one day I'll start my own studio and then I can make a zillion bucks off the next Minecraft and become an incel lunatic like Notch, but until then I'll learn and I absorb as much information as I can from people who actually know what they're talking about.

You seem somewhere around paragraph 2 of my journey. You can skip several painful steps if you listen to the advice of these guys who are already making games for a living. They could, but probably won't teach you how to code, or do art.

They can tell you ten different places where the path begins, but walking that path is up to you.

PS. That other ideas guy I met is still an ideas guy.

jizzy sillage
Aug 13, 2006

You could store the entire plan, and test the current action for viability. If the current action needs to change, go back and redo the plan.

jizzy sillage
Aug 13, 2006

So first I'll ask, in your Action class, do you have a function that is run by the planner to check whether this Action is a viable one? From HappieCat's GOAP project:

code:
// check what actions can run using their checkProceduralPrecondition
HashSet<GOAPAction> usableActions = new HashSet<GOAPAction> ();
foreach (GOAPAction a in availableActions) 
  {
    if ( a.checkProceduralPrecondition(agent) )
      usableActions.Add(a);
  }
Writing this function for each of the Actions your agents may take is important. It turns an action from a dumb list of preconditions and effects into something that's a bit smarter. build_thing knows what it's building, right? It has a target, the thing it wants to build - a house, maybe:

code:
build_thing.checkProceduralPrecondition(agent)
{
  return resourceDepot.Find(target.requiredResource);
}
You can make States (the bools that are named and toggled on or off) smarter if you need to as well - or you can create and destroy them dynamically, along with their preconditions and effects. They don't need to just be bools. You could, every frame, sort through and add an Action to the Actor's list of available Actions for every type of thing you can build:

build_thing(house, wood)
build_thing(house, stone)
build_thing(pathway, dirt)

Then cull the list according to what resources exist on the map. You could even do this outside of the Actor, in a BuildingManagementDatabase or whatever, that tells all Actors of type Builder "Here are your available build options this frame. Request a plan from the planner."

Nolgthorn posted:

But I still don't know which is the best choice because I don't know how far away the actor is from any of these crates. The actor could be anywhere, assuming that more actions could be queued before this one.

Why can't you check this? The Actor should be aware of where it is, and where its target is. Are you not running your AI every frame? If you run it every frame, it would know if it or the target moved. If you don't want it to run every frame, you need error checking in the Action itself - "when I reached the wood pile, there was none left. I have to request a new plan". What happens when the Actor has its plan interrupted? What if its goal changes?

Nolgthorn posted:

In the example it was checking the state "door_closed" which is a nonsensical boolean state that doesn't seem to indicate which door it's supposed to be looking at.

When the Actor decides to move somewhere, it needs to call a pathfinding method to find a path there, right? Why not have your pathfinding method return a list of all closed doors in the path, and then store that in the Actor?

Hopefully this helps somewhat, GOAP isn't especially easy and I haven't yet finalised/finished my first implementation of it. Good luck!

jizzy sillage
Aug 13, 2006

KillHour posted:

Just keep in mind that you will have to traverse the cost tree similar to pathfinding every time you need to make a decision, so it can become computationally expensive.

All the examples I could find used a progressive search through the tree for the planning algorithm, which is SO BAD. Nolgthorn, I think you mentioned you wrote one that starts at the end, which is good. If you start at the 50 possible actions you have, it's some bonkers huge number of dead end plans. If you start at the end, with the 3 of those 50 actions that actually lead to the goal state, you have a slightly less huge number of plans.

I'm sure someone who knows complexity notation could do the math but I was not paying attention in class that day.

jizzy sillage
Aug 13, 2006

Plus you'll need something to pass out goals to the agents rather than them self-selecting, or you'll get 50 agents all running over to build the thing, or snatching the last of a resource before another guy who needs it arrives.

KillHour posted:

The direction you traverse the tree probably doesn't matter in the long run. If the impossible step is the last one, going backwards is faster, but if the impossible step is the first one, forwards is faster. It likely averages out.

Ah, mine is a turn based tactical game. There's always a valid option for each of my goals, it just sucks. If they can't shoot, they'll punch.

edit: ...does that mean it's still 50/50 on whether it's faster forwards or backwards? gently caress, lol

jizzy sillage fucked around with this message at 06:48 on Aug 7, 2020

jizzy sillage
Aug 13, 2006

TheHoosier posted:

That did it. Thank you. I knew it was something really simple. I had it in my head that expPos would recalculate each time Instantiate was called, for some reason.

The vars you set up stay the same between yields, so it doesn't recalculate. If you instantiated a new copy for a new boss, it'd have a different expPos but it would be the same for each of its loops.

jizzy sillage
Aug 13, 2006

In Unreal you can do a dithering effect which is rendered with opaques (ie. not on the transparency layer), I guess you could look into doing that in Unity. Then you'd just enable dithering with a different level of extremity for more or less 'ghostly' ships.

jizzy sillage
Aug 13, 2006

CodfishCartographer posted:

Wound up solving my normalization problem: I simply reduced the max speed when both a horizontal and vertical button are held. Had to use MATH to do so: squared the original maxSpeed and then doubled it to get maxSqr - then took the square root of that and halved it to get the newMaxSpeed, which I used instead. Classic A2 + B2 = C2, but since it's being added on twice (once each for both horizontal and vertical) I had to halve it. MATH!

This was a great watch, thanks!

You could have just normalized your input, right?

code:
Vector2 input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")).normalized;
Gamepad inputs from sticks tend to come already normalized (or near enough) so if you have gamepad support you won't run into weird issues with your normalized max speed being applied to a normalized input.

jizzy sillage
Aug 13, 2006

Yeah if you're using OnCollisionEnter it can't retrigger on the same object until it's done OnCollisionExit, so I'd manually linecast. Manually linecasting means you could also do it 10/20 times a second instead of on Update/FixedUpdate (if performance is an issue).

jizzy sillage
Aug 13, 2006

yeah if you're 20,000 units away from origin you're gonna start seeing fpp jitter

jizzy sillage
Aug 13, 2006

lord funk posted:

Yeah this is so, so finicky. Like, you can't even leave the armature named 'Armature'. That magically breaks it (I'm not joking).

https://github.com/xavier150/Blender-For-UnrealEngine-Addons

There's still some stuff you need to slowly learn how Unreal 'wants it' but afaik for root motion it expects the root bone to be named "root". Otherwise this Addon will error check the Export for you and fix the scaling and the front axis and all the other semi-finicky things.

jizzy sillage
Aug 13, 2006

Yep, TSoftObjectPtrs need to be loaded to be used - and they need to be checked to ensure they're loaded every time you want to use one, because they can be unloaded at any time.

They're mainly useful for preventing huge dependency chains in your project, where a lamp references a room which references a level which references fifteen different characters and eighty decorative actors, each which have a set of 1-4kish textures and some reference Niagara VFX, etc etc etc, meaning you can't use that lamp in a different level without loading all that other poo poo into memory.

Those dependency chains happen when you use a TObjectPtr instead of a TSoftObjectPtr.

https://youtu.be/4-oRyDLfo7M

jizzy sillage
Aug 13, 2006

Depends where the Load call is being made - in a constructor, must be synchronous; elsewhere, can be async.

Edit: I'm not up to date right now on exactly how those calls are made and work, they might have different usages - so LoadObject might return a bool but LoadSynchronous might return the pointer for example. You'll need to do a bit of exploration there.

jizzy sillage fucked around with this message at 00:42 on Jan 29, 2023

jizzy sillage
Aug 13, 2006

Yeah for an input mapping context, a TObjectPtr should be fine. It's only loading a small amount of data. If you're gonna be referencing a skeletal mesh, which could be referenced by an animation blueprint, which in turn could reference 50 animations, then you need to start thinking about things a little differently.

Also anywhere you use a raw pointer like that, you can (should) replace it with TObjectPtr to get some nice garbage collection and other safety features.

jizzy sillage
Aug 13, 2006

UE has tons of tutorials, examples, sample projects, online learning videos, and everything else Unity has. Not sure if it specifically has a complete tutorial to make a small puzzle game like that from start to finish, though.

Edit: https://dev.epicgames.com/community...st-things-first

jizzy sillage fucked around with this message at 22:52 on Jan 30, 2023

jizzy sillage
Aug 13, 2006

Alterian posted:

Unreal has the robot tutorials.

Oh yeah, I forgot about Stack-o-bot.

jizzy sillage
Aug 13, 2006

Try the dumbest solution first (or the first one your brain summons, usually the dumbest, natch) and then when it doesn't perform good, make it perform gooder or do the second dumbest solution. Repeat until release day.

Ihmemies posted:


I gave a look at the gameobjects and having every single piece of road, every building etc. to be a gameobject feels like the Unity editor would just crash even if I tried :v:

Try it. It won't.

jizzy sillage
Aug 13, 2006

Rendering is done by batching objects, and running them through a culling algorithm. If you have building A, B, and C, and each building is rendered using a 4k texture for color, one for normal map, and one for AO/Roughness/Metallic, that's 9 x 4k textures.

Then you ask the engine to render 25,000 of each building. It loads those 9 textures into your graphics card and draws the buildings using the appropriate textures for each of the 75k objects.

But some of those buildings are culled - the buildings in front block the view of the ones behind, a bunch aren't even in the camera frustum, etc. So really you end up drawing maybe 1,500 of them, using the same 9 textures.

If you want to know what Unity can do, Cities Skylines was made with Unity.

edit: also I haven't explained mipmaps either which are calculated by Unity for you and are a memory saving feature.

jizzy sillage fucked around with this message at 11:54 on Feb 4, 2023

jizzy sillage
Aug 13, 2006

Well you can either have a giant texture that you need to modify in-place (requires you to write all sorts of poo poo to modify the texture directly which isn't hard but also isn't fun), or you could create a 2D sprite for "Hospital", "Small House", etc, and then just render however many you need at whatever x,y coordinate it lives at.

Computers are fast as gently caress bro, try it and see how many it can render before you start to lose frame rate. It'll be a ton more than you think.

jizzy sillage
Aug 13, 2006

Yeah I have a ton of experience with Unity and Unreal Engine game dev and I'd still start this project by building "Cube Clicker 2000" where you click a spot and a cube appears there.

- Then add different shapes or colors of cubes.
- Then clamp their positions to be on a grid.
- Then make it so that when you add yellow cubes, yellow desire meter goes down and green meter goes up.
- Then click a bunch of grey cubes in a row and have them automatically flatten out into flat grey cubes (roads).
- Then click and drag to draw the lines of grey cubes.
- etc.

Learning how to do the stuff I've written above is a day or two worth of work for my students (some of whom are second year CS students at University).

Edit: https://youtu.be/kMA0PG8Q8n0

jizzy sillage fucked around with this message at 12:29 on Feb 4, 2023

jizzy sillage
Aug 13, 2006

Raenir Salazar posted:

Does anyone happen to know if in Unreal if "Game Instance" is loaded after all of the PostWorldInitialization calls?

As my colleague always says, F12! (Control + B in Rider). Also you could just print a debug line in both GameInstance constructor and PWI and see which prints first.

jizzy sillage
Aug 13, 2006

Raenir Salazar posted:

Sadly it's not that simple since at work we have like 50 modules and I've been tasked with refactoring some code to be less tightly couples and I think for the observer pattern ideally I should be passing a reference to the subject of all of the observers that will be watching it? And I'm trying to find a spot that would be persistent between levels.



Seems to indicate the GameInstance is created and initialised first.

Edit: though on closer inspection it mentions UWorld Start but not the UWorld init.

For observer you'd be using delegates and binding to them in every other relevant place right?

jizzy sillage fucked around with this message at 23:10 on Feb 8, 2023

jizzy sillage
Aug 13, 2006

Raenir Salazar posted:

Yeah that last part is where I'm a little confused.

Problem:
We have a settings menu that is managing the internal state of various I suppose I'll call them "Models" so the Settings Menu is calling methods like ChangeCameraSpeed on our SettingsManager.

Example:
code:
void MySettingsMenu::HandleOnCameraSpeedSliderChanged(float InValueChanged) 
{
     MySettingsManager->ChangeCameraSpeed(InValueChanged);
}
My understanding is that this is an example of tight coupling; normally for smaller programs this isn't a big deal, but in larger projects the SettingsMenu directly changing the in game settings can introduce hard to trackdown bugs.

The solution as I understand it: Use the Observer pattern, which in Unreal is/can? implemented by using Delegate/Events. Instead of the IObserver/ISubject boilerplate which I see on C++ Websites?

However, while we do have an EventManager class that contains something like 95% of our games delegates, but it's also 1,000 lines and to use events for all the methods the Settings Menu currently has would probably add another 15 events; and if more parts of the game need similar refactoring I think it'd be better if we didn't continue to bloat this single "Superman" Event class?

So if I want to avoid using this global event class, I just create the delegates for the Settings Menu; and then broadcast; but then the Settings Manager, in order to subscribe to these events, would still need an include and thus needs to still "know about" the Settings Menu class right? Is that normal?

Am I overthinking this and is it fine for the "Observer" in this case to know about the thing it wants to Observe? In general when googling/researching design patterns I get that there's like a hierarchy of concerns of when it is or is not called for but I'm not sure how to judge/determine this.

In the case of SettingsMenu making changes that only SettingsManager needs to know about, the coupling is okay - as long as the SetMan isn't watching for updates in its Tick. So if SetMenu only ever tells SetMan "Hey the player just updated their mouse sensitivity" then that's fine. You start to need Delegates (Unreal Engine Delegates) when you have a bunch of things all reliant on knowing certain things happened. Easy example is Player death.

Bad:

- Player dies
- EventManager watches on Tick for bIsPlayerDead = true, triggers something
- AudioManager watches on Tick for bIsPlayerDead = true, plays some audio
- Enemies nearby all check to see if player is dead, find new targets
- UI Widgets A, B, and C all watch and update.
- etc.

Good:

- Player dies, Broadcasts Multicast Delegate OnPlayerDeathDelegate
- EventManager is subbed to OnPlayerDeathDelegate, triggers OnPlayerDeath and records the stats, gives some achievements, whatever
- AudioManager is subbed, plays some audio
- Fifteen different enemies are nearby, subbed, get told the Player has died and find new targets.
- UI Widgets A and B are subbed, so they get the broadcast and update, but turns out C never needed to care so we just removed the binding in the UI Widget C.

The other aspect is that you're moving the code from one side of the equation to the other - instead of SettingsMenu calling SettingsManager->ChangeSensitivity(float newSense), now SettingsManager just binds itself to the delegate on construction and unbinds on death. Now in your SettingsMenu, you just blindly broadcast into the void "Hey a thing changed, anyone care? No? Cool." and it doesn't matter if nothing cared, or the SettingsManager hasn't finished Init, or there are five SettingsManagers of different types (one for Gamepad, one for KB+M) with different behaviours that happen when the broadcast is sent. By moving all the binding into the SettingsManager, it can bind to the Menu events, or it can bind to a system that Loads/Saves settings, or both, and you don't need the SettingsMenu and LoadSaveManager to have a reference to a SettingsManager.

Bit of a braindump but that might help a little?

jizzy sillage
Aug 13, 2006

Looks fuckin' whack to me. Are they trying to dereference mVertices?

jizzy sillage
Aug 13, 2006

Yeah that project sounds horrifying to work in. Introduce the team to the concept of delegates and event-based code and pray they don't make it worse while you disentangle the patch they've assigned you.

jizzy sillage
Aug 13, 2006

Raenir Salazar posted:

I love discovering that load bearing code not only doesn't work but apparently never worked, but instead it only pretended to work. This isn't my blood its victory wine.

Not only have you seen the man behind the curtain - you have become him.

jizzy sillage
Aug 13, 2006

Raenir Salazar posted:

As an aside, it's mind boggling to me that chatgpt is giving me better answers for questions I have about unreal than googling the same question.

It might be wrong or I correct on some level, but it's giving me a better idea than what I did before.

I love ChatGPT for rubber ducking. Always fact check the answer it gives you, but I've worked through a few difficult problems by saying "I tried that, it doesn't work. Can you give me another solution?" until it's exhausted its memory of StackOverflow.

Bing search and Edge are (can't believe I'm saying this) also getting pretty good. Summaries of articles, pdfs, etc. Pulling recipes out of 50 pages of lake trip memoirs so I don't have to scroll.

10/10 would not read about that time the writer made a hearty soup for her family while wintering at a chateau again.

jizzy sillage
Aug 13, 2006

...what have we done? Chuck all AI into the Sun, there's no going back from this.

jizzy sillage
Aug 13, 2006

Could you have a job (system?) that is something like HearGunfire, which:

- iterates over all entities with a Transform and a Hearing component
- iterates over all Gunfire + Transform components
- checks the distance, and
- if it's below a certain limit, add a FleeingGunfire component to that entity

I'm not super familiar with ECS specifically but in my exploration of Data Oriented programming this would be the approach I'd try.

jizzy sillage
Aug 13, 2006

ChatGPT: Trust, but verify.

jizzy sillage
Aug 13, 2006

Depending on the use case, I'd just set a cool down on how often the trigger can happen.

Adbot
ADBOT LOVES YOU

jizzy sillage
Aug 13, 2006

Rocko Bonaparte posted:

Anecdotally, how much code do you all put into just resolving collisions like this? Sure, Unity gives the raw logic for it, but how many layers do you wind up putting on top of it? Given what I've read on here and elsewhere about people having to extend it, I kind of expect that now from everybody.

When I'm teaching I usually tell my students to do the dumbest, simplest option first, and they rarely get to the level of polish where they're validating triggers/collisions, but I would try, in order of priority:

1. Not use physics if possible - if it's an 'interact', do an overlap on the button press event and check it in there.
2. Manually write a kinematic controller, resolve myself to living in edge-case hell until I've worked on it for months.
3. Set a timer on the trigger, check again when the timer is complete, if the object still overlaps/is in the trigger volume it might have been intentional.
4. Something else to do with reading player intent in their movement? Project the character velocity forward and ...?

Edit: also for collisions on a character, the collider should be as small as makes sense - usually ground to neck in height, radius matching torso width/depth, disincluding head, arms, etc.

Ranzear I saw recently a tweet I can't find about making boats float on water cheaply - four points on the corners of a plane, raycast down to hit the water's surface, solve for a plane that closest meets those four contact points. Could do something like that for land and tank tracks?

jizzy sillage fucked around with this message at 09:38 on Aug 3, 2023

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