Hey there, my name is Charles and this is part 3 of a series in which I'm using Unity
to recreate the Core System from Red Dead Redemption 2.
In part 2 we began writing our first bit of real core system functionality by implementing
health ring regeneration.
In this video introduce health core depletion, which'll effectively complete the functionality
of our first core.
If you haven't already, I highly recommend watching parts 1 and 2 so it's easier to
follow along.
Otherwise, let's get right into it.
First things first, let's review our user story.
"As a player who enjoys immersive games, I want Arthur's health core to deplete over
time so that I have an incentive to make him sleep and eat."
I really like how this story was written because it explains why this feature is valuable to
the player.
And it also describes the type of player that cares about this functionality, which could
affect how we implement it at a high level.
Let's read the acceptance criteria next.
Given that he's alive, Arthur's health core should deplete over time when it isn't
empty.
And the rate of depletion should be configurable.
Simple enough!
Let's boot up Unity and Rider.
And open up the HealthSystem class.
So I have a feeling that the implementation is gonna to be pretty straightforward.
But there's one thing I'm not 100% sure about.
I don't really know how, or if, it's going affect the logic we've already written.
Thankfully, we've been using Test-Driven Development, so we have a nice suite of tests
that were designed to protect us against regressions.
This logic will be super easy to write but I don't think there's any harm in using
TDD to tease it out.
So let's open up the HeatlhSystemTest class.
Now let's go ahead and write a base case test.
But wait, pop quiz, what base case behavior do you think we'll be testing and what do
you think I'll name the test.
Pause the video and try to reason it out, then leave a comment letting me know how you
did.
Alright, create a Unity test called "EmptyCore_NoDepletion".
Then create an instance of health system and initialize it's values.
I'm just gonna paste in some code from a previous test.
We can max everything out except for the core which we'll set to 0.
Then assert that the core value is still 0 after one update has elapsed.
Run the test.
And it passes.
But we haven't really done anything yet.
If we switch over to the HealthSystem class, we can see that the logic for this test is
actually already in place.
The first guard clause in the Update method returns when the core value is equal to 0.
But we should at least expose a variable to hold the depletion rate and set it in the
test before 5we move on.
Go ahead and add a public float variable called DepletionRate.
Then switch back to the HealthSystemTest class and initialize it's value to 0.
Now rerun the test.
Great!
Still geen.
We're trying to guard against future regression so each test should be reflect the true state
of the class.
Which means we'll have to refactor our previous tests to include the new variable.
This time, let's rerun the entire suite.
Still green.
Beautiful!
Real quick, just wanted to give a quick shoutout to Mateo from our community Discord server.
The other day he shared the Live Snippet that I used to create the base case test and it's
been really helpful.
It was super easy to set up and now all I need to do is type utest and hit tab whenever
I need to create Unity test.
Live Snippets are a feature in Rider, the code editor that I use.
I'll leave a link in the description in case you're interested in checking it out.
Alright let's get back to it.
Create a new test called "FullCore_Depletes".
Copy in the initialization logic from the previous test.
And set the depletion rate to 1 and the core value to Time.deltaTime.
The reason we're doing this is because delta time equals the amount of time that has elapsed
since the previous frame.
So we're gonna need to factor that into our logic just like we did for the regeneration
rate.
Since our depletion rate is set to 1, or 1 per second, we'd expect to assert that the
value is equal to 0 after one update.
The problem is that there's no way to control delta time's value and it changes every
frame.
So instead of using float.Epsilon as our delta, we'll just use a number that's a little
higher.
Or I guess it's a lot higher in mathematical terms, but you get what I mean.
Run the test.
It fails.
So switch over to the HealthSystem class and add in the logic.
We can drop it in right after the first guard clause.
Run the test.
Beautiful.
Now, this isn't our first rodeo.
We're gonna need to make sure that we're not depleting past 0 just like we did for
regeneration.
So switch back to the HealthSystemTest class and add one more test.
Call it "AlmostEmpty_DepletesToEmpty".
Copy in the initialization from the previous test.
And set the core value to 0.001.
Now let's assert that the value is equal to 0 using epsilon as the delta.
Run the test.
Perfect!
It fails, which is just what we want.
Now we can pop back into the HealthSystem class and adjust the logic to meet our new
needs.
Using Math.Max will ensure that the core value will never be set to a value lower than 0.
Run the test.
Beautiful.
How about a quick demo?
Let's switch back to Unity and set the deplete rate to a value that'll be easy to visualize.
Now run the scene.
Awesome!
Well, that's it for part 3.
We've completed our first fully functional core.
In part 4 we'll get right to work on stamina, which should be pretty straightforward considering
it functions exactly like the health.
If you enjoyed this video, please leave a like and a comment letting me know what you
thought.
And for more Unity videos and tutorials just like this one, don't forget to subscribe
with notifications on.
Thanks for watching and I'll catch you in the next video.
Không có nhận xét nào:
Đăng nhận xét