Welcome.
Now, we've just put a lot of effort into adding an ability system component and an attribute set.
We were careful to initialize our ability system component with an owner, actor and an avatar actor.
So our ability system component knows who its owner is.
What about the attribute set?
Well, when we construct the attribute set alongside the ability system component inside the owner actor's
constructor, as we've done, it's automatically registered with the ability system component.
The ability system component has access to it and any other attribute sets that are registered with
it.
We can have multiple attribute sets if we wish.
Say you want to distribute your attributes among several different attribute sets based on category.
Well, you can do this if you like, but it's important to know that each of these must be separate
classes.
You can't have more than one attribute set of the same class type.
Otherwise, you get ambiguity attempting to retrieve it from the ability system component.
On the other hand, it's perfectly acceptable to contain all of your attributes on the same attribute
set.
This can make things simpler, especially if the attribute set needs to know about the values of the
other attributes when making calculations.
Attributes take up negligible memory so you can even share a single attribute set among all classes
in your project if you wish, and simply use the attributes that you need in any given class in this
game project.
Our attribute set will contain attributes that are used by all characters in the game, so we'll have
just a single attribute set.
But keep in mind for future reference that you can have multiple.
So what are attributes exactly?
Attributes are numerical quantities associated with a given entity in the game such as a character.
All attributes are floats.
They exist within a structure called gameplay attribute data.
Attributes are stored on the attribute set, and the attribute set keeps them under close supervision.
We can know when an attribute changes and respond to it with any functionality that we like.
Now attribute values can be set directly in code, but the preferred way to change them is by applying
gameplay effects.
When we get to gameplay effects in this course, we'll soon learn that gameplay effects can change attribute
values in a number of different ways.
Aside from the built in capabilities of gameplay effects, another reason to use them is because gameplay
effects allow us to predict changes to attributes.
Prediction means that the client doesn't need to wait for the server's permission to change a value.
The value can change immediately client side and the server is informed of the change.
The server can then roll back any changes that it deems invalid.
This is a huge benefit because prediction can take a lot of extra work to program yourself.
Prediction is something that makes for a smoother experience in multiplayer.
It's one of those things that you don't notice when it's there, but you do notice when it's not.
Here's how a client side change would occur without prediction on the client.
Let's say you have an attribute that needs to change since the server should be in charge of important
gameplay changes.
Otherwise clients would be able to cheat.
A request is sent to the server telling it that the attributes value needs to change so the server receives
the request decides whether that request is valid based on any number of criteria set by the developers,
and if that change is deemed valid, the server then sends the confirmation back down to the client
who can now change the attributes value.
Since data takes time to travel across the network, this results in a noticeable delay from the time
the client needed to change the value to the time it received permission from the server to actually
change it.
It's not unusual for lag times to reach 100 milliseconds or more, so performing an action in the game
and having a noticeable delay before you can see and hear the effects of that action makes for a very
bad gameplay experience.
Let's see how this type of thing works with prediction.
With prediction in gas, a gameplay effect modifies an attribute client side and that change is perceived
on the client instantly.
No lag times.
Then that change is sent up to the server who still has the responsibility of validating that change.
If the server decides it's a valid change, then cool.
It can inform the other clients of the change.
However, if the server decides that the change is not valid, let's say a client hacks the game and
tries to do an ungodly amount of damage, for example, then the server can reject that change and roll
back the changes, setting the client's value.
Back to the correct one.
So the server still has authority, but our client doesn't have to have a delay.
Prediction is complicated and having it as a built in feature throughout gas is a huge benefit that
lets us focus on creating gameplay mechanics and not worry about implementing lag compensation.
So an attribute is an object of type gameplay attribute data and is stored on the attribute set.
Attributes actually consist of two values a base value and a current value.
The base value is the permanent value of an attribute.
The current value is the base value plus any temporary modifications caused by gameplay effects.
Think about this in terms of buffs and debuffs, you may have an effect that adds or subtracts a value
for a certain period of time, and once that time is up, that modification is undone and the attribute
goes back to its base value.
Now, you may be tempted to conclude that the base value is the max value for the attribute.
For example, when calculating the percentage for a health bar, do you divide the current value by
the base value?
Well, no.
This is a common mistake and it's not the way to go about it.
The max value for an attribute is separate from the attribute itself.
If the max value can change, which is pretty common, the max value should be its own separate attribute.
This way we can have gameplay effects applied to the attribute itself or apply to the max attribute
separately, and the percentage for your health bar, for example, can simply be the fraction of health
divided by max health.
So now that we know what attributes are.
It's time to add some to our attributes set and we'll do that next.