Checkmate Dev Log 5/14/26 - Learning about ✨INHERITANCE✨ (And Naughty Attributes)
Hey all. So. Last post, I have finally decided to bite the bullet and learn inheritance because of one thing: There are two scripts that I am working on that are roughly the same. And changing one script means combing through the other and changing the same thing. Yeah. That blows. So let's inherit.
To start, think of inheritance as a family of objects. In Animal Crossing, you have a bunch of trees. All of them run essentially the same code. They're there, and you can shake them, but what's inside the trees that you can shake out can mean that you have inherited classes.
So for Checkmate we have two identical paddles with essentially the same controller. They do the same things but they take different inputs to do those things. To do so, we have a few new keywords:
protected (another access class like public and private which means "every generation beyond me can use this")
virtual (which modifies the line so it can be overridden)
override (which is exactly what it says)
and sealed (which goes before "override" so you don't need to make note of it any further in the family)
Together with what I know, we're going to make something new that I've never made before!
That right there is a reminder of where I am right now. Everything that was here got shunted to the new parent, there's nothing in this, period (that's literally the entire script now), and yet this is on the paddle the player can use and it still works.
So, all caught up? Cool. Time to do some cool stuff. First, we take out everything that makes the parent a player paddle because the CPU doesn't need the extra code. The goal is to make this take different events to do the same thing. So we're going to pull out what the player uses first and what the CPU will not use.
First thing to scratch is ControlScheme. The player will have multiple control schemes to handle different input methods. Mouse wheel? Good. Want to move the mouse up and down? Sure. WASD or Arrows? Why not? The CPU doesn't have a mouse or keyboard, it's just going to tell the paddle "I'm scrolling up" or "I'm clicking". So that can go to the player. Now we modify anything that uses Control Scheme so that it can be overridden in the child.
Which we're in luck, because the only thing that uses the inputType is MoveTargetY, which is most of the input system. And that's what's great about object oriented programming, because when you sort everything out, you just edit a block instead of going all over the place.
So here's the code. It's in the parent (obviously). Let's make it so that the child can put whatever it wants in there:
So, next step, we'll copy this over to the child and make this more universal. Player controller has this code now. So, now we make a base function (And I just learned this, you can call that inside the child function which is awesome) and then adapt the override.
All this is doing is taking input and following- Actually let's get rid of that part and move it to the state machine where it belongs:
Super simple stuff. Almost as if making the base class is ironing out the last kinks at the same time. So the player class is going to use this script but the base class is not. Scroll and mouse sensitivity will be useless to the CPU so the base doesn't need it. So that moves too. Just a quick test...
The reason why it's breaking is because I thought that you could mess around with parameters in the child and add new ones. You cannot. The declaration for an override has to be literally the same. Only what's inside the block can be changed.
I added one to the new script, and I learned that [Header] namespaces are Unity-exclusive (Which makes sense, it involves the inspector), so when new code like that is pulled in, the library that uses it must be too.
So I'll toss that in with the InputSystem because we'll also be using that.
Next step: "PaddleController.targetY can't be accessed due to protection level". So let's make targetY protected in the parent.
Boom. Child can access it. Next, aimSensitivity isn't in the base anymore for input, aim line turning goes to the child.
Let's try something else. We'll keep those in and instead simplify them for just scroll wheel. So...
For now, both classes will have a base script that can be used by input. A CPU controller will modify this script with its own version just like the player does to account for other ways to move the paddle.
Testing and... Perfect. And again, the reason why I'm doing this is to make the CPU easy to build from. Think about it like layers. You want to give the Mona Lisa a moustache? Either you want to buy two of them so you don't mess one up, or you just put a glass pane over it and put the moustache on it so Mona can just be Mona.
After testing all of that, we're still good. However:
This state was actually at the top of the script before. So, another thing to learn: Any new variables added will pop up below anything the base had.
Now as far as changing sensitivity goes, making it protected actually hid those. So we'll just serialize the fields.
Reason why I am? Just to test mouse sensitivities. And I have learned that I may want target Y to just follow the mouse and all, but that aside, I want to be able to have that only show when it's needed. So side lesson.
THAT wish requires a new package. Sometimes you need a package to script things better. TextMeshPro wasn't always in Unity but the company made it mainstream because everyone was using it. What I want uses a package called NaughtyAttributes. So let's learn how to install this thing.
First, you head to Window => Package Manager to see what you have.
This window will show and as you can see, I'm all set. To get it you go to the asset store and look for its name. (The Asset Store is in the same menu below Services.) Then you look it up, add it to your assets, go to the manager, download it, import it, bob's your uncle, game comes out in seven years.
So for what I want, I asked Aria how to do it. It's simple. You use the package...
We add the naughty attribute to the thing...
And now the Inspector is a lot more useful and less cluttery.
So, that aside, I learned something just now.
I learned that sometimes the best solution is usually the easiest one.
And making a brand new class that's just like the player to split between itself and a CPU? It's hard.
You know what's easier? Making the Paddle Controller the player controller and having the CPU inherit from that. So, tons of time wasted. I'll take a break. We'll learn more next post.