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
blastron
Dec 11, 2007

Don't doodle on it!


The trick with space games is that the planets are so vastly far away (compared to nearby things like asteroids and other ships) that they're effectively part of the background. As such, you can render the scene in two passes: one pass in a scale model of the solar system, and one in a more typical, interactive scene. That way, you don't need to worry about having astronomical-scale draw distances.

e: God drat it the mobile app didn't load the rest of the posts for some reason, sorry for the redundancy

Adbot
ADBOT LOVES YOU

blastron
Dec 11, 2007

Don't doodle on it!


This is the dumbest possible thing to be happy about but after a day of scraping through UE4's source to find out how to use a whole bunch of stuff that is apparently only documented in an 80-minute VOD recorded off of one of Epic's livestreams...



I've spawned a viewport in a custom editor and this is the happiest I have been all week.

blastron
Dec 11, 2007

Don't doodle on it!


Here’s the industry thread: https://forums.somethingawful.com/showthread.php?threadid=3415662

Echoing everyone else’s advice that you should be very financially stable if you want to do indie development, either full- or part-time. I went full-time indie for a year and managed to significantly deplete my life savings building a mobile puzzle game that made a grand total of $26.

I decided to do this to begin with because I’m personally not someone who can write code for work and then go home and write more code even if they’re different fields, and my boring enterprise mobile app day job wasn’t leaving me with enough juice to be able to do what I really wanted. If my main source of income weren’t coding, I could have probably made it work, but before I went full-time I started feeling a bit burnt-out.

I did ship a game, though, and that got me a “real” industry job at a mid-sized studio.

blastron
Dec 11, 2007

Don't doodle on it!


Voronoi will indeed not give you the results you want unless you add more steps, like having a very dense set of cells and combining them in a second pass.

Is the goal to create country boundaries? You might want to consider how they’re made in real life. Rivers and mountains make good divisions if countries are relatively new, while older countries generally have their borders defined based on where people settled before a formal boundary was drawn.

blastron
Dec 11, 2007

Don't doodle on it!


Lork posted:

Does anybody do Blueprint in here? I want to make a list of references to instances of another blueprint - something like "List<MyBlueprint>" in most languages. I found Typed Element List but I can't figure out how to package anything as an "Element Handle" to satisfy the demands of the Add action.

When you say instances of a Blueprint, do you mean active objects (such as a list of dogs in the world), defined subclasses (a list of types of dogs), or something else? In either of those cases you can just make a regular array, pick the object class, and select either an object reference or a class reference.

blastron
Dec 11, 2007

Don't doodle on it!


Lork posted:

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

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

Glad you figured that out! Learning all the little buttons you need to click is probably the hardest part about Blueprint.

blastron
Dec 11, 2007

Don't doodle on it!


neurotech posted:

Over the past few days I've been trying to learn Unity so I can start making some simple games. Every time I open the IDE I find that I get really overwhelmed and rapidly lose the will to get stuck into things. Has anyone encountered this before? If so, how did you overcome it?

I get this all the time for a lot of different things, and my therapist thinks it’s a fun combination of anxiety and ADHD. What I recommend is figuring out a very small slice of something to work on, and to make it as manageable as possible to avoid being overwhelmed. Maybe find a tutorial on something basic and follow it along step by step?

blastron
Dec 11, 2007

Don't doodle on it!


sailormoon posted:

I'm familiar with what I need to do for game networking and have programmed a few games in Ebiten / SDL2 using rollback netcode, but I was curious how hard this was in modern engines. I see Unreal doesn't really guarantee deterministic frames -- is "good" networking pre-built in? Not looking to make anything more than a 4-8 player sidescroller, so nothing overly complex. I'm okay diving into the C++ weeds, which is why I was looking more into Unreal but what would be open to other engines to delve into.

