我想随着时间造成法术伤害。所以这是我的代码:

public class Spell : MonoBehaviour
 {
    public float damage = 1.0f;
    public bool ignoreCaster = true;
    public float delayBeforeCasting = 0.4f;
    public float applyEveryNSeconds = 1.0f;
    public int applyDamageNTimes = 5;

    private bool delied = false;

    private int appliedTimes = 0;
    void OnTriggerStay(Collider other)
    {
        IDamageable takeDamage = other.gameObject.GetComponent<IDamageable>();
        if(takeDamage != null)
        {
            StartCoroutine(CastDamage(takeDamage));
        }
    }

    IEnumerator CastDamage(IDamageable damageable)
    {
        if(!delied)
        {
            yield return new WaitForSeconds(delayBeforeCasting);
            delied = true;
        }

        while(appliedTimes < applyDamageNTimes)
        {
            damageable.TakeDamage(damage);
            yield return new WaitForSeconds(applyEveryNSeconds);
            appliedTimes++;
        }
    }
}


问题是while从哪里开始。我想检查是否appliedTimes < applyDamageNTimes,然后确定是否确实造成损坏,请等待延迟(applyEveryNSeconds),然后再次检查,但我对协程不方便,由于某种原因,它没有这样做。

这是工作代码。如果有人需要,还可以寻找其他答案!

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

public class Spell : MonoBehaviour
{
    public float damage = 1.0f;
    public bool ignoreCaster = true;
    public float delayBeforeCasting = 0.0f;
    public float applyEveryNSeconds = 1.0f;
    public int applyDamageNTimes = 1;

    private bool delied = false;

    private int appliedTimes = 0;

    private bool test = false;
    void OnTriggerStay(Collider other)
    {
        IDamageable takeDamage = other.gameObject.GetComponent<IDamageable>();
        if(takeDamage != null)
        {
            StartCoroutine(CastDamage(takeDamage));
        }
    }

    IEnumerator CastDamage(IDamageable damageable)
    {
        if(!test && appliedTimes <= applyDamageNTimes || !test && applyEveryNSeconds == 0)
        {
            test = true;
            if(!delied)
            {
                yield return new WaitForSeconds(delayBeforeCasting);
                delied = true;
            }
            else
            {
                yield return new WaitForSeconds(applyEveryNSeconds);
            }
            damageable.TakeDamage(damage);
            appliedTimes++;
            test = false;
        }
    }
}

最佳答案

OnTriggerStay称为每帧2个对象发生碰撞的帧。这意味着CastDamage协程的异步实例在每一帧都被调用。所以发生的是,您每秒受到的损坏很大,每秒模拟没有任何损坏,呵呵。

因此,将OnTriggerStay更改为OnTriggerEnter。

根据其类型,我宁愿创建一个DPS脚本并将其应用于游戏对象,以便...


法术击中目标
AddComponent ();


然后,MyDpsSpell每隔N秒就会对其所在的对象造成一次损坏,并在完成后将其自身删除:

// Spell.cs

void OnTriggerEnter(Collider col) {
    // if you don't want more than 1 dps instance on an object, otherwise remove if
    if (col.GetComponent<MyDpsAbility>() == null) {
        var dps = col.AddComponent<MyDpsAbility>();
        dps.Damage = 10f;
        dps.ApplyEveryNSeconds(1);
        // and set the rest of the public variables
    }
}


// MyDpsAbility.cs

public float Damage { get; set; }
public float Seconds { get; set; }
public float Delay { get; set; }
public float ApplyDamageNTimes { get; set; }
public float ApplyEveryNSeconds { get; set; }

private int appliedTimes = 0;

void Start() {
    StartCoroutine(Dps());
}

IEnumerator Dps() {
    yield return new WaitForSeconds(Delay);

    while(appliedTimes < ApplyDamageNTimes)
    {
        damageable.TakeDamage(damage);
        yield return new WaitForSeconds(ApplyEveryNSeconds);
        appliedTimes++;
    }

    Destroy(this);
}


如果这是一个光环咒语,单位每秒会受到一次伤害,则可以执行以下操作:

float radius = 10f;
float damage = 10f;
void Start() {
    InvokeRepeating("Dps", 1);
}


void Dps() {
    // QueryTriggerInteraction.Collide might be needed
    Collider[] hitColliders = Physics.OverlapSphere(gameObject.position, radius);

    foreach(Collider col in hitColliders) {
        col.getComponent<IDamagable>().TakeDamage(10);
    }
}


https://docs.unity3d.com/ScriptReference/Physics.OverlapSphere.html

关于c# - 随时间推移而造成的损害,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44497565/

10-12 00:24
查看更多