Interfaces vs Base Classes?

I’m currently looking into how CodeMonkey implemented the accuracy system in the Xcom prototype he made, and was surprised to see an interface called IUnitAction. Within, it contained a few functions and a enum list of every action type. I also noticed that it did not replace the BaseAction class in the prototype, but that class contains lot less code than the BaseAction class on this course, presumably because the interface does a lot of the work instead.

The hit percent UI on units (which tells the player the chance to hit them with a shoot action) is enabled through the UnitWorldUI script when the shoot action is selected, by checking the action type through the IUnitAction interface and then running the necessary code if it’s a shootAction. I could just copy that code from the IUnitAction script, but I’d like to understand why it was done that way and the advantages of it. Could I not just have the BaseAction get the action type, in the same way it gets a string for the action name to apply to the action buttons, making the IUnitAction script unnecessary?

I wondered whether it has been done this way because it allows future expansion on the actions. For example, I was wondering how I might expand the grenade action in future to support multiple types of grenades. I expected I would be making a BaseGrenadeAction, so that each grenade extends BaseGrenadeAction, which in turn extends BaseAction, but could/should I use an interface like this to set up a bunch of different types of grenades, which are all routed through the grenade action?

ShootAction could presumably be expanded with the an interface for a bunch of shooting abilities (examples from Xcom like rapid fire, suppression, double-tap, flush, close encounters etc) and allowing the HitChanceText to be correctly displayed for each of them, or ShootAction could be turned into BaseShootAction with all the variant abilities fed through it before going through BaseAction.

Hopefully I’m making sense. Is one of these two options a better approach in this project (particularly, is one more performant than the other) or is it a personal preference thing?

Hi @BadNeighbour.
I haven’t had a chance to check out @CodeMonkey’s XCom prototype, so I don’t want to do more harm than good by trying to answer. I’ve tagged Hugo into the conversation, though. He’ll likely explain it way better than I will.

From looking at the xcomm version(wanted to see how he did cover) it looks alot like Hugo was going for" get it working, polish it later" approach.

I find I do the same thing with singletons and unity tags, before I switch to better architecture once i see the more complete picture.

There’s a lot of working that goes between an initial prototype and the final course code so you shouldn’t try to compare those two directly. It has been a long time since I made that prototype so I don’t remember how it differs from the course.

Both options you mentioned are valid, I would say the answer comes down to how similar are those new Grenades/ShootActions you want to create. If they are extremely similar to the base GrenadeAction/ShotAction then extending a base class makes sense, if you want to make those new ones behave very differently then perhaps an interface might make more sense.

For accuracy, I think the only thing I took into account in the original prototype was distance, I think I simply made it lose a tiny bit of accuracy for every grid position of distance. You can look into XCOM itself to see how they calculate accuracy, all the values are shown to the player, you can see all the + and - like if the player has a Scope weapon it gets +10, if the enemy is in half cover it gets -25, etc

Thanks for the reply. It sounds to me like I’m better off going with interfaces in general, as I have the flexibility to either keep the abilities similar, or make them function quite differently if I want to (at least with greater ease). Grenades I may use a base class, as I imagine most of them will have the same throw physics and just a different explosion outcome at the end.

I tried to bring in the accuracy system, but I couldn’t quite get it to work (I think the UnitWorldUI’s hit chance text was just showing the randomised aim stat I made for the targeted unit for some reason, and preventing shoot actions from working at all even though I hadn’t touched the actual shoot action logic yet).

I was getting frustrated and felt I was moving quite far away from what the course covers at this point, so rather than continuing to try to iterate on the tutorial project and ask awkward questions, I’ve started on my actual game project. A bit intimidated by the prospect of making a gridSystem like this work with procedurally-generated voxel terrain I barely understand, but hopefully I can figure it out.

I can share what i did on the shoot function, though I’ve been playing with it still.

    onAnyShoot?.Invoke(this, new OnShootEventArgs
    {
        targetUnit = targetUnit,
        shootingUnit = unit
    });

    onShoot?.Invoke(this, new OnShootEventArgs 
    {targetUnit = targetUnit,
    shootingUnit = unit
    });

    targetUnit.GetGridPosition();
    unit.GetGridPosition();

    PathFinding.Instance.FindPath(unit.GetGridPosition(), targetUnit.GetGridPosition(), out int pathLength);

    float distanceModifier = pathLength / 10; //calculates the path score and divides it by 10, gets the actual spaces
    //Debug.Log(distanceModifier + " DistanceModifier");
    float accuarcyReduction = distanceModifier / maxShootDistance;  //returns a value between 0 and 1, 1 will apply the max"distance penalty"
    //Debug.Log(accuarcyReduction + " AccuarcyReduction");
    float hitChance =  (weaponAccuracy - accuarcyReduction * distancePenaltyWeight) * 100 ;

    //Debug.Log(hitChance + " HitChance"); 

    if (UnityEngine.Random.Range(1, 101) < hitChance)
    {
        targetUnit.Damage(shootDamage);
    }

    else
    {
        Debug.Log("Missed! " + hitChance + " HitChance");
    }

I also did a script on unit action system to open a dialogue on how much damage/accuracy before we go actually attack.

Privacy & Terms