|
Does anybody know how to work with FPlatformFileManager in Unreal Engine 5.x? I'm trying this and platfile is null: code:
In 4.x, you'd initialize FPlatformFileManager using a static singleton: FPlatformFileManager::Get() but that's been deleted.
|
# ? Jan 31, 2024 09:29 |
|
|
# ? May 27, 2024 04:00 |
|
The ::Get method still seems to be there in the 5.x docs? What makes you think it's deleted?
|
# ? Jan 31, 2024 12:36 |
|
Jabor posted:The ::Get method still seems to be there in the 5.x docs? What makes you think it's deleted? Visual Studio highlighted it as invalid and the hover-over stated it had been "deleted." I suppose I could have been a manly man and tried to compile it anyways.
|
# ? Jan 31, 2024 16:20 |
|
Do you have the engine source downloaded? I spend quite a lot of time looking directly at the source to see how the engine uses its features. e: Oh, I think I might know what’s wrong: Get() returns a reference, and you need to store it as a reference. I’m not at my work computer so I can’t check, but I would bet that what’s been deleted is the copy constructor. blastron fucked around with this message at 18:46 on Jan 31, 2024 |
# ? Jan 31, 2024 18:44 |
|
And yeah Visual Studio will hallucinate syntax errors with Unreal so compile anyways.
|
# ? Feb 1, 2024 01:00 |
|
Ahh I guess I forget about returning references. I just never, never, never do it. So this compiles: code:
Edit: In source-level debug, I saw it was trying to match the path I was using to modules. I thought that was really strange. I don't really understand the objective there. Maybe to access collateral included in a module or something? It looks like if I use the parameterless version with the reference I am given from Get(), then I think I get the actual file system. I'm still messing around with it to make sure. Rocko Bonaparte fucked around with this message at 09:50 on Feb 1, 2024 |
# ? Feb 1, 2024 07:04 |
|
So I was having the damndest time figuring out the quirks of UE 5 file I/O. Videos do this-or-that that aren't entirely consistent and watching videos for that is just annoying anyways. My work has a Chat GPT license so I wrote up a prompt to demonstrate how to do it in UE5. I don't have the exact prompt here, but I asked it to check for a directory, create it if it doesn't exist, write a file with "Hello World" into that directory, then open the file again and print the contents to the log. So after a bunch of hemming and hawing, I get this:code:
Outside of thinking I need to mention this in the Tech Nightmares thread: 1. Yesterday, I was trying to use FileExists instead of DirectoryExists and that was returning false for a directory I created. So the distinction is really important. 2. I'm trying to understand the significance of the leading slash in the paths. It seems important because when I wasn't using that, I was having some kind of grief with paths. According to the Unreal Source Discord, you need that slash because ProjectDir doesn't have the trailing slash and winds up just concatenating the names instead of paths. I don't know if I'm convinced because when I step debugged, it looked like at least a path concatenation operation tried to run. Now, it could have decided to just glue the text together, but I'd have to restore the old code to be sure. 3. My wife has decided I'm out of a job now and I should just start farming.
|
# ? Feb 2, 2024 09:10 |
|
1) Yeah, that seems like a semantic difference between the POSIX/unix centric idea of the filesystem and the DOS/Windows idea. While Unreal is pretty good about being cross-platform friendly, its philosophy tends to skew to Windows-focused. In the UE3 days there were DWORDs and BYTEs all over the codebase. 2) I wouldn't be surprised if FPaths::ProjectDir() returns a path-style object (I don't have engine source in front of me at the moment), and i bet concatenating two paths works as expected. Looks like your/ChatGPT's code is concatenating the string literal to the path object, which I'm guessing just does string concat to support something like adding an extension to a filename. 3) Actually writing code is a pretty small part of my job. I'm not confident LLMs will be able to do that consistently well for quite a while, but even if they do: you still, largely speaking, wrote that program. You wrote it in a different language with a buggy transpiler, but you still had to tell it what to do, it just knew the API reference, sorta.
|
# ? Feb 2, 2024 09:26 |
|
this is a long shot but i know there's a lot of smart people in here, so here goes: i'm trying to make a function to multiply two q7.8 fixed point numbers in godot's gdscript (don't ask) and every example i find of this online uses programming languages where you can limit the number of bits of your integers, so for this example this would be something like (int_32)(int_16 a * int_16b) >> 8 however in gdscript all integers are 64-bits and i'm not really sure how to deal with this. my naive implementation was simply (a * b) >> 8 where a and b are both (artificially) limited to 16 bits and this works great for positive numbers whose multiplication never exceed 32 bits but breaks down completely with bigger/negative numbers for example with this method if i multiply 1.6 by 3.2 i get 5.12 (good) but if i multiply 1.6 by negative 3.5 i get a number larger than 16 bits and chopping it off doesn't work 1.6 * 3.2 is 0x019A * 0x0333 = 0x051F (correct) 1.6 * -3.2 is 0x019A * 0xFCCD = 0x184E0 (incorrect) the result i'm looking for should be 0xFAE0 so weirdly the fraction is correct but the whole number part is mangled. anyone?
|
# ? Feb 4, 2024 14:19 |
|
Your Computer posted:i'm trying to make a function to multiply two q7.8 fixed point numbers in godot's gdscript (don't ask) and every example i find of this online uses programming languages where you can limit the number of bits of your integers, so for this example this would be something like (int_32)(int_16 a * int_16b) >> 8 code:
|
# ? Feb 4, 2024 14:35 |
|
Why are you partaking in witchcraft in these most holy of places!?
|
# ? Feb 4, 2024 14:36 |
|
i'm even more confused because it seems like the resolution isn't the problem here? i busted this out on a calculator and indeed i get 194E052 which is a perfectly fine 32-bit number and does contain the EO but not the FA that i expect. so it feels like there has to be some special case to handle negative numbers? but i can't find anything by googling - heck even the wikipedia article on fixed point arithmetics says "To multiply two fixed-point numbers, it suffices to multiply the two underlying integers" but this clearly isn't producing the right result...! my only sanity check is the game boy code that i know works, and the multiplication routine i used there is all sorts of unholy wizardry since it does this multiplication on an 8-bit system. but it does produce the right results so i have something to compare to Raenir Salazar posted:Why are you partaking in witchcraft in these most holy of places!? i'm doing terrible crimes and i walk willingly into hell
|
# ? Feb 4, 2024 14:45 |
|
not up for real bit twiddling atm, but for negative numbers at least, seems like you could calculate the sign and magnitude of the result separatelyPython code:
|
# ? Feb 4, 2024 14:50 |
|
I do kinda shudder a little at what real world circumstance prompts needing to do bit fiddling, especially in game dev, remember this?code:
|
# ? Feb 4, 2024 14:53 |
|
Grace Baiting posted:not up for real bit twiddling atm, but for negative numbers at least, seems like you could calculate the sign and magnitude of the result separately Raenir Salazar posted:I do kinda shudder a little at what real world circumstance prompts needing to do bit fiddling, especially in game dev i posted about it in the thread previously but i made a lil' pinball collision engine in game boy assembly and as a fun little project i'm working on porting that as closely as possible to godot, i.e. still using 16-bit fixed point integers instead of floats etc.
|
# ? Feb 4, 2024 15:01 |
|
If you try and take my binary operators away from me, why I'll rotate your bits so hard you'll be XORing trinary for the rest of your shiftless existence.
|
# ? Feb 4, 2024 15:07 |
|
That said, their use should definitely be contained to well-tested, isolated regions of carefully crafted spicy shenanigans.
|
# ? Feb 4, 2024 15:10 |
|
ynohtna posted:That said, their use should definitely be contained to well-tested, isolated regions of carefully crafted spicy shenanigans. Out of curiosity what are some coding crimes you've done with them? It's always amazing what sort of really spicy performant code that comes out of stuff.
|
# ? Feb 4, 2024 15:15 |
|
yeah okay i decided i needed someone way smarter than me to look at this and the only place i know of with experts on this sort of thing is the game boy dev discord server. i didn't wanna just barge in there and ask about a non-game boy related thing but i was desperate within minutes someone helps me solve it code:
for good measure they also gave me another way to solve it like so code:
|
# ? Feb 4, 2024 17:02 |
|
Oh, right, sorry, I missed that it was signed int16s.
|
# ? Feb 4, 2024 17:46 |
|
Raenir Salazar posted:Out of curiosity what are some coding crimes you've done with them? It's always amazing what sort of really spicy performant code that comes out of stuff. I swear, as an old from the time of bit-plane video (pain!) and floating point being an additional processor, who has done far more low-level MIDI and audio work than is sensible, that I have only ever followed orders and the rules of engagement of the time. Tagging aligned pointers by using the unused bits is a trick that never gets old (but that detail must never ever leak beyond an implementation barrier). As does packing data as tight as possible into platform size words so atomic compare-and-swap can be used for inter-thread communication instead of more complicated mechanisms. Floating point tricks for clamping, square roots, saturation or fixing denormalized numbers come out of the toolbox occasionally. I'm easily dazzled by blinky things, though, and get a simple kick out of XOR. I'm literally coding up a munching squares variant ((x ^ y) < t) to trigger dumb synthesizer stuff this weekend!
|
# ? Feb 4, 2024 18:02 |
|
ynohtna posted:munching squares variant ((x ^ y) < t) I'll be stealing this tyvm
|
# ? Feb 4, 2024 20:12 |
|
Your Computer posted:for good measure they also gave me another way to solve it like so The most reliable way to do sign extension of a 16-bit number (assuming it's already in a signed type larger than 16 bits) is just code:
OneEightHundred fucked around with this message at 21:06 on Feb 4, 2024 |
# ? Feb 4, 2024 21:01 |
|
Raenir Salazar posted:Out of curiosity what are some coding crimes you've done with them? It's always amazing what sort of really spicy performant code that comes out of stuff. Not really performant, but: I used to always use bit fiddling for annoying boolean logic checks (for MUDs/rpgs). So you could flag someone as having finished certain checkpoints by giving them some integer PLOT variable, and having a series of values of powers of 2 for each thing they need to check off the list. So instead of having a huge block of if(finished_part_1 && finished_part_2 && finished_part_3_good_ending && && && && && etc) you could just make a variable ALL_CHECKPOINTS_GOOD_OUTCOME (which would be like 10001110101110011, each '1' here being a flag that you set when they did the thing), and you just compare it to their PLOT var. If they have the bits in the right places then they did the thing and you can proceed. It's basic stuff but back in the 90s that blew my mind.
|
# ? Feb 17, 2024 10:19 |
|
Kaedric posted:Not really performant, but: I used to always use bit fiddling for annoying boolean logic checks (for MUDs/rpgs). So you could flag someone as having finished certain checkpoints by giving them some integer PLOT variable, and having a series of values of powers of 2 for each thing they need to check off the list. So instead of having a huge block of if(finished_part_1 && finished_part_2 && finished_part_3_good_ending && && && && && etc) you could just make a variable ALL_CHECKPOINTS_GOOD_OUTCOME (which would be like 10001110101110011, each '1' here being a flag that you set when they did the thing), and you just compare it to their PLOT var. If they have the bits in the right places then they did the thing and you can proceed. That's very interesting, I haven't yet really had a chance yet myself trying to tackle that problem of how to track story progression and that's a very interesting one. But how scalable is that? I assume you're limited by the total number of bits? You could probably use an arbitrarily sized array and depending on the language maybe you can do a similar check. It doesn't seem super readable to me though, I wonder what the other solutions for that people have come up with.
|
# ? Feb 17, 2024 16:52 |
|
Raenir Salazar posted:That's very interesting, I haven't yet really had a chance yet myself trying to tackle that problem of how to track story progression and that's a very interesting one. But how scalable is that? I assume you're limited by the total number of bits? You could probably use an arbitrarily sized array and depending on the language maybe you can do a similar check. It doesn't seem super readable to me though, I wonder what the other solutions for that people have come up with. for linear progression, you need log bits. which is why metroid prime only uses one save block packed structs arent that hard to read or work with, really.
|
# ? Feb 17, 2024 17:57 |
|
leper khan posted:for linear progression, you need log bits. which is why metroid prime only uses one save block I mean more from a broader architectural perspective, i.e patterns like for an RPG. For questions like, who is responsible for keeping this information, how to pass it around and access it in a "Clean" way, maybe I wanna do something a bit complication and OOP based where maybe I maintain "Progression" differently for different aspects of the game, maybe the system that tracks what a NPC remembers you doing/saying is different from the system that tracks if you reached a certain area and is different from the how the overall story is saved/progressed (i.e through some sort of graph/node network) and then there needs to be system or manager that manages and keeps track of all this while keeping/maintaining enough like commonality for easy mocking and unit testing etc so adding a new type of quest doesn't brick everything else without warning you first.
|
# ? Feb 17, 2024 18:24 |
|
i think everyone's more or less on the same page here but: you'd defininitely want to apply it tactfully but i think some basic twiddling is still pretty applicable in a lot of cases (and also not a lot of cases) and still worth considering for some games today things like older FF games might have for example a buff bitfield thats however many bits you need for blind/petrified/etc and each character/monster has its own copy of that bitfield, and also for characters it'd be saved so you can come back later and walk around with poison slowly killing your party. or for tracking which megaman bosses you killed, you just need the 8 dead or not bits. for a more complicated buff system this may be too simple on its own but you can build a system of timers etc around it, or have a battle system know how to deal with actors that have the field, or just use a different data structure entirely really. i guess more often nowadays you'd just throw a BuffComponent on an entity in c# ime with its flag enums its not the worst for reading/later understanding purposes and gives a bit more of an interface as well: C# code:
this follows standard programming procedure for optimizing things and what youre comfortable with, and it is also more trouble than its worth for a lot of things ityool 2024 than it was in 87 when it was necessary when developing metroid. (which btw, if you want to see how they tracked the whole game in 128 bits for its password system this has some info) also you can run into them a lot in some interfaces and sometimes you just gotta deal with it, a simple example being windows modifer keys . its just a solid and classic way to do this kind of thing too even if you dont have reasons to do advanced twiddling and easily dealt with in whatever environment i think what im trying to get at writing all this is that some bit twiddling can still be handy to have for critical data and still have managers, even a light one like the C# flags, around these bits if you want better maintainability and still be able to get to the bits if you do need them; its also a wildly available option across every (most?) languages/frameworks/paradigm/platform and not always just an ambitious optimization or arcane ritual in summary i like bit flips and i cannot lie u other coders cant deny bobthenameless fucked around with this message at 08:10 on Feb 18, 2024 |
# ? Feb 18, 2024 07:58 |
|
you dont need to mark explicit numbers in a flags enum [except for on None]
|
# ? Feb 18, 2024 15:03 |
|
sure, also probably worth noting that HasFlag used to be much worse for performance in the dotnet framework days but is much faster now and closer to a bitwise op since Core 3 at least.
|
# ? Feb 18, 2024 19:01 |
|
I'm cross posting because I'm still mad about it and I want to complain againKillHour posted:: "I finally finished implementing enough of a DX12 pipeline to start testing"
|
# ? Feb 18, 2024 20:12 |
|
leper khan posted:you dont need to mark explicit numbers in a flags enum [except for on None] Yes, you do, otherwise you'll get the wrong behaviour when using them as flags. code:
code:
Red Mike fucked around with this message at 21:13 on Feb 18, 2024 |
# ? Feb 18, 2024 21:10 |
|
Kaedric posted:Not really performant, but: I used to always use bit fiddling for annoying boolean logic checks (for MUDs/rpgs). So you could flag someone as having finished certain checkpoints by giving them some integer PLOT variable, and having a series of values of powers of 2 for each thing they need to check off the list. So instead of having a huge block of if(finished_part_1 && finished_part_2 && finished_part_3_good_ending && && && && && etc) you could just make a variable ALL_CHECKPOINTS_GOOD_OUTCOME (which would be like 10001110101110011, each '1' here being a flag that you set when they did the thing), and you just compare it to their PLOT var. If they have the bits in the right places then they did the thing and you can proceed. With the context of crimes: I did hundreds of these booleans, labeled it as ascii, and dumped them in a blob column in the database. It worked perfectly because their suggested alternative was having hundreds of columns, with even more story flags being made willy-nilly.
|
# ? Feb 18, 2024 21:25 |
|
Red Mike posted:Yes, you do, otherwise you'll get the wrong behaviour when using them as flags. what a garbage language why
|
# ? Feb 19, 2024 13:57 |
|
Because all [Flags] does is change the ToString method on the enum (or rather the ToString knows to check for it), and enable a couple code inspection warnings in a compatible IDE. You could use normal enums and have them act the same as a flags one, but you'd end up with confusing ToString behaviour when you combine flags (unless the combined value maps to an existing name). It gets more fun when you realise that you can have multiple names that point to the same value (see HttpStatusCode that has Moved = 301 and MovedPermanently = 301), and that evaluating equality between them gets confusing quickly. There's a reason I said it just saves so much sanity to keep enums simple, explicit, and expressive, and not rely on any built-in handling.
|
# ? Feb 19, 2024 14:09 |
|
I've been tooling around with starting a loose board game adaptation using Godot, but past the opening stuff (taking some hex based code and adapting it to move pieces around) I'm a little intimidated by how to organize a turn based game with Godot. Does anyone have recommendations on how to structure that kind of program?
|
# ? Feb 19, 2024 17:57 |
|
StashAugustine posted:I've been tooling around with starting a loose board game adaptation using Godot, but past the opening stuff (taking some hex based code and adapting it to move pieces around) I'm a little intimidated by how to organize a turn based game with Godot. Does anyone have recommendations on how to structure that kind of program? sure. build the program independent of the presentation layer. then have the presentation read and modify your state through its API
|
# ? Feb 19, 2024 20:13 |
|
Yeah, the underlying game will have a state, and a set of valid actions (functions) which modify that state. Those actions correspond to moves/turns that players can make. The game should update to the new state instantly in response to the functions being invoked. The display layer is responsible for turning the user's input into function calls, and for updating the displayed game state to match the underlying state.
|
# ? Feb 20, 2024 05:14 |
|
Raenir Salazar posted:That's very interesting, I haven't yet really had a chance yet myself trying to tackle that problem of how to track story progression and that's a very interesting one. But how scalable is that? I assume you're limited by the total number of bits? You could probably use an arbitrarily sized array and depending on the language maybe you can do a similar check. It doesn't seem super readable to me though, I wonder what the other solutions for that people have come up with. You are limited by bits, but that just takes organization (by splitting up conceptual flags into different variables). I will agree that the idea is not inherently easy to understand, but I will argue that it is definitely readable in comparison to managing flags/state via booleans. There are probably several clever ways to deal with flags/state out there but I don't know them, so I'll just talk what I know Let me show a brief example of a naive boolean flag management. Whether these variables are tucked away in an array/struct/whatever is just set dressing, you're still accessing them directly to discover their value: code:
Something similar but with bitfiddle (don't @ me about using int, you can use whatever, some languages have more options here): code:
|
# ? Feb 21, 2024 08:58 |
|
|
# ? May 27, 2024 04:00 |
|
an example of this i've worked with in the past is skills for an mmorpg. this skill "can target the ground" and "has an area of effect" and "is a trap" and "ignores defense", and so on. it's easy to rack up dozens of these and cramming them into a single "battle flags" integer and unpacking it is pretty ergonomic as far as mmorpg code goes
|
# ? Feb 21, 2024 09:44 |