Search Unity

Question Faction system - Can i damage this target or not ?

Discussion in 'Scripting' started by Pytchoun, Mar 18, 2023.

  1. Pytchoun

    Pytchoun

    Joined:
    Apr 12, 2015
    Posts:
    203
    Hi,

    I use this for know if i hit something and apply damage.
    Code (CSharp):
    1. if (hitCollider.TryGetComponent(out IDamageable damageable))
    2.             {
    3.                 Vector3 contactPosition = hitCollider.ClosestPoint(_zombieHandTransform.position);
    4.                 damageable.AnyDamage(_zombieSO.Damage, contactPosition);
    5.                 break;
    6.             }
    But what happen if both target and owner are on the same side and shouldn't be able to hit together.
    I need something to know if i can hit this or not.

    When you have multiple faction you can't just set a bool to know if you side 1 or side 2.

    Should i use a enum ? Or something else ? What you suggest ?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    I would reach for ScriptableObject instances to define what faction each unit is in.

    enums are bad in Unity3D if you intend them to be serialized:

    https://forum.unity.com/threads/bes...if-not-do-something-else.972093/#post-6323361

    https://forum.unity.com/threads/unity-card-game-structure.1006826/#post-6529526

    It is much better to use ScriptableObjects for many enumerative uses. You can even define additional associated data with each one of them, and drag them into other parts of your game (scenes, prefabs, other ScriptableObjects) however you like. References remain rock solid even if you rename them, reorder them, reorganize them, etc. They are always connected via the meta file GUID.

    Collections / groups of ScriptableObjects can also be loaded en-masse with calls such as
    Resources.LoadAll<T>().
     
  3. Pytchoun

    Pytchoun

    Joined:
    Apr 12, 2015
    Posts:
    203
    Hi, thanks for your answer.

    Do you have a sample of this SO ? So i can set a faction to my Unit.

    The goal is to be able to know:
    If both Unit are on the same faction so you can't attack it.
    If both Unit are on a different faction but they are friendly together and then you can't attack it.
    If both Unit aren't on same faction or friendly faction and you can attack it.
     
    Last edited: Mar 18, 2023
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,934
    It can honestly be an empty scriptable object:
    Code (CSharp):
    1. [CreateAssetMenu(menuName = "Units/Unit Faction")]
    2. public class UnitFaction : ScriptableObject
    3. {
    4.    
    5. }
    But you can of course load it up with other data, such as display name, the faction logo, etc.

    Then you just reference this SO on your units. If one unit has the same faction scriptable object as another unit, they can't attack each other.
     
    Bunny83 likes this.
  5. Pytchoun

    Pytchoun

    Joined:
    Apr 12, 2015
    Posts:
    203
    Well ok but in this case you don't check friendly faction.
     
  6. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,934
    It works either way.

    If both units are referencing the same faction asset, they can't attack each other.

    So... naturally, if they aren't referencing the same asset, they can attack each other.

    Make sense?

    You could serialise a list of these factions in them as well, and provide a simple method that tells you whether a faction is friendly or not:

    Code (CSharp):
    1. [CreateAssetMenu(menuName = "Units/Unit Faction")]
    2. public class UnitFaction : ScriptableObject
    3. {
    4.     [SerializeField]
    5.     private List<UnitFaction> _friendlyFactions = new();
    6.    
    7.     public bool IsFriendlyFaction(UnitFaction unitFaction)
    8.     {
    9.         if (unitFaction == this)
    10.         {
    11.             return true;
    12.         }
    13.        
    14.         return _friendlyFactions.Contains(unitFaction);
    15.     }
    16. }
     
    Bunny83 likes this.
  7. Pytchoun

    Pytchoun

    Joined:
    Apr 12, 2015
    Posts:
    203
    Thanks

    I don't understand the difference between this 2 lines.

    Code (CSharp):
    1. if (unitFaction == this)
    2.         {
    3.             return true;
    4.         }
    5.      
    6.         return _friendlyFactions.Contains(unitFaction);
     
  8. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,934
    First part checks if the passed in reference is the same reference the call was made on. Ergo, are they same faction (in which case they're friendly).

    Otherwise, it returns whether or not the friendly factions collection contains the passed in reference. Again, if it contains a match, it's friendly, otherwise they're not.
     
  9. Pytchoun

    Pytchoun

    Joined:
    Apr 12, 2015
    Posts:
    203
    Ok, thanks.