Unity emphasizes a philosophy called Composition Over Inheritance.
The idea is that rather than thinking of what a particular entity "is":
A soldier is a unit which is selectable and which is damageable.
You think of the set of behaviours/features it "has":
A soldier has a selection behaviour and a taking-damage behaviour
So then, as you suggest in the question, you can break these responsibilities off into their own
Selectable (watch out for naming conflicts with
UnityEngine.UI.Selectable) can respond to click events and hold information needed to draw a selection highlight.
Damageable can track the current health, resistances, and handle firing off low-health state change events or destruction animations.
Your "soldier" might not exist as a class anywhere in code - it's just a particular combination of components and parameter values that gives the set of behaviours you want, ie. an entity with both Selectable and Damageable components attached (among others).
This move from defining each entity in code to doing it in data gives us a number of outcomes that are useful in game development:
Non-programmers on the team can take a more active role in developing game behaviour. If your coders provide a good set of building-block components, the level designers can go to town experimenting & combining them in new ways, without waiting on a coder to write a class that glues-together all the bits they need in a new standalone class.
Occasionally you'll get new behaviour "for free" out of this combinatoric play. For example, take an enemy and remove the Damageable component - boom, now you have invulnerable enemies, without a coder creating a special mode or flag. ;)
We can create and modify these compound entities on the fly while the game is running, without recompiling code or relying on edit-and-continue functionality.
This style helps encourage small modular components, each easy to understand and modify on their own, rather than massive sprawling classes with many responsibilities as you describe - a common pitfall in game development, with player classes especially!
A more modular, data-driven architecture tends to have fewer bottlenecks for exclusive checkouts & merging when multiple developers are collaborating on a cluster of features.
This pattern can also make it easier to develop tools like level editors or support user generated content, since all the game entities are just data files that can be modified without code changes.
That's not to say you can't or shouldn't use interfaces - they're still a great tool to have in your toolbox, especially when you have some kind of well-defined need in your game and multiple ways you might want to serve that need.
For example, maybe your base AI movement logic knows it wants to move into firing range for whatever weapon it's using - but that weapon might vary from one unit archetype to another. You could introduce an
IAttackBehaviour interface exposing methods to select a target, locate a good attack position for the movement behaviour to reach, and to execute an attack. Then you could implement this in concrete types like
GrenadierAttackBehaviour, etc. Your movement behaviour just needs to know it "has" an IAttackBehaviour attached, but doesn't need to implement these details itself for every archetype flavour. This allows AI designers to mix & match components as they need, while maintaining a clear contract for how the movement & attack behaviours communicate.