id like to run some code only when my character is below an altitude of 40 meters.
I feel like there must be a more efficient, performance way to check if my player is below 40 meters than running an update function to constantly check.
Is there a way to somehow watch a variable band only call a function when it passes a certain value?
Like watch my altitude variable and when it goes below 40m send some kind of callback? And again only when you pass this on the way up?
The setter will go off everytime you change altitude. It works the same as a normal property where you don’t specify a getter and setter function. The code inside the setter or getter does what you expect it to do. In the example above (which may not be 100% correct since I didn’t try it) the functions dosomethingOnWayUp and dosomethingOnWayDown will only be triggered if the conditions stated in the “if” are met.
@protopop it might be a good idea to check Microsoft’s reference manual, there’s lots of a good information properties. One of the main uses for properties is to perform validation, in addition to exposing data in a class.
I guess then an update function would be just as performance heavy to check since my altitude varies constantly varies as you run, so like both Setters and Update check things every frame? But I guess a setter is a more elegant way to do this and it links directly to a specific variable. I was going maybe I could register an event that would only fire when the condition was met. I’m under the imporessikn that events are less performance heavy, but maybe under the hood they too check constantly?
A set property will run every time you change the value of that property, so it depends entirely on when you change the value of Altitude.
You should know that, unless you’ve got thousands of these objects, you will literally never notice a performance difference between either of these. (And if you ARE using thousands of them, the discussion shouldn’t be about these two, but rather, you should be using DOTS to control them. But that’s another discussion for another time) It’s a simple float comparison, your CPU can do hundreds upon hundreds of those in an amount of time that’s so small that it basically can’t be accurately measured.
Don’t worry so much about the performance of your code until you start experiencing slowdown. Then, profile it, and you’ll find what is actually using up CPU time. (And it won’t be this.)
[quote=“protopop, post:6, topic: 768542, username:protopop”]
I guess then an update function would be just as performance heavy to check since my altitude varies constantly varies as you run, so like both Setters and Update check things every frame? But I guess a setter is a more elegant way to do this and it links directly to a specific variable. I was going maybe I could register an event that would only fire when the condition was met. I’m under the imporessikn that events are less performance heavy, but maybe under the hood they too check constantly?
[/quote]Checking in “Update” will also check when the Altitude hasn’t changed, while the property setter does not. If you know that the altitude will always be different everytime Update checks, then the Update function is just as good. As @StarManta mentioned, this will not be an issue for your performance though.
What I don’t understand is doesn’t the setter have to “check” the altitude every frame also wether altitude has changed or not ? How else will it know what the value is?
They said I guess I shouldn’t worry about it because it’s a small performance hit, but I am trying to understand what’s behind the way it works.
A property is a pair of functions that masquerade as a single variable. Let me show you how the compiler sees a property, that may help clear up what’s going on.
Imagine this:
private int altitude = 0f;
public void SetAltitude(int value) {
prevaltitude = altitude;
altitude = value;
if (value >= 40 && prevaltitude < 40)
{
dosomethingOnWayUp();
}
else if (value <= 40 && prevaltitude > 40)
{
dosomethingOnWayDown();
}
}
public int GetAltitude() {
return altitude;
}
// elsewhere
yourObject.SetAltitude(41f);
Debug.Log("The altitude is "+yourObject.GetAltitude());
You can see how this works - it only executes all that code when you call SetAltitude. It’s not going to run that code at other times on its own, only when you call that specific function.
Now here’s the trick: After the code is compiled, the code I wrote above and the code from @AlexN2805 are identical. The compiler actually does compile properties into pairs of functions that look just like those two functions. Anywhere you write “yourObject.Altitude = something” it uses the equivalent of “yourObject.SetAltitude(something)”, and anytime you write “somethingElse = yourObject.Altitude” it uses the equivalent of “somethingElse = yourObject.GetAltitude()”.
So bringing this back to your original question: the setter “checks” the instant that the value is assigned, no matter how often or how rarely that happens. In contrast, Unity calls Update() on each object once per frame, every frame.
That’s kind of what I suspected, like a getter and setter I guess is a shorthand for writing the same code in a more verbose way.
The only thing still eluding me is that the code you just wrote would still need an update loop attached to it to run because my character moves around and his altitude changes. And I would have to send the altitude int to this function ie I’d have to send yourObject.SetAltitude(playerAltitude); each frame so this function, or the setter In Alex code to check if the condition has Been met.
I’m going to try this code on my actual player before I say too much more because I think I might have an aha moment once I see it in action. I’m more an artist than an engineer and sometimes it is hard to wrap my head around these concepts. But the idea that both codes compile down to essentially the same thing behind the scenes is one of the questions I was very curious about - thanks for making it clear
By the way this is a screenshot from my game, I’m going to be using this altitude check as part of a simplified weather system so all of these answers will help me achieve that - thank you
Ahhhh OK so even with a setter I still have to CALL that setter. So I need some kind of loop, an update loop being the most common, but I could use an ienumerator or something if I wanted to call it less often for performance, which may be a good idea.
I thought there was a way to “watch” a variable and call a method when the condition was met. Something like a “OnVariableChanged”, but you know even as I write this I’m realizing even that would have to send the event firing to a condition checker code, so it ends up being the same thing.
I guess there is no way to attach a condition to a variable as an event - like if I could attach “in less than 40” to my altitude and have it watch for it. And it would have to know about the previous value anyways because you need that to get the direction, and so it’s only called as it passes the threshold.
I’m gonna use a co routine - which I think is more performant than an update loop if I’m right - and try it with Alex’s getter setter , with the knowledge from you that the core functionality is the same.
To reiterate from earlier, this is an incredibly simple function and worrying about performance on it is a waste of time. Whatever you use will have more performance cost in overhead (which is also so small as to be inconsequential) than the algorithm itself has.
Nope, it’s not. An object with no Update() that has a coroutine running (or waiting - Unity still needs to evaluate every frame whether or not it’s time to continue the coroutine even if the coroutine is yielding) has about the same processor overhead (which again is tiny and inconsequential), but also coroutines often cause allocations which (once a lot of memory allocations accumulate) can trigger the garbage collection, which actually can cause a noticeable performance hiccup. Optimizing to get rid of GC allocations is a whole other topic. (and before you start going crazy trying to optimize for GC allocations, a coroutine might add a few bytes worth of allocations and it takes megabytes to trigger a GC cycle)
You’re driving yourself crazy with micro-optimizations and this is a bad practice because you will never finish a game this way. You’re also making assumptions about which of two things is more efficient without profiling the things, which is really bad practice, because you are as likely as not to make it worse.
It’s important to recognize when something is important in terms of performance and when it isn’t, and this is absolutely the latter. It’s so tiny and so inconsequential that the least effective possible solution you can think of still won’t make any kind of performance hit. So don’t worry about it.
OK, OK I’m going to stick with the update+setter because this is a very simple check:) Ill save the coroutines for processor intensive loops like AI. Thank you for the scoop.
If you change the altitude of an object, the property setter is executed. You do not need to check in an update loop anymore, because anytime the altitude of an object is set, the setter already checks if it’s higher or lower than 40 and acts accordingly.
EDIT: I see @JeffDUnity3D basicly wrote the same thing. Sorry.