I'm not sure what you call "good", but Unreal uses a model where there is an authoritative server that handles the bulk of gameplay logic and broadcasts the state of the world to players. There is some amount of rollback in Unreal's native systems, such as character movement, where clients can send their inputs to the server, which will apply corrections and broadcast that back out to the player. If you're using Unreal systems out of the box, this is generally pretty good. However, if you're making new systems, Unreal's built-in networking tools don't inherently have rollback, so if you're making a feature that requires snappy player input response, you'll be rolling your own.

blastron
Dec 11, 2007

Don't doodle on it!


I’m not following this thread super closely, but has anyone suggested event dispatchers and delegates? These are the easiest way to have level-specific logic where an object X triggers events that in turn trigger behaviors on objects Y and Z. The ideal implementation of these is to have a single actor in your level that exposes a bunch of delegates that listener objects can bind to, then a bunch of functions that call those delegates, which triggering objects will themselves call. This gives you a centralized object that you can pretty easily expand by both adding new delegate to handle new events and also adding new callers/subscribers to hook new things into the system.

blastron
Dec 11, 2007

Don't doodle on it!


It's also important to consider what level of effort a given thing may actually merit. If the primary purpose of this is to get something off the ground real quick in order to support more interesting gameplay, then just do the hackiest thing that lets you do that, with the understanding that at some point soon you'll probably need to tear it up and build something more comprehensive.

blastron
Dec 11, 2007

Don't doodle on it!


TooMuchAbstraction posted:

One of the things I really liked about Unity was coroutines. Being able to have multiple different execution contexts, each with their own closures for tracking state, was really handy for doing things like "first I want to play this animation, then I want to update this game state, then I want to play this other animation, then..." kinds of scenarios. Way less complicated than extracting all of their state to class member fields and putting a state machine in that runs in the Update function.

I'm not on Unity any more, I'm learning Unreal. So I found the UE5Coro library, and tried to use it. Unfortunately, it likes to crash the editor if I exit PIE while there's still active coroutines. The underlying cause appears to be that the coroutines are still active, despite the game being over and a bunch of important state having been cleaned up. This leads to access violations. For example, in this Rider screenshot, you can see that the i and j variables are clearly inaccurate; the Grid UObject is also null:



UE5Coro has functions for forcing coroutines to run in the main game thread, and for detecting coroutine cancellation, neither of which fix the issue. I suspect that when you exit PIE, a lot of stuff is just being forcibly cleaned up/unloaded, and it’s on me to recognize and respond to that (hence why I’m not bugging the UE5Coro dev for help).

I tried overriding the AActor::EndPlay function, so that my own code could recognize that the game is ending, and exit coroutines early; that doesn’t help either.

What’s the correct way to recognize and respond to PIE ending? Actually, a more appropriate question is probably: what’s the correct way to recognize and respond to an object being unloaded? After all, I might well get similar crashes when loading a new level. I only have one level at the moment, so it hasn’t come up.

Thanks for any advice or suggestions!

For the sake of completeness, here’s the function that’s most consistently crashing for me. It’s detecting matches in a match-3 game, clearing matched tokens, waiting for new tokens to fall in, and then scanning again, recursively.

I don’t know anything about this coroutines library, but when I’ve previously had to do asynchronous programming using UE’s futures or tasks, I used the garbage collector and/or smart pointers to determine if something had been cleaned up on another thread. If you’ve got a UObject you’re working with, I would recommend storing its pointer in a TWeakObjectPtr and calling IsValid() on that. This will (I think) catch all cases where EndPlay has been called and game objects have been either deleted or are pending destruction.

e: If these coroutines are being contained within a UObject and you’re capturing a pointer to this, there is a convenience function that checks to see if a given raw pointer is valid and points to a live UObject: IsValid(const UObject*).

blastron fucked around with this message at 19:13 on Oct 7, 2023

blastron
Dec 11, 2007

Don't doodle on it!


Unreal actually does support unity builds. They’re very nice on large projects, but occasionally something fucks up somewhere and I waste two hours trying to figure out why something is failing to compile in my client build when the server build works just fine. I have a non-zero number of checkins that add whitespace to a comment in order to get the compiler to realize it missed a dependency somewhere.

