Problem with Reload Script

Hi sorry for the distub but i was working on my new script for T.B.S. course( with Hugo Cardoso aka Code Monkey) and i have and issue, when in the scene i press the button for the reload the sound is functioning but all the units do the reload Action, i want the only unit selected execute the action but i cant find what is the problem in Script pls help me( and if you read the comment in in italain because im Italian too and to lazy to change language sorry).

this is the Script:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ReloadAction : BaseAction
{
[SerializeField] private AudioClip reloadSoundClip;
private AudioSource reloadSound;

public static event EventHandler OnReloadActionStarted;
public static event EventHandler OnReloadActionCompleted;

private float reloadTime = 0.9f;
private float stateTimer;

private void Start()
{
    reloadSound = GetComponent<AudioSource>();
    if (reloadSound != null)
    {
        reloadSoundClip = reloadSound.clip;
        reloadSound.playOnAwake = false;
    }
    else
    {
        // Gestisci il caso in cui l'AudioSource non è presente sull'oggetto
        Debug.LogWarning("AudioSource non trovato su " + gameObject.name);
    }
}

private void Update()
{
    if (!isActive) return;

    stateTimer -= Time.deltaTime;
    if (stateTimer <= 0f)
    {
        Reload();
        OnReloadActionCompleted?.Invoke(this, EventArgs.Empty);
        ActionComplete();
    }
}

public override string GetActionName()
{
    return "Reload";
}

public override void TakeAction(GridPosition gridPosition, Action onActionComplete)
{
    if (!unit.IsEnemy())
    {
        stateTimer = reloadTime;
        OnReloadActionStarted?.Invoke(this, EventArgs.Empty);
        ActionStart(onActionComplete);
    }
    else
    {
        // Non fare nulla se è un'IA nemica
        Debug.Log("IA nemica tentata di ricaricare");
        onActionComplete();
    }
}

public override List<GridPosition> GetValidActionGridPositionList()
{

    return new List<GridPosition> { unit.GetGridPosition() };
}

public override int GetActionPointCost()
{
    return 1; // Puoi cambiare questo valore in base alle tue esigenze
}

private void Reload()
{
    // Aggiungi la logica di ricarica qui
    if (reloadSoundClip != null)
    {
        reloadSound.Play();
    }
}

public override EnemyAIAction GetEnemyAIAction(GridPosition gridPosition)
{
    return null; // Non fornire un'azione per l'IA nemica
}

}

What does the OnReloadActionStarted and OnReloadActionCompleted events do?

it will activate the event in the Unit animator script, it works but whr the button is pressed all units start the action and i can’t understand the issue

Can you show the handlers?

public static event EventHandler OnReloadActionStarted;
public static event EventHandler OnReloadActionCompleted;

