Unity2D 在玩家转动时使用协程进行跟踪?
Unity2D using coroutines for tracking when the player is turning?
我正在使用骨架来为播放器设置动画。当玩家转向时,我有 3 个基本骨架可以转换:
- 个人资料中的玩家,
- 玩家转向和
- 玩家面对镜头
向左或向右,渲染器只是使用以下方式渲染镜像:
if (movement > 0) transform.localScale = new Vector2(1f, 1f);
if (movement < 0) transform.localScale = new Vector2(-1f, 1f);
然而,捕捉玩家从右向左移动(或反之亦然)的中间状态被证明是棘手的。
我设置了 3 个渲染器来运行如下:
void Start()
{
rightRenderer.enabled = true;
turningRenderer.enabled = false;
centerRenderer.enabled = false;
}
并且我一直在假设协程可用于测量 Input.GetAxis("Horizontal");
从左到右(或反之亦然)的移动。所以我根据以下内容整理了各种实验:
private List<float> trackedMovement = new List<float>();
private bool isTurning;
private float speed = 0f;
private int turningCounter = 0;
public IEnumerator countdownTurn()
{
while (0 < turningCounter--)
{
if (turningCounter == 0)
{
StopCoroutine("countdownTurn");
break;
}
yield return new WaitForSeconds(0.2f);
}
}
public IEnumerator turn()
{ // speed can be between 0 and 2.5f;
if (speed > 0 && speed <= 0.5f)
{
while (speed != 0)
{
trackedMovement.Add(movement);
trackedMovement.ForEach(f =>
{
if (
((f > 0 && movement < 0) ||
(f < 0 && movement > 0)))
{
isTurning = true;
trackedMovement = new List<float>();
turningCounter = 5;
StartCoroutine("countdownTurn");
}
});
yield return new WaitForSeconds(0.02f);
}
}
}
void Update()
{
StartCoroutine("turn");
speed = defaultAnimator.GetFloat("Speed");
turn();
}
我脑子里的理论是 turningCounter 可以通过数字显示玩家的状态
假设我从左向右移动:
turningCounter = 4
玩家正在从左侧转向镜头。
rightRenderer.enabled = false;
turningRenderer.enabled = true;
centerRenderer.enabled = false;
turningCounter = 3 || 2
玩家正对着镜头。
rightRenderer.enabled = false;
turningRenderer.enabled = false;
centerRenderer.enabled = true;
turningCounter = 1
玩家正在从镜头转向右侧。
rightRenderer.enabled = false;
turningRenderer.enabled = true;
centerRenderer.enabled = false;
turningCounter = 0
玩家完全面向右侧。
rightRenderer.enabled = true;
turningRenderer.enabled = false;
centerRenderer.enabled = false;
我所有的实验都产生了不一致的结果。
如果我将渲染器例程放在子协程 countdownTurn
中,它们并不总是在玩家转向时触发 left/right。
如果我尝试在任何更新语句中测量转动计数器(我已经尝试过标准、固定和默认但没有太大成功),我会得到关于 turningCounter 值的陈旧反馈(即它有时会给我一些倒计时,但不是倒计时的全部]。
所以我的问题是:
协程是解决这个问题的最佳方式吗?如果是这样,是否有任何关于我如何从他们那里获得干净一致的转向计数器值的建议?
如果协程 不是 一个好的解决方案,人们是否采用了任何其他方法来创建所需的结果?
[编辑] 按照@Everts 的建议,使用当前局部尺度作为计算方向变化的基础。
if localscale.x < 0
and movement > 0
那么我们可以推测玩家想要转弯(对于这个人为的例子)。 localscale.x > 0
和 movement < 0
.
也是如此
因此我们能够起草以下更新(我在此处附上一个简化版本,忽略了蹲伏机制等):
void Update()
{
movement = Input.GetAxis("Horizontal");
if (((transform.localScale.x > 0 && movement < 0) ||
(transform.localScale.x < 0 && movement > 0))
&& !isTurning)
{
isTurning = true;
turningCounter = 5;
StartCoroutine("countdownTurn"); // simply ticks down turningCounter every 0.n seconds
}
if (turningCounter == 3) setRenderDirection(); // ie. routine for transforming localscale (mirroring the image)
// show player in profile at end of counter
profileRenderer.enabled = turningCounter < 1;
// show player turning towards camera on 4 and away from camera on 1
turningRenderer.enabled = turningCounter == 4 || turningCounter == 1;
// show player looking dead center for 2 counts
centerRenderer.enabled = turningCounter == 2 || turningCounter == 3;
if (turningCounter < 1)
{
isTurning = false;
defaultAnimator.SetBool("isTurning", false);
}
}
我正在使用骨架来为播放器设置动画。当玩家转向时,我有 3 个基本骨架可以转换:
- 个人资料中的玩家,
- 玩家转向和
- 玩家面对镜头
向左或向右,渲染器只是使用以下方式渲染镜像:
if (movement > 0) transform.localScale = new Vector2(1f, 1f);
if (movement < 0) transform.localScale = new Vector2(-1f, 1f);
然而,捕捉玩家从右向左移动(或反之亦然)的中间状态被证明是棘手的。
我设置了 3 个渲染器来运行如下:
void Start()
{
rightRenderer.enabled = true;
turningRenderer.enabled = false;
centerRenderer.enabled = false;
}
并且我一直在假设协程可用于测量 Input.GetAxis("Horizontal");
从左到右(或反之亦然)的移动。所以我根据以下内容整理了各种实验:
private List<float> trackedMovement = new List<float>();
private bool isTurning;
private float speed = 0f;
private int turningCounter = 0;
public IEnumerator countdownTurn()
{
while (0 < turningCounter--)
{
if (turningCounter == 0)
{
StopCoroutine("countdownTurn");
break;
}
yield return new WaitForSeconds(0.2f);
}
}
public IEnumerator turn()
{ // speed can be between 0 and 2.5f;
if (speed > 0 && speed <= 0.5f)
{
while (speed != 0)
{
trackedMovement.Add(movement);
trackedMovement.ForEach(f =>
{
if (
((f > 0 && movement < 0) ||
(f < 0 && movement > 0)))
{
isTurning = true;
trackedMovement = new List<float>();
turningCounter = 5;
StartCoroutine("countdownTurn");
}
});
yield return new WaitForSeconds(0.02f);
}
}
}
void Update()
{
StartCoroutine("turn");
speed = defaultAnimator.GetFloat("Speed");
turn();
}
我脑子里的理论是 turningCounter 可以通过数字显示玩家的状态
假设我从左向右移动:
turningCounter = 4
玩家正在从左侧转向镜头。
rightRenderer.enabled = false;
turningRenderer.enabled = true;
centerRenderer.enabled = false;
turningCounter = 3 || 2
玩家正对着镜头。
rightRenderer.enabled = false;
turningRenderer.enabled = false;
centerRenderer.enabled = true;
turningCounter = 1
玩家正在从镜头转向右侧。
rightRenderer.enabled = false;
turningRenderer.enabled = true;
centerRenderer.enabled = false;
turningCounter = 0
玩家完全面向右侧。
rightRenderer.enabled = true;
turningRenderer.enabled = false;
centerRenderer.enabled = false;
我所有的实验都产生了不一致的结果。
如果我将渲染器例程放在子协程 countdownTurn
中,它们并不总是在玩家转向时触发 left/right。
如果我尝试在任何更新语句中测量转动计数器(我已经尝试过标准、固定和默认但没有太大成功),我会得到关于 turningCounter 值的陈旧反馈(即它有时会给我一些倒计时,但不是倒计时的全部]。
所以我的问题是:
协程是解决这个问题的最佳方式吗?如果是这样,是否有任何关于我如何从他们那里获得干净一致的转向计数器值的建议? 如果协程 不是 一个好的解决方案,人们是否采用了任何其他方法来创建所需的结果?
[编辑] 按照@Everts 的建议,使用当前局部尺度作为计算方向变化的基础。
if localscale.x < 0
and movement > 0
那么我们可以推测玩家想要转弯(对于这个人为的例子)。 localscale.x > 0
和 movement < 0
.
因此我们能够起草以下更新(我在此处附上一个简化版本,忽略了蹲伏机制等):
void Update()
{
movement = Input.GetAxis("Horizontal");
if (((transform.localScale.x > 0 && movement < 0) ||
(transform.localScale.x < 0 && movement > 0))
&& !isTurning)
{
isTurning = true;
turningCounter = 5;
StartCoroutine("countdownTurn"); // simply ticks down turningCounter every 0.n seconds
}
if (turningCounter == 3) setRenderDirection(); // ie. routine for transforming localscale (mirroring the image)
// show player in profile at end of counter
profileRenderer.enabled = turningCounter < 1;
// show player turning towards camera on 4 and away from camera on 1
turningRenderer.enabled = turningCounter == 4 || turningCounter == 1;
// show player looking dead center for 2 counts
centerRenderer.enabled = turningCounter == 2 || turningCounter == 3;
if (turningCounter < 1)
{
isTurning = false;
defaultAnimator.SetBool("isTurning", false);
}
}