blastron
Dec 11, 2007

Don't doodle on it!


leper khan posted:

I'm not sure I like the trade of shorter build farm builds for longer local incremental builds.

Ah, I may have been a little imprecise when I said “server” and “client” builds. We use incremental builds both locally and on the farm, with a nightly clean build. I meant that the build (both locally and on the farm) might fail differently when I’m compiling the binary for the game client and the binary for the game server, despite the code changes being identical on both of them.

No idea about translation units. Compilers terrify me and as soon as a build goes wrong in more than the most basic way I nuke everything and start from scratch.

blastron
Dec 11, 2007

Don't doodle on it!


I don’t know if this is related to what you’re trying to do, but Unreal has built-in functionality for retrieving the name of the current function as a string through the __FUNCTION__ macro, as described here. It’s pretty handy for logging errors.

blastron
Dec 11, 2007

Don't doodle on it!


Rocko Bonaparte posted:

UE5 was all about the Blueprints for everything, but then I wanted to make a subsystem, and suddenly it threw me into the C++ hell with all of UE5's whack-rear end stuff. I'm kind of surprised you can't subclass a subsystem as a Blueprint. What a strange line to make.

The big problem with Blueprints is that you can build an entire game with them, but only if you stay within the bounds that whatever team worked on whatever feature you're using decided on, and those bounds can be pretty clearly defined as "would a programmer want to foist this off onto someone else so they don't have to deal with it?". There's a general assumption that the kind of person who wants to integrate against the EOS backend for identity management is the kind of person who's already writing most of their stuff in C++. You can make a whole game exclusively in Blueprint, but if you want to ship that game, you're going to need to interface with that whack-rear end stuff.

If you're running into weird C++ poo poo, @ me in the Dogpit discord. I'm not super active, but I've been working in this engine for far, far too long and can probably point you in the right direction.

blastron
Dec 11, 2007

Don't doodle on it!


The Fool posted:

unrelated but I just tried to install unreal engine on my laptop and it's 60gb?!?!

guess I'm going with godot for this project

You can cut this down a ton by unchecking the box that downloads sample content, but it'll still be gigabytes and then you won't have any sample content. Unreal's a big beefy boy.

blastron
Dec 11, 2007

Don't doodle on it!


Rocko Bonaparte posted:

I blew some odd hours figuring out that Unreal's UGameplayStatics::OpenLevel function is a non-blocking call and just signals a level change without fully doing it. So all the stuff I'd load in and change right afterwards would get nuked because the level wouldn't actually load until later. It took a lot of digging around to find which delegate to subscribe to in order to be told the level was finished loading, and I settled on FCoreUObjectDelegates::PostLoadMapWithWorld. You'd think FWorldDelegates::LevelAddedToWorld would be it, but that was never invoked at all.

My player control isn't completely re-established with the loaded player pawn yet. I do get my player controller and possess the pawn with it, but none of my controls actually respond. So I assume there's a bunch of other Unreal-specific technicalities with all this that I still haven't figured out.

What are you initializing, and is there a reason you’re not doing this as part of BeginPlay on the game mode?

blastron
Dec 11, 2007

Don't doodle on it!


Rocko Bonaparte posted:

In other news, I think the Unreal Source server on Discord has an implicit policy of solving everything with X instead of Y. So if you want to do X, they'll ask why you aren't doing Y. If you ask about Y, they will ask when you aren't doing Z. If you ask about Z, then they'll ask why you aren't doing X.

So far, I have traversed this once and when asked why I wasn't doing X (the thing I wanted to do originally), I try to lean into it. "Wow, what is that? How would I do X?" But then the rotating timer goes off and they start saying I should do Y instead.

