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...
.
所以即使在默认的timeScale
a
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 的其他“方式”而无需编写重复代码
我在游戏中有一个脚本可以击晕目标并将其抛向空中。问题是,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...
.
所以即使在默认的timeScale
a
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 的其他“方式”而无需编写重复代码