- Home /
apply something on enum
Hey, Here is the issue, i have some states on the player's hunger. Depending on his current state, diferente things will happen, for exemple if he is hungry, he moves 50% slower. Here is the code for that
CurrentNourishment ReverseNourishment()
{
if(CurHunger < 5)
{
currentNourishment = CurrentNourishment.Nourished;
}
if(CurHunger <= 50 && CurHunger > 5)
{
currentNourishment = CurrentNourishment.Fine;
}
if(CurHunger <= 75 && CurHunger > 50)
{
currentNourishment = CurrentNourishment.Hungry;
}
if(CurHunger > 75)
{
currentNourishment = CurrentNourishment.Starving;
}
return currentNourishment;
}
I thought about using a While, but it kept crashing, i thought about a switch, but that repeated the whole thing several times, so if i put curSpeed--; it would keep happening until he couldn't even move, when in reality, i only want that to happen once. I understand why this happens, but i dont know how to fix it. Here is my update.
void Update()
{
if(!isDead)
{
IncreaseHunger();
IncreaseThirst();
ReverseNourishment();
}
}
I understand that it runs several times on update until the condition is not met, but how can i fix this?
There is information missing here to help you. You mention a variable called curSpeed, but I don’t see it in your code. Where are you manipulating curHunger?? The only reference I see to curHunger is during currentNourishment checks. I’m guessing all of this is time dependent. If a certain amount of time goes by without nourishment/food/water/etc... the curHunger goes up is my assumption. So it likely looks something like this:
float hungerTimer = 0.0f;
float hungerIncrement = 5.0f;
void Update(){
hungerTimer = hungerTimer + Time.deltaTime;
if(hungerTimer >= 60){
//every 60 seconds reset hungerTimer and apply hungerIncrement to CurHunger and do a nourishment check
hungerTimer = 0.0f;
CurHunger = CurHunger + hungerIncrement;
ReverseNourishment();
}
}
//not sure what you have worked out for replenishing the player, likely an OnTriggerEnter with food colliders will replenish
That code would add 5 to CurHunger every 60 seconds and also set currentNourishment at the same time. You would also want to do a currentNourishment Update after you get food as well for example.
A while statement will make unity crash if it is an infinite loop. This means that within the while loop you need to eventually have an exit plan/something that changes the condition to false. The exception is to have a while loop in a coroutine with a yield statement which does not stop the update loop, but runs separately. If you want that code to run every 5 seconds for example, you should put it in a coroutine with a while loop and use yield return new WaitForSeconds(5.0f);
. That will run the code every 5 seconds and will not crash unity as the main update loop will be unaffected. As far as curSpeed is concerned I would make it mirror CurHunger, curSpeed = 100 - CurHunger; and you can do that when you set CurHunger or at the end of ReverseNourishment()..
Did this help?? I’m not 100% sure about what you are asking for, but hopefully I hit the nerve.
Cheers
Answer by Eno-Khaon · Apr 20, 2019 at 09:48 PM
Rather than directly reducing your "curSpeed" value, you could use your nourishment as a multiplier for your speed.
For example:
float curSpeed;
float baseSpeed = 5.0f;
float nourishmentMult;
CurrentNourishment ReverseNourishment()
{
// If the function returns something, might as well make use of it
CurrentNourishment newNourishment;
// Since the same value is being tested throughout,
// might as well save checks by using "else if"
if(CurHunger < 5)
{
newNourishment = CurrentNourishment.Nourished;
nourishmentMult = 1.0f; // Don't reduce speed
}
else if(CurHunger <= 50 && CurHunger > 5)
{
newNourishment = CurrentNourishment.Fine;
nourishmentMult = 0.95f; // Reduce speed slightly
}
else if(CurHunger <= 75 && CurHunger > 50)
{
newNourishment = CurrentNourishment.Hungry;
nourishmentMult = 0.75f; // Reduce speed moderately
}
else// if(CurHunger > 75) // This condition is currently implied
{
newNourishment = CurrentNourishment.Starving;
nourishmentMult = 0.5f; // Reduce speed significantly
}
CalculateSpeed();
return newNourishment;
}
void CalculateSpeed()
{
curSpeed = baseSpeed * nourishmentMult * otherMultA * otherMultB;
}
void Update()
{
// ...
currentNourishment = ReverseNourishment();
// ...
}
I threw in a few example values as a point of reference, but the main point to be made here is that you simply need fixed conditions to dictate your speed if you want reasonable control over it. You can still scale it relative to the current point in a given hunger level (Lerp()) as desired.
Fantastic answer, cleared it up for me! Though that does leave me with a question. In terms of being able to have neat and eficiente code will this give me any problems? At first i was using a seperate script to calculate the player's movement. I suppose i could access this Hunger script from the Player $$anonymous$$ovement script and that would be fine right? Because i really want to avoid using public things as much as possible. Once again, thanks alot!
Well, "neat and efficient" code is always handy, but isn't necessarily always the easiest thing to hammer out. The more variety you want, the more complex it has to be. If you want things that you adjust in the editor ins$$anonymous$$d of hard-coded script values, then you can easily wind up with one complex, complicated (editor) script to allow your other one to *look* simpler.
On another note, public variables themselves aren't necessarily a "bad" thing. If you want your variables to have separate read/write access, you could use Properties ins$$anonymous$$d. For example:
private float _nourishment$$anonymous$$ult;
public float nourishment$$anonymous$$ult
{
get
{
// The value can be read from anywhere
return _nourishment$$anonymous$$ult;
}
private set
{
// The value can only be changed from inside the script
_nourishment$$anonymous$$ult = value;
}
}
// Example
void Start()
{
// Both of these do the exact same thing
// Use the property, for a simple and consistent
// variable name
nourishment$$anonymous$$ult = 1.0f;
// Use the raw variable name if you don't need the
// "set" section of the property or want to
// avoid anything else in it (such as added function calls)
_nourishment$$anonymous$$ult = 1.0f;
}
By handling it that way, you'll always be able to read the value from anywhere (public "get" access), but it would only be modifiable inside of the Nourishment script itself (private "set" access or none at all).
Your answer
Follow this Question
Related Questions
Update within an if statement not working? 3 Answers
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
C# the position of the object 1 Answer
If gameobject moves do this 1 Answer