I've kind of given up on that Discord at this point. There's a bunch of knowledgeable and helpful people on it, but the level of questions they're able to answer are the kinds of questions I can find answers for myself on Reddit or the UE community boards. Anything more arcane than that, like "when I finish loading player config data from the backend, is it okay to finish instantiating their player controller from the task graph or do I need to do that in a tick?", is something I need to ask my industry friends about or check Epic's licensee discussion boards for.

e: This isn't to say that it's a bad resource in general. If you've got questions about stuff that's well supported by the engine, they'll definitely be able to at the very least point you in the direction of a solution.

blastron fucked around with this message at 22:37 on Jan 13, 2024

blastron
Dec 11, 2007

Don't doodle on it!


Rocko Bonaparte posted:

Getting screwed by autosave has all kinds of fun ways to manifest. I could just as well say that the player was saving as they were dodging an attack, but when they reload, they now start stationary and get killed by it each time.

What's the intended goal of your autosaving system such that you're at risk of softlocking the player if the save catches them mid-input? That implies a very granular system that saves and restores practically all state, which has a whole host of both design and technical issues. Is there a reason you want to do it that way, rather than something that's less precise but more deliberate?

blastron
Dec 11, 2007

Don't doodle on it!


Unreal’s footprint for working in the editor is surprisingly small, so any moderately powerful machine is fine. If your PC can run the kind of game you’re making (and you’re not making a hilariously unoptimized mess), you can run the editor. I’ve done small hobby projects on a five year old laptop and it was just fine.

Is there a particular reason you’re looking for specifications? If you’re just asking if Unreal will run adequately on your existing machine, the answer is “probably yes”. If you’re looking for specs for a new machine, building a mid-tier gaming rig with a big SSD and as much extra RAM as you can afford is a solid starting point.

blastron
Dec 11, 2007

Don't doodle on it!


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

blastron
Dec 11, 2007

Don't doodle on it!


Rocko Bonaparte posted:

Unreal Blueprint code gets into some serious spaghetti really quickly. I think my main issue is with reusing return values. Say, I have an object to which I'll be doing a bunch of stuff in a row. A sequence will give a top-to-bottom ordering but won't stop me from having to connect that object in a fan to all of the different commands. Is there a better way to do this? Just save it to a temporary variable and drop that next to every command?

I either use a temporary variable to eliminate wires or reroute nodes to keep everything tame. I also try to keep things as uncluttered as possible, which generally involves collapsing chunks of logic into their own nodes or using comment blocks and reroute nodes to segregate things into discrete chunks.

Since you're mentioning that you're reusing return values: one very important thing to note is that pure functions (the ones without execution pins) are evaluated every time their return values are accessed. This is generally fine, since pure functions shouldn't be mutating state and should be quick to access, but you can get in trouble if you're using something with variable results, like a random number generator.

blastron
Dec 11, 2007

Don't doodle on it!


Truspeaker posted:

Speaking of reroute nodes, I just learned yesterday that there is a shortcut to just pop one down wherever your cursor is. By default it's the R button, and if you do it while dragging an execution pin around it even lets you continue dragging the pin around without having to click again.

One of those very small things that seems obvious in hindsight, but feels huge after (sort of) years of right clicking and hitting "rer" as fast as I could.

Double-clicking on an existing wire gets you a node, too!

blastron
Dec 11, 2007

Don't doodle on it!


Rocko Bonaparte posted:

I have an Unreal Engine CommonTextBlock with an overflow policy set to ellipses. When it gets excess text, it just draws it beyond the the area. It's a title text inside of a custom button. I'm guessing it has to do with some constraint issue with its hierarchy. It goes something like:

1. Root widget
2. Size Box
3. Button
4. Vertical Box
5. The Text Block is here

The button doesn't expand if the text is larger than the default 300 pixel width given for the size box. However, the text does. What I want is to constrain everything below the size box such that the text block is forced to use its overflow policy.

I'm assuming there is some concept I don't know about for carrying constraints around in that hierarchy.

