不能将InvokeRepeating与方法参数一起使用.我该如何解决这个问题

本文关键字:何解决 解决 问题 InvokeRepeating 方法 参数 一起 不能 | 更新日期: 2023-09-27 18:28:39

我正试图实现一个随时间损坏的系统,但Unity一直在说"正在尝试调用方法…无法调用。"我想调用的方法使用参数"Collider coll",但根据我的研究,如果该方法说了参数,你就无法调用。

这是我的代码:

using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;
public class DamageOverTime : MonoBehaviour
{
    public int PHP; //PHP = Player Health from PlayerHealth.cs script.
    public int Damage; //Amount of damage.
    public int DamageOverTime; //Damage over time.
    public float DamageInterval_DOT = .25f; //Damage interval for damage over time.
    public string Level;
    PlayerHealth player;
    void Start()
    {
        player = GameObject.Find("Player").GetComponent<PlayerHealth>();
        InvokeRepeating("OnTriggerEnter", DamageInterval_DOT, DamageInterval_DOT);
    }
    void Update()
    {
        PHP = GameObject.Find("Player").GetComponent<PlayerHealth>().PlayerHP;
        if (PHP <= 0)
        {
            SceneManager.LoadScene(Level);
        }
    }
    void OnTriggerEnter(Collider coll)
    {
        if (coll.gameObject.tag == "Player")
        {
            GameObject.Find("Player").GetComponent<PlayerHealth>().PlayerHP = PHP - Damage;
        }
        if (coll.gameObject.tag == "Ball")
        {
            gameObject.SetActive(false);
            SceneManager.LoadScene(Level);
        }
    }
}

我的目标是让OnTriggerEnter函数循环1/4秒(或更低)。当电流进入对撞机时,我的健康在大约一秒钟内耗尽了60%,这太快了。我应该如何解决这个问题?

不能将InvokeRepeating与方法参数一起使用.我该如何解决这个问题

不能将InvokeRepeatingOnTriggerEnter一起使用,因为它是一个触发器,这意味着当其持有者进入时,它将触发一次。另外,InvokeRepeating意味着你希望不断重复一个动作,而这里的情况并非如此。您希望触发器发生一次,然后随着时间的推移删除health points

解决方案-Coroutine

Unity3D自定义使用IEnumerableyield关键字Coroutine,后者总是返回IEnumerator。它是如何工作的?它将返回对Coroutine中的每个yield的控制,然后返回到它返回控制的确切点,而不是从头开始执行函数。

代码:

void OnTriggerEnter(Collider coll)
{
    if (coll.gameObject.tag == "Player")
    {
        StartCoroutine("DamageOverTimeCoroutine");
    }
    if (coll.gameObject.tag == "Ball")
    {
        gameObject.SetActive(false);
        SceneManager.LoadScene(Level);
    }
}
public IEnumerator DamageOverTimeCoroutine()
{
    var dotHits = 0;
    while (dotHits < 4)
    {
        //Will remove 1/4 of Damage per tick
        GameObject.Find("Player").GetComponent<PlayerHealth>().PlayerHP -= Damage / 4;
        dotHits++;
        //Will return control over here
        yield return new WaitForSeconds(DamageInterval_DOT);
        //And then control is returned back here once 0.25s passes
    }
}

这个Coroutine当然还有改进的空间。您可以将参数传递给它,就像传递给C#中的任何其他方法一样。此外,您还可以实现其他非硬编码的inverval。上面的代码只是关于如何处理此类场景的一个简单示例。

随着时间的推移持续损坏

public IEnumerator DamageOverTimeCoroutine()
{
    var dotHits = 0;
    var player = GameObject.Find("Player").GetComponent<PlayerHealth>();
    while (true)
    {
        //Stop removing damage, player is dead already
        if (player.PlayerHP <= 0)
            yield break;
        //Will remove 5 Damage per tick
        player.PlayerHP -= 5;
        dotHits++;
        //Will return control over here
        yield return new WaitForSeconds(DamageInterval_DOT);
        //And then control is returned back here once 0.25s passes
    }
}

要从代码中的其他地方停止Coroutine,请使用StopCoroutine("DamageOverTimeCoroutine")停止某些协程类型,或使用StopAllCoroutines()停止所有当前活动的协程。