Should Location and Reach have getters or be private members?

Hello everyone!

I have a background as a Java Backend Developer so I already know there is nothing too wrong or too right on this case, since it is a very simple scenario.
What I’m looking for are thoughts and opinions about the overall design of my grabber: is it better than others? Is it for the good reason?
So this definitely wants to be a “high level” discussion about a mostly theoric and picky question, and I am already aware how little they are relevant in a pragmatic world as it is professional programming.

Anyway, the lecturer uses the methods

FVector GetPlayersWordPos() 
FVector GetPlayersReach()

Which is an approach I like, also very similar to how you do in Java, so familiar to me.

What I did instead is to always refer to private members and use void methods to update them.

Grabber.h

private:
	FVector LineEnd {0.f,0.f,0.f};
	FVector PlayerViewPointLocation {0.f,0.f,0.f};
	FRotator PlayerViewPointRotation {0.f,0.f,0.f};

Grabber.cpp

void UGrabber::UpdateReach()
{
	GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(
		OUT PlayerViewPointLocation,
		OUT PlayerViewPointRotation
		);
	LineEnd = PlayerViewPointLocation + (PlayerViewPointRotation.Vector() * PlayerReachInCentimeters);
}

The reason why I did this is because I considered that, in this specific scenario:

  1. Position and Reach (which I called LineEnd) are always updated together so their update can be (quotes) “an atomic operation” (I even considered to replace them with a struct)
  2. Position and Reach (at the current state of the project) will never be used by anyone but Grabber.cpp, so they should be as hidden as possible to the outside
  3. Position and Reach are updated continuously so I thought it was more logical (and performant, but by an irrelevant amount) that they should always be seen as members rather that something accessed by a function, for which I prefer it does some more logic.

The approach of the Getters however is good because:

  1. Makes the code slighly better to be read
  2. It is more changes-proof

What are your thoughts about it?

1 Like

Hi there. Welcome to the community.

In an application, I would always go with getters and setters. They are suboptimal however as each call to a method involves creating stack space, pushing variables into it with set at least, then executing and finally popping the stack when done. So, generally for game development, unless the property is being accessed as in the case of a component, I would generally access the Member variables directly. This holds true if the code sits in a tick or something as it’s executing frequently and small savings add up.

Rule of thumb, at least the one I follow, for code that requires performance is avoid short methods (less than 5 lines of actual code) unless there’s a legitimate reason such as a common calculation you might want to tweak later.

Having an exposed variable in a class is fine. However, UpdateReach is good example of where, if it was being used in many places, is a good way of wrapping up the code. If UpdateReach code is in a single place however, I would not wrap it as a method.

One observation re pointers and methods like GetWorld and GetFirstPlayerController - they can theoretically return nullptr which would crash UE. Adding null checks could justify wrapping the code in a method but again, it’s a small amount of code.

As far as readability is concerned. Comments.

Another option would be to use a preprocessor macro to do the same as the method. This would inline the code on compile thus maintaining readability and performance together.

I hope this helps.

Thanks for the answer, It helps indeed!
I intuitively already found out something like the “rule of thumb”, but it is always interesting to see it formalized by others!

Still on the subject, what do you think about inline functions? I know they should be more performant because their content is just pasted in caller’s code (I use them for very short and safe function, like logging). Does Unreal Engine fully support them?

For example I used it on this debug function that was called under Tick()

.h

inline void LogRotation() const;

.cpp

inline void UDoorOpener::LogRotation() const
{
	UE_LOG(LogTemp, Display, TEXT("%s -> %s | StartYaw:%f, CurrentYaw:%f, TargetYaw:%f"), *GetOwner()->GetName(), *GetOwner()->GetActorRotation().ToString(), StartYaw, CurrentYaw, DoorOpenFinalRotation);
}

I’m not knocking beegeedee’s advice at all by the way when I say the following. Its good advice.

But, at the same time, you could find code from popular games in the past or possibly current day which offer code or even examples from people who have many years with UE that can be seen that perform great and look at that.

There are games with tons of functions that perform just fine. You can have tons of functions and the calls can be short anyway because of the way the code executes may not involve everything. All depends on how you code something. Could be you need to do something complex and it may be complex and heavy no matter what you do.

A lot comes down to time. A lot comes down to what your performance goal is, or your opinion if its worth it or not, knowledge, or whatever. I always feel there’s no one right answer to that. Everyone has a different idea of what’s acceptable and different knowledge.

You kind of have to learn how to do it over time. You definitely won’t master this overnight and possibly not for some years unless you only plan to specialize in it.

But, its really if you want to or not. Not everyone is going to say use getters and setters and not everyone is going to say don’t use them. You will just do whatever you do. You will form an opinion and it will be your thing.

1 Like

To be clear, the use of functions/methods are good but don’t use lots of small ones and especially not in code that requires high performance. This is something that 25 years of industry has taught me and sometimes copying code is better, not because it looks better because it runs a lot faster and you need that speed. You have to balance the gains - 20% faster might not be worth it but less than have the time would totally be worth it…

Games are usually more time-critical and even recently, calculating stress on structures (Engineering, not games) copying code sped up a calculation to the point it was over 300x faster than the original as much as it broke my heart to do so (original calc took over 11 minutes, new calc took about 2 seconds with identical results) but sometimes you have to. This was just last week and lately I spend 1/2 my time optimising existing code rather than writing new code.

1 Like

Insightful! I never considered that “a bad practice” like copy-and-paste can become a “good practice” when applied in the right place! I guess I will master all these tricks with experience :slight_smile:

1 Like

That’s a great find. Even the speed of sound let out a gasp :smiley: