unity3d OnTriggerEnter2D()多次触发TakeDamage()

ia2d9nvy  于 2023-05-01  发布在  其他
关注(0)|答案(1)|浏览(226)

我正在尝试创建多人游戏与网络游戏对象在主机上我只造成一次伤害,而在客户端上我造成的伤害约3-5次每击中。下面是我的enemyStats脚本:

public override void OnNetworkSpawn()
    {
        base.OnNetworkSpawn();
        singleton = this;
        health.Value = enemyData.HP;
        damage.Value = enemyData.Damage;

        // event
        MeleeCollision.onDamaged += TakeDamageServerRpc;

        health.OnValueChanged += (int previousHealth, int newHealth) =>
        {
            health.Value = newHealth;
        };
    }

    public override void OnNetworkDespawn()
    {
        base.OnNetworkDespawn();

        // event
        MeleeCollision.onDamaged -= TakeDamageServerRpc;
    }

    private void TakeDamage(int damageAmount)
    {
        health.Value -= damageAmount;
        Debug.Log("enemystats message: hit");
    }

    [ServerRpc]
    private void TakeDamageServerRpc(int damageAmount)
    {
        TakeDamage(damageAmount);
    }

和meleCillision脚本:

public static Action<int> onDamaged;

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.gameObject.CompareTag("Enemy"))
        {
            onDamaged?.Invoke(PlayerStats.singleton.damage.Value);
            Debug.Log("MeleeCollision message: hit");
        }
    }

有办法解决吗?
我试图在onTrigger函数中添加bool状态,但这不起作用
P.S.我发现问题是客户端每次点击会示例化大约5个斜杠预制件。下面是负责此操作的代码:

[Header("Attack")]
    [SerializeField] private GameObject slashPrefab;
    [SerializeField] private Transform spawnPoint;
    [SerializeField] private float attackDelay = 0.5f;
    private NetworkVariable<bool> isAttacked = new NetworkVariable<bool>(false);
    private Quaternion fixRotation = Quaternion.Euler(90, 0, 0);

    public override void OnNetworkSpawn()
    {
        base.OnNetworkSpawn();
        isAttacked.OnValueChanged += (bool previousValue, bool newValue) =>
        {
            isAttacked.Value = newValue;
            Debug.Log(isAttacked.Value);
        };
    }

    private void Update()
    {
        if (!IsOwner) return;
        if (Input.GetMouseButton(0) && !isAttacked.Value) AttackServerRpc(spawnPoint.position, spawnPoint.rotation, attackDelay);
    }

    private IEnumerator Attack(Vector3 position, Quaternion rotation, float delay)
    {
        isAttacked.Value = true;
        var prefab = Instantiate(slashPrefab, position, rotation * fixRotation);
        prefab.GetComponent<NetworkObject>().Spawn(true);
        yield return new WaitForSeconds(delay);
        isAttacked.Value = false;
    }

    [ServerRpc]
    private void AttackServerRpc(Vector3 position, Quaternion rotation, float delay)
    {
        StartCoroutine(Attack(position, rotation, delay));
    }
zyfwsgd6

zyfwsgd61#

@derHugo在他的评论是正确的。我认为同一次碰撞被处理了多次。我添加了浮动伤害冷却来存储冷却时间,并添加了一个字典来存储每个敌人的最后一次碰撞时间。
尝试一下,看看它是否解决了你的问题

public class MeleeCollision : MonoBehaviour
{
    public static Action<int> onDamaged;

    
    public float damageCooldown = 0.5f;
    private Dictionary<GameObject, float> lastHitTime;

    private void Awake()
    {
        lastHitTime = new Dictionary<GameObject, float>();
    }

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.gameObject.CompareTag("Enemy"))
        {
            if (!lastHitTime.ContainsKey(other.gameObject) || Time.time - lastHitTime[other.gameObject] > damageCooldown)
            {
                onDamaged?.Invoke(PlayerStats.singleton.damage.Value);
                lastHitTime[other.gameObject] = Time.time;
                Debug.Log("MeleeCollision message: hit");
            }
        }
    }
}

相关问题