简体   繁体   English

为什么我的函数在 OnTriggerStay 中运行两次?

[英]Why is my function runs twice in OnTriggerStay?

I have a simple game in Unity .我在Unity 中有一个简单的游戏。

The situation is like if I kill an enemy, it drops a pickupable Health.这种情况就像我杀死一个敌人,它会掉落一个可拾取的生命值。 In the OnTriggerEnter , I handle the player collision with the health, and if the player misses health, it heals a certain amount.OnTriggerEnter 中,我处理玩家与生命值的碰撞,如果玩家错过生命值,它会恢复一定数量的生命值。 (70 exactly) (正好 70)

When player is standing on the health while at maximum health, it does nothing.当玩家在最大生命值时站在生命值上时,它什么也不做。 But if player got damaged while standing on the health, the health should also be picked up, that is where OnTriggerStay comes in.但是如果玩家在站在生命值上时受到伤害,生命值也应该被捡起,这就是OnTriggerStay 的用武之地。

There I constantly check if the player needs heeling, if do, do the healing, and destroy the heal object.在那里我不断检查玩家是否需要倾斜,如果需要,进行治疗,并摧毁治疗对象。 My problem is that it runs twice.我的问题是它运行了两次。 It heals the amount twice to the player.它为玩家治疗两次。 No matter what I do, the function I call in OnTriggerStay is gonna run twice.无论我做什么,我在OnTriggerStay 中调用的函数都会运行两次。 Why is that?这是为什么? Anybody knows the solution?有人知道解决方案吗?

Here is the part of my Player.cs file, and my Heal.cs file:这是我的 Player.cs 文件和 Heal.cs 文件的一部分:

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

public class Player : MonoBehaviour
{
  //HP and MANA system
    [SerializeField]
    private int playerHealth;
    [SerializeField]
    private int playerMaxHealth = 100;
    [SerializeField]
    private Transform Healthbar;

    private void OnTriggerStay(Collider other)
    {
        if (other.tag == "Enemy")
        {
            timer += Time.deltaTime;
            if (timer > attackSpeed)
            {
                Enemy enemy = other.GetComponent<Enemy>();
                if (enemy != null)
                {
                    enemy.DamageEnemy(playerDamage);
                }
                timer = 0.0f;
            }
        }
        if (other.tag == "PatrollingEnemy")
        {
            timer += Time.deltaTime;
            if (timer > attackSpeed)
            {
                PatrollingEnemy enemy = other.GetComponent<PatrollingEnemy>();
                if (enemy != null)
                {
                    enemy.DamageEnemy(playerDamage);
                }
                timer = 0.0f;
            }
        }
        if (other.tag == "Heal")
        {
            heal(other, false);

        }
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Heal")
        {
            heal(other, false);
        }
        else if (other.tag == "HealthPotion")
        {
            heal(other, true);
        }
    }
    private void heal(Collider other, bool isPotion)
    {

        dynamic heal;
        if (isPotion)
        {
            heal = other.GetComponent<HealthPotion>();
        }
        else
        {
            heal = other.GetComponent<Heal>();
        }
        if (playerHealth < playerMaxHealth && heal != null)
        {
            addHealthToPlayer(heal.HealAmount);
            Destroy(other.gameObject);
        }
    }

    private void addHealthToPlayer(int amount)
    {

        playerHealth += amount;
        if (playerHealth > playerMaxHealth)
        {
            playerHealth = playerMaxHealth;
        }
        rescaleHealthBar();
    }

    private void rescaleHealthBar()
    {
        Healthbar.transform.localScale = new Vector3((float)playerHealth / (float)playerMaxHealth, 1.0f, 1.0f);
    } 
}


public class Heal : MonoBehaviour
{
    float timer = 0.0f;
    float destroyTimer = 0.0f;
    float timeWhenDestroy = 15f;
    Vector3 rotation = new Vector3(0, 45, 0);

    private int healAmount = 70;
    public int HealAmount
    {
        get
        {
            return healAmount;
        }
    }

    void Update()
    {
        timer += Time.deltaTime;
        destroyTimer += Time.deltaTime;
        if (destroyTimer > timeWhenDestroy)
        {
            Destroy(this.gameObject);
        }
        transform.Rotate(rotation * Time.deltaTime);
        if (timer < 1.0f)
        {
            transform.Translate(Vector3.up * Time.deltaTime);
        }
        if (timer > 1.0f)
        {
            transform.Translate(-Vector3.up * Time.deltaTime);
        }
        if (timer > 2.0f)
        {
            timer = 0.0f;
        }
    }
}

https://docs.unity3d.com/ScriptReference/Object.Destroy.htmlhttps://docs.unity3d.com/ScriptReference/Object.Destroy.html

Maybe both your events (Enter & Stay) are fired during that frame ?也许您的两个事件(进入和停留)都在该帧期间被触发?

https://docs.unity3d.com/ScriptReference/Collider.OnTriggerStay.html https://docs.unity3d.com/ScriptReference/Collider.OnTriggerStay.html

OnTriggerStay is called almost all the frames for every Collider other that is touching the trigger. OnTriggerStay 几乎在所有接触触发器的碰撞器的所有帧中都被调用。 The function is on the physics timer so it won't necessarily run every frame.该功能位于物理计时器上,因此不一定每帧都运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM