无法将InvokeRepeating与方法参数一起使用.我该如何解决? [英] Cannot use InvokeRepeating with method parameters. How do I work around this?

查看:616
本文介绍了无法将InvokeRepeating与方法参数一起使用.我该如何解决?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实施随时间推移而造成的损害的系统,但是Unity一直在说试图调用方法...无法被调用."我想调用的方法使用参数"Collider coll",但是根据我的研究,如果该方法具有参数,则无法调用.

I'm trying to implement a damage over time system, but Unity keeps saying "Trying to Invoke method...Couldn't be Called." The method I want to call uses the parameters "Collider coll", but from my research you can't invoke if the method has said paremters.

这是我的代码:

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%,这太快了.我应该如何解决?

My goal is to get the OnTriggerEnter function to loop ever 1/4 of a second (or lower possibly). Current upon entering a collider my health is drained by 60% in about a second which is far too fast. How should I work around this?

推荐答案

您不能将InvokeRepeatingOnTriggerEnter一起使用,因为它是触发器,这意味着一旦其持有人进入,它将触发一次. 另外,InvokeRepeating表示您要继续连续重复操作,而在这里情况并非如此.您希望触发一次,然后随着时间的推移删除health points.

You can't use InvokeRepeating with OnTriggerEnter, because it's a trigger, which means it will trigger once when entrance of its holder occured. Also InvokeRepeating means that you want to keep repeating an action continously which is not the case here. You want your trigger to occur once and then remove health points over time.

Unity3DIEnumerable和称为Coroutineyield关键字进行自定义用法,该关键字始终返回IEnumerator.怎么运行的?它会在我们的Coroutine中的每个yield上返回控制权,然后返回到它提供控制权的确切点,而不是从头开始执行函数.

Unity3D makes custom usage of IEnumerable and yield keyword called Coroutine that always returns an IEnumerator. How it works? It will return control on every yield there is in our Coroutine and then will go back to exact point where it gave back control instead of starting function execution from scratch.

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.上面的代码只是有关如何处理此类情况的简单示例.

There's of course room for improvement in this Coroutine. You can pass parameters to it, same as you can to any other method in C#. Also you can implement other invervals that are not hardcoded. Code above is just a simple example on how to deal with such scenarios.

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()停止当前处于活动状态的所有协程.

To stop Coroutine somewhere else from code use StopCoroutine("DamageOverTimeCoroutine") to stop certain coroutine type or StopAllCoroutines() to stop all coroutines that are active now.

这篇关于无法将InvokeRepeating与方法参数一起使用.我该如何解决?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