There’s some magical combinations of buttons you need to hit in order to get text to respect layout. The first thing that comes to mind is that your text block might need to be set to fill horizontally instead of being center-aligned. There’s two sets of alignment buttons for text: one, toward the top of the list of properties, that controls how the widget behaves in the layout, and another, kinda in the middle, that controls text flow within the widget. I think, but am not sure because I’m not at my computer, that text containers need to be coerced into fitting into the rest of the layout by using fills.

blastron
Dec 11, 2007

Don't doodle on it!


Rocko Bonaparte posted:

I had made a little animation sequence earlier in the week where the pawn would shake the spear over their head triumphantly, so I'm trying to figure out how to actually integrate that. I don't really understand the details of AnimGraph. State machines in general? Sure. This thing? I don't know what does or doesn't go into it.

I wanted to use that animation as a precursor to having an attack animation. So I want it interrupt player movement, play the animation, and then start it over at idle (where they can immediately go back to movement if they want). I am guessing I have to set up my own boolean to signal the transition, add the state for playing the animation, and integrate the boolean across the existing transitions. What I don't really know how to do is have the spear animation play just once all the way through before going back to idle. Where do I put that logic and how do I tell it played just once?

You’re looking for Animation Montages, which are wrappers for animations that can be manually invoked and tracked on a given actor. You can specifically say “play this animation once and notify me on completion”, and it will override the animation blueprint’s evaluation in order to do so.

Animation Blueprints are great for things that are state-based, like locomotion, but if you’re looking for things that need to be timed with specific effects, go with a montage.

blastron
Dec 11, 2007

Don't doodle on it!


Are you looking for some way to reference the binding itself? So, rather than saying “bind Foo(), then, when X happens, unbind Foo()”, you’d say “bind Foo(), then, when X happens, clear this binding”?

I can think of ways to do that in C++, but I’m not sure if any of that is accessible in Blueprint.

blastron
Dec 11, 2007

Don't doodle on it!


For the UWorld thing, what’s your specific use case? Generally, if you’re in Blueprint land, you should be building global manager-type things as components hanging off of things that exist in the world.

Adbot
ADBOT LOVES YOU

blastron
Dec 11, 2007

Don't doodle on it!


Raenir Salazar posted:

So I don't think this is true, it is certainly very convenient to use Actors to access World, and I'm sure would work for most Indie projects but I don't think they're really meant to be the intended solution for things like Managers. At my previous job we had a few of those (Actor implemented Managers) and they were just absolutely painful to work with and had all sorts of issues.

Based on my research it seems like maybe Subsystems might be the intended way, but I can't say more without trying them out first. But presumably and ideally I could have a "SomethingSubsystem" which has that world context, and does the things I need; but I'm not really supposed to be experimenting too much with stuff I'm not familiar with right now at my work so I picked the solution that at least I knew would work now and not require changing anything I've already implemented in Blueprint. With my solution I just had to reparent like one blueprint and my issue went away.

Again, what’s the thing you’re trying to do? Subsystems are a solution to having manager/supervisor objects, but whether they’re the best thing for your specific use case depends on your specific use case. I generally prefer components hanging off of the core game objects like the game mode/state (and sometimes instance) because they have specific lifecycles tied to the game flow and will get events like BeginPlay, whereas subsystems live outside of that flow and get different things.

(Note that I’m specifically talking about components on existing objects, not sticking more actors in the level. That’s another good way to make managers, but it’s also very dependent on use case.)

Rocko Bonaparte posted:

I think it is inevitable to get into trouble with UE5 based on all that X-instead-of-Y-instead-of-Z-instead-of-X stuff I experience in that Unreal Discord. I think it does make easy stuff easy and hard stuff possible, but the hard stuff gets really wacky.

I suppose what I need to see a little is streams of advanced developers going into the muck or something.

Agreed! All of my deep knowledge has come from reading through documentation that’s hidden away as comments within the engine source and talking with my other Unreal engineer friends. For such a widely-used engine, there’s a depressing lack of comprehensive information out there on how to actually use it.

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