But from what I understand, casting is pretty expensive and I’ve ended up using it a lot, which I feel discouraged for because I would like to learn to make my code more professional and clean. I’ve seen that interfaces are the main solution out there, but for this case they are not useful I believe, as I only want to get a variable’s value.
So, let’s say, for example, I have this variable in my BP GameModeBase:
If you want to avoid cast nodes you can implement blueprint interfaces, which are functions you can implement and call for any class. But casting isn’t that bad, it’s commonly used. Unless you are measuring bad performance, don’t worry about it. I would just add getters to the classes you mentioned but some people prefer interfaces, also for good reasons.
@Roy_Wierer.Seda145 is right. You don’t need to worry about casting unless it affects your performance. But using interfaces is a good practice.
Since you want to get multiple references and variable I would go with Interfaces. This way you would have the groundwork to use this references in other classes too. How you structure them is totally up to you. Choose whatever suits your needs.
Another way (But I don’t recommend it) would be casting the references at the beginning of the game and storing them in variables. I beleive you can see what is problematic with this approach.
Do not store the components in variables on the class as you will have to check for their validity every time. It is better to use a getter the moment you need the data and cast that. If the cast fails the data is invalid.
One more thing, your HUD shouldn’t access anything on the Game Mode. If you think you ever might develop multiplayer games its best not to allow the hud and game mode to directly communicate. It doesn’t work for multiplayer games so it’s best to break that kind thing before it’s a habit you’d have to unlearn.
In multiplayer games the game mode only exists on the server, and it can communicate with the game mode and each player’s player controller. That’s fine.
But the hud only exists on the player-owned clients. They can communicate with their own player controller and with the game state, because those are replicated between client & server. But, the clients can’t directly communicate with the game mode.
So anything the hud might need, use player controller or game state as an intermediate between it and the game mode.
It really isn’t, at least not unless you do it in a tight inner loop or for thousands of objects per frame.
And once you’re in C++, casting is much cheaper than in Blueprint, so if it ends up being a real performance bottleneck, you can always convert to C++.
In general, though, you need to know which player controller – if you have multi-player, everything needs to be derived off of some particular player controller instance. Also, the game mode only runs on the “server” or “authority” – again, if you have multiplayer.
If you have single-player, and don’t support split-screen, then “get player controller 0” will always work, and the game instance running will always be authority, so “get game mode” will always work, too. And if you really care, you could cache the cast player controller class inside the “on player join” callback, and similarly cast the game mode inside the “begin play” callback.
Until now I’ve been using the HUD to only draw cosmetic graphics on screen, like a reticle or this debug widget that shows info about the player while in development:
To access the values I was using the casting of course, but I didn’t knew that HUD and GameMode should not be related, so thanks for that tip
So, in a multiplayer game, if clients cannot directly communicate with the game mode, can they communicate with the game state, and this one with the game mode?
As I’ve understood, an interface is code that can be reused by actors/elements that aren’t the same parent class, so I guess that if you don’t need an execution of code but just get/set a single variable is ok to use a cast? My main concern comes when (as I readed) Casting is always loaded in memory (or something like that), so even if you are in the beginning of a game, you’ll have loaded a casting at the end of the game.
Yes, that’s basically it… but player actions usually use the PlayerController.
Client - “fire weapon”… becomes client-to-server RPC call. Server then handles it. The server’s GameMode and PlayerController and GameState can interact on the server.
And then data flows from server to client via replication… for global GameState, for local player’s PlayerController, and for all the relevant Pawns (eg other players that are shooting/shot at - their pawns replicate, the PlayerControllers do not).
So yes, GameMode/GameState/PlayerController can communicate on the server. On the client GameState/Local PlayerController/Hud can communicate (as well as the pawn).
I dont know if anyone said it, but you can get variable from gamemode with your player controller by making a custom event and setting it to run as (run on server) then cast to your gamemode - get self - get controlled pawn - and cast to your pawn. After you can save inside your pawn what variable you need from gamemode