finnaly both are working i will paste immediatly look
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ReloadAction : BaseAction
{
[SerializeField] private AudioClip reloadSoundClip;
private AudioSource reloadSound;

public event EventHandler OnReloadActionStarted;
public event EventHandler OnReloadActionCompleted;

private float reloadTime = 0.6f;
private float stateTimer;

private void Start()
{
    reloadSound = gameObject.AddComponent<AudioSource>();
    if (reloadSoundClip != null)
    {
        reloadSound.clip = reloadSoundClip;
        reloadSound.playOnAwake = false;
    }
}

private void Update()
{
    if (!isActive) return;

    stateTimer -= Time.deltaTime;
    if (stateTimer <= 0f)
    {
        Reload();
        OnReloadActionCompleted?.Invoke(this, EventArgs.Empty);
        ActionComplete();
    }
}

public override string GetActionName()
{
    return "Reload";
}

public override void TakeAction(GridPosition gridPosition, Action onActionComplete)
{
    if (!unit.IsEnemy())
    {
        stateTimer = reloadTime;
        OnReloadActionStarted?.Invoke(this, EventArgs.Empty);
        ActionStart(onActionComplete);
    }
    else
    {
        // Non fare nulla se è un'IA nemica
        Debug.Log("IA nemica tentata di ricaricare");
        onActionComplete();
    }
}

public override List<GridPosition> GetValidActionGridPositionList()
{
    return new List<GridPosition> { unit.GetGridPosition() };
}

public override int GetActionPointCost()
{
    return 1; // Puoi cambiare questo valore in base alle tue esigenze
}

private void Reload()
{
    // Aggiungi la logica di ricarica qui
    if (reloadSoundClip != null)
    {
        reloadSound.Play();
    }
}

public override EnemyAIAction GetEnemyAIAction(GridPosition gridPosition)
{
    return null; // Non fornire un'azione per l'IA nemica
}

}

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UnitAnimator : MonoBehaviour
{
[SerializeField] private Animator animator;
[SerializeField] private Transform bulletProjectilePrefab;
[SerializeField] private Transform Muzzle;
[SerializeField] private Transform gunTransform;
[SerializeField] private Transform swordTransform;

private void Awake()
{
    if (TryGetComponent<MoveAction>(out MoveAction moveAction))
    {
        moveAction.OnStartMoving += MoveAction_OnStartMoving;
        moveAction.OnStopMoving += MoveAction_OnStopMoving;
    }

    if (TryGetComponent<ShootAction>(out ShootAction shootAction))
    {
        shootAction.OnShoot += ShootAction_OnShoot;
    }

    if (TryGetComponent<SwordAction>(out SwordAction swordAction))
    {
        swordAction.OnSwordActionStarted += SwordAction_OnSwordActionStarted;
        swordAction.OnSwordActionCompleted += SwordAction_OnSwordActionCompleted;
    }

    if (TryGetComponent<GrenadeAction>(out GrenadeAction grenadeAction))
    {
        grenadeAction.OnGrenadeActionStarted += GrenadeAction_GrenadeActionStarted;
        grenadeAction.OnGrenadeActionCompleted += GrenadeAction_GrenadeActionCompleted;
    }

    // Gestione eventi di ricarica con riferimento a un'istanza specifica
    if (TryGetComponent<ReloadAction>(out ReloadAction reloadAction))
    {
        reloadAction.OnReloadActionStarted += ReloadAction_OnReloadActionStarted;
        reloadAction.OnReloadActionCompleted += ReloadAction_OnReloadActionCompleted;
    }
}

// Eventi Azione Granata
private void GrenadeAction_GrenadeActionStarted(object sender, EventArgs e)
{
    animator.SetTrigger("Grenade");
}

private void GrenadeAction_GrenadeActionCompleted(object sender, EventArgs e)
{
    EquipGun();
}

// Eventi Ricarica Arma
private void ReloadAction_OnReloadActionStarted(object sender, EventArgs e)
{
    animator.SetTrigger("ReloadStart");
}

private void ReloadAction_OnReloadActionCompleted(object sender, EventArgs e)
{
    animator.SetTrigger("ReloadEnd");
    EquipGun(); // Equip gun after reload is completed
}

// Eventi azione Spada
private void Start()
{
    EquipGun();
}

private void SwordAction_OnSwordActionStarted(object sender, EventArgs e)
{
    EquipSword();
    animator.SetTrigger("SwordSlash");
}

private void SwordAction_OnSwordActionCompleted(object sender, EventArgs e)
{
    EquipGun();
}

// Eventi Azione Movimento
private void MoveAction_OnStartMoving(object sender, EventArgs e)
{
    animator.SetBool("IsSprint", true);
}

private void MoveAction_OnStopMoving(object sender, EventArgs e)
{
    animator.SetBool("IsSprint", false);
}

private void ShootAction_OnShoot(object sender, ShootAction.OnShootEventArgs e)
{
    animator.SetTrigger("Shoot");

    Transform bulletProjectileTransform = Instantiate(bulletProjectilePrefab, Muzzle.position, Quaternion.identity);
    BulletProjectile bulletProjectile = bulletProjectileTransform.GetComponent<BulletProjectile>();

    Vector3 targetUnitShootAtPosition = e.targetUnit.GetWorldPosition();
    targetUnitShootAtPosition.y = Muzzle.position.y;
    bulletProjectile.Setup(targetUnitShootAtPosition);
}

private void EquipSword()
{
    swordTransform.gameObject.SetActive(true);
    gunTransform.gameObject.SetActive(false);
}

private void EquipGun()
{
    swordTransform.gameObject.SetActive(false);
    gunTransform.gameObject.SetActive(true);
}

}

Finally its work sorry Bixarro for the disturb but im too happy, if needed can use and i give you thi one

