WaitForSeconds 未随 Time.TimeScale 缩放

WaitForSeconds is not scaling with Time.TimeScale

我在游戏中有一个脚本可以击晕目标并将其抛向空中。问题是,yield return new WaitForSeconds(0.01f),并通过扩展眩晕长度,根本不会随 Time.DeltaTime 缩放,即使它应该。如果游戏速度足够快,这会导致攻击永久击晕敌人。 相关代码如下:

void Start()
{
    coll = gameObject.GetComponent<Collider2D>();
    halfLength = stunLength / 2;
    baseColor = gameObject.GetComponent<SpriteRenderer>().color;
    StartCoroutine("Gust");
}

public IEnumerator Gust()
{
    coll.enabled = false;
    float sus = halfLength;
    while (halfLength > 0)
    {
        transform.position += new Vector3(0, halfLength * 0.05f, 0);
        halfLength -= 0.03f;
        yield return new WaitForSeconds(0.01f);
    }
    while (halfLength < sus)
    {
        transform.position += new Vector3(0, halfLength * -0.05f, 0);
        halfLength += 0.03f;
        yield return new WaitForSeconds(0.01f);
    }
    coll.enabled = true;
    StunEnd();
}

正在通过 UI 按钮在脚本之外更改 Time.TimeScale。任何帮助将不胜感激。

假设您的游戏以每秒 60 帧的速度运行。

也就是说两帧之间的最小时间已经是1 / 60 = 0.016666....

所以即使在默认的timeScalea

yield return new WaitForSeconds(0.01f);

已经比默认帧率短了,无论如何都会 yield => 这基本上等于使用

yield return null;

所以现在如果你加快你的游戏时间甚至更短,它仍然是相等的

yield return null;

yield 至少一帧!

我希望你现在明白这是怎么回事了。


与其尝试使用一些固定的时间间隔,不如直接使用帧并依赖于 Time.deltaTime

您可以尝试使用类似

的内容

如果你想按持续时间和特定位置偏移

// adjust this!
public Vector3 stunOffset = Vector3.up;

private IEnumerator MoveTo(Vector3 to, float duration)
{
    yield return MoveFromTo(transform.position, to, duration);
}

private IEnumerator MoveFromTo(Vector3 from, Vector3 to, float duration)
{
    for(var timePassed = 0f; timePassed < duration; timePassed += Time.deltaTime)
    {
        transform.position = Vector3.Lerp(from, to , timePassed / duration);
        yield return null;
    }

    transform.position = to;
}

public IEnumerator Gust()
{
    coll.enabled = false;
    float sus = halfLength;

    var initialPosition = transform.position;
    var targetPosition = initialPosition + stunOffset;

    yield return MoveTo(targetPosition, halfLength);

    yield return MoveTo(initialPosition halfLength);

    coll.enabled = true;
    StunEnd();
}

或者,如果您想以固定移动速度前进

// Adjust these
public float stunSpeed = 1f;
public Vector3 stunOffset = Vector3.up;

private IEnumerator MoveTo(Vector3 to, float speed)
{
    while(tranform.position != to)
    {
        transform.position = Vector3.MoveTowards(transform.position, to, speed * Time.deltaTime);
        yield return null;
    }

    transform.position = to;
}

public IEnumerator Gust()
{
    coll.enabled = false;
    float sus = halfLength;

    var initialPosition = transform.position;
    var targetPosition = (stunOinitialPosition + stunOffset;

    yield return MoveTo(targetPosition, stunSpeed);
    yield return MoveTo(initialPosition stunSpeed);

    coll.enabled = true;
    StunEnd();
}

也许你应该将控制的禁用和人群控制的“动画”分成两个单独的协程。

IEnumerator DisableControl()
{
coll.enabled = false;
yield return new WaitForSeconds(stunLength);
coll.enabled = true;
}

IEnumerator Gust()
{
    //Perform object manipulation/play animation
}

这样你就可以避免误用 waitforseconds 和 stunlocking 对象。 它还可以让您潜在地 re-use 眩晕逻辑并使用 crowd-controlling 的其他“方式”而无需编写重复代码