Как проверить тег Unity C#

При стрельбе запускается луч, при попадании в любой объект с колайдером он спавнит эффект попадания в моем случае, след от пули, мне нужно сделать так, чтобы при попадании в объект с тегом Person у меня спавнился эффект крови и потом пропадал, не понимаю как это сделать, надеюсь на вашу помощь.

Вот сама реализация кода стрельбы для игры на движке Unity.

using System.Collections;
using UnityEngine;

public class Weapon : MonoBehaviour
{
    public float damage = 21f;
    public float fireRate = 1f;
    public float force = 155f;
    public float range = 15f;
    public ParticleSystem hitFlash;
    public ParticleSystem muzzleFlash;
    public Transform bulletSpawn;
    public AudioClip shotSFX;
    public AudioSource _audioSource;
    public GameObject hitEffect;
    public GameObject Gilza;
    public float GilzaForce = 5f;

    public Camera _cam;
    private float nextFire = 0f;
    public GameObject BloodEffect;


    void Update()
    {
        if (Input.GetButton("Fire1") && Time.time > nextFire)
        {
            nextFire = Time.time + 1f / fireRate;
            Shoot();
            GilzaF();
        }
    }

    void Shoot()
    {
        
          
        _audioSource.PlayOneShot(shotSFX);
        muzzleFlash.Play();

        RaycastHit hit;

        if (Physics.Raycast(_cam.transform.position,_cam.transform.forward,out hit,range))
        {
            Debug.Log("Попадание в обьект "+ hit.collider);

        

            
            GameObject impact = Instantiate(hitEffect, hit.point, Quaternion.LookRotation(hit.normal));
            

            if(hit.rigidbody !=null)
            {
                 hit.rigidbody.AddForce(-hit.normal * force);
            }
        }
    }

void GilzaF()
{
     Instantiate(Gilza,bulletSpawn.position, bulletSpawn.rotation);
     {  
         Gilza.GetComponent<Rigidbody>().AddForce(bulletSpawn.forward * GilzaForce, ForceMode.Impulse);
     }
     
}

Ответы (1 шт):

Автор решения: Yaroslav

Суп нужно отделять от мух. Бизнес логика поведения, визуал и управление это должны быть разные классы.

Класс Weapon должен отвечать ТОЛЬКО за стрельбу и ни за что больше. Тут стоит использовать корутину.

public class Weapon : MonoBehaviour
{
    public event Action Shot;
    public event Action<RaycastHit> OnHit;

    [SerializeField] private float _damage = 21f;
    [SerializeField] private float _fireRate = 1f;
    [SerializeField] private float _distance = 15f;
    [SerializeField] private float _pushPower = 15f;
    [Space]
    [SerializeField] private Transform _firePoint;

    private IEnumerator _shootProcess;
    private bool _attack;

    public void StartShoot ()
    {
        _attack = true;
        if (_shootProcess != null)
            return;
        _shootProcess = ShootProcess();
        StartCoroutine(_shootProcess);
    }

    public void StopShoot ()
    {
        _attack = false;
    }

    private IEnumerator ShootProcess ()
    {
        while (_attack)
        {
            Fire();
            yield return new WaitForSeconds(_fireRate); 
        }
        _shootProcess = null;
    }

    private void Fire ()
    {
        if (Physics.Raycast(_firePoint.position, _firePoint.forward, out RaycastHit hit, _distance))
        {
            GameObject target = hit.collider.gameObject;
            if (target.TryGetComponent(out IDamagable dTarget))
                dTarget.ApplyDamage(_damage);
            if (_pushPower > 0 && target.TryGetComponent(out Rigidbody body))
                body.AddForce(-hit.normal * _pushPower);
            OnHit?.Invoke(hit);
        }
        Shot?.Invoke();
    }
}

Визуал может получать калбеки через события. Теги не используются вообще из-за того что это строковый литерал в котором можно ошибиться, тяжело искать баги и ОЧЕНЬ трудно что-то поменять.

С геометрией уровня всё просто, декали с частами. Что касается реакции других объектов на попадание, то это не дело оружия, кровоточит не пуля! Цели могут пускать кровь, брызки, лужи и тд, но причиной может быть всё что угодно, пули, шипы, удар тяжёлым и тупым, а цвета могут быть от красного до серобуромалонового или не пускать ничего, потому что это какой-нибудь скелет, который не кровь пускает а осколки костей. В связи с чем за реакцией на ранение должна отвечать сама цель, один из её компонентов, желательно под каким-нибудь интерфейсом, поскольку их может быть много разных и не только у юнитов, но и декораций.

[RequireComponent(typeof(Weapon))]
public class WeaponView : MonoBehaviour
{
    [SerializeField] private ParticleSystem _muzzleFlash;
    [SerializeField] private AudioSource _audio;
    [Space]
    [SerializeField] private Transform _sleevePoint;
    [SerializeField] private GameObject _sleeveTemplate;
    [SerializeField] private float _sleeveForce = 5;
    [Space]
    [SerializeField] private GameObject _decalTemplate;
    private Weapon _weapon;

    private void OnEnable ()
    {
        _weapon = GetComponent<Weapon>();
        _weapon.Shot += OnShot;
        _weapon.OnHit += OnHit;
    }

    private void OnDisable ()
    {
        _weapon.Shot -= OnShot;
        _weapon.OnHit -= OnHit;
    }

    private void OnShot ()
    {
        _muzzleFlash?.Play();
        _audio?.PlayOneShot(_audio.clip);
        SpawnSleeve();
    }

    private void OnHit (RaycastHit hit)
    {
        if (hit.collider.gameObject.GetComponent<Rigidbody>() == false)
            OnHitGeometry(hit);
        if (hit.collider.gameObject.TryGetComponent(out IHitReaction target))
            target.Hit(hit.point, -hit.normal);
    }

    private void SpawnSleeve ()
    {
        var sleeve = Instantiate(_sleeveTemplate, _sleevePoint.position, _sleevePoint.rotation);
        if (sleeve.TryGetComponent(out Rigidbody body))
            body.AddForce(sleeve.transform.forward * _sleeveForce);
    }

    private void OnHitGeometry (RaycastHit hit)
    {
        Instantiate(_decalTemplate, hit.point, Quaternion.LookRotation(hit.normal));
    }
}
→ Ссылка