public class ShootAction : BaseAction
{
[SerializeField] private AudioClip shootSoundClip;
private AudioSource HandGunShootSound;

public  static event EventHandler<OnShootEventArgs> OnAnyShoot;
public event EventHandler<OnShootEventArgs> OnShoot;

public class OnShootEventArgs : EventArgs
{
    public Unit targetUnit;
    public Unit shootingUnit;
}



private enum State
{
    Aiming,
    Shooting,
    Cooloff,
}

[SerializeField] private LayerMask obstaclesLayerMask;



private State state;
private int maxShootDistance = 7;
private float stateTimer;
private Unit targetUnit;
private bool canShootBullet;

// Gestione componente AudioSource a questo oggetto per la riproduzione dell'AudioClip
private void Start()
{
    HandGunShootSound = gameObject.AddComponent<AudioSource>();
    HandGunShootSound.playOnAwake = false; // Assicurati che l'AudioClip non venga riprodotto automaticamente all'avvio
    HandGunShootSound.clip = shootSoundClip; // Assegna l'AudioClip all'AudioSource
}



private void Update()
{
    if (!isActive)
    {
        return;
    }

    stateTimer -= Time.deltaTime;

    switch (state)
    {
        case State.Aiming:
            Vector3 aimDir = (targetUnit.GetWorldPosition() - unit.GetWorldPosition()).normalized;

            float rotateSpeed = 10f;
            transform.forward = Vector3.Lerp(transform.forward, aimDir, Time.deltaTime * rotateSpeed);
            break;
        case State.Shooting:
            if (canShootBullet)
            {
                Shoot();
                canShootBullet = false;
                
            }
            break;
        case State.Cooloff:
            break;
    }

    if (stateTimer <= 0f)
    {
        NextState();
    }
}

private void NextState()
{
    switch (state)
    {
        case State.Aiming:
            state = State.Shooting;
            float shootingStateTime = 0.1f;
            stateTimer = shootingStateTime;
            break;
        case State.Shooting:
            state = State.Cooloff;
            float coolOffStateTime = 0.5f;
            stateTimer = coolOffStateTime;
            break;
        case State.Cooloff:
            ActionComplete();
            break;
    }
}

private void Shoot()
{
    if (shootSoundClip != null)
    {
        HandGunShootSound.Play(); // Riproduci l'AudioClip
    }


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

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

    targetUnit.Damage(40);
    
}



public override string GetActionName()
{
    return "Shoot";
}

public override List<GridPosition> GetValidActionGridPositionList()
{
    GridPosition unitGridPosition = unit.GetGridPosition();
    return GetValidActionGridPositionList(unitGridPosition);
}

public List<GridPosition> GetValidActionGridPositionList(GridPosition unitGridPosition)
{
    List<GridPosition> validGridPositionList = new List<GridPosition>();

    for (int x = -maxShootDistance; x <= maxShootDistance; x++)
    {
        for (int z = -maxShootDistance; z <= maxShootDistance; z++)
        {
            GridPosition offsetGridPosition = new GridPosition(x, z);
            GridPosition testGridPosition = unitGridPosition + offsetGridPosition;

            if (!LevelGrid.Instance.IsValidGridPosition(testGridPosition))
            {
                continue;
            }

            int testDistance = Mathf.Abs(x) + Mathf.Abs(z);
            if (testDistance > maxShootDistance)
            {
                continue;
            }

            if (!LevelGrid.Instance.HasAnyUnitOnGridPosition(testGridPosition))
            {
                // Grid Position is empty, no Unit
                continue;
            }

            Unit targetUnit = LevelGrid.Instance.GetUnitAtGridPosition(testGridPosition);

            if (targetUnit.IsEnemy() == unit.IsEnemy())
            {
                // Both Units on same 'team'
                continue;
            }

            Vector3 unitWorldPosition = LevelGrid.Instance.GetWorldPosition(unitGridPosition);
            Vector3 shootDir = (targetUnit.GetWorldPosition() - unitWorldPosition).normalized;

            float unitShoulderHeight = 1.7f;
            if (Physics.Raycast(
                    unitWorldPosition + Vector3.up * unitShoulderHeight,
                    shootDir,
                    Vector3.Distance(unitWorldPosition, targetUnit.GetWorldPosition()),
                    obstaclesLayerMask))
            {
                // Blocked by an Obstacle
                continue;
            }

            validGridPositionList.Add(testGridPosition);
        }
    }

    return validGridPositionList;
}

public override void TakeAction(GridPosition gridPosition, Action onActionComplete)
{
    targetUnit = LevelGrid.Instance.GetUnitAtGridPosition(gridPosition);

    state = State.Aiming;
    float aimingStateTime = 1f;
    stateTimer = aimingStateTime;

    canShootBullet = true;

    ActionStart(onActionComplete);
}

public Unit GetTargetUnit()
{
    return targetUnit;
}

public int GetMaxShootDistance()
{
    return maxShootDistance;
}

public override EnemyAIAction GetEnemyAIAction(GridPosition gridPosition)
{
    Unit targetUnit = LevelGrid.Instance.GetUnitAtGridPosition(gridPosition);

    return new EnemyAIAction
    {
        gridPosition = gridPosition,
        actionValue = 100 + Mathf.RoundToInt((1 - targetUnit.GetHealthNormalized()) * 100f),
    };
}

public int GetTargetCountAtPosition(GridPosition gridPosition)
{
    return GetValidActionGridPositionList(gridPosition).Count;
}

}
its the my Version of ShootAction Scpit with the adding of sound maybe its a little improvement but very pleasant

These are not the handlers. I want to see the handlers. The bits that is subscribed to these and do the work

These are the handlers. The events are static so when this is handled, all the units handle it. You have to either not make it static (which I see you did) or check in the handler if the sender equals the attached unit.
Removing static from the events is what I would have suggested so, good job

Privacy & Terms