[英]How to change X object position smoothly while object with moving Y axis?
Object is moving by Y axis, i need to move X axis position smoothly. 物体在Y轴上移动,我需要平滑地移动X轴位置。
void FixedUpdate()
{
playerRigidbody.velocity = new Vector2(0.0f, 2.0f);
if (Input.GetKeyDown(KeyCode.RightArrow))
{
if (newBallPos != 2)
{
Vector3 pos1 = this.transform.position;
Vector3 pos2 = this.transform.position;
pos2.x += 1f;
StartCoroutine(Move_Routine(this.transform, pos1, pos2));
}
}
----
}
----
private IEnumerator Move_Routine(Transform transform, Vector3 from, Vector3 to)
{
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime;
transform.position = Vector3.Lerp(from, to, Mathf.SmoothStep(0f, 1f, t));
yield return null;
}
}
With this code. 有了这段代码。 X axis changes, but with old Y axis position and it create's kind of shaking for time X axis moves.
X轴发生变化,但是旧的Y轴位置会产生X轴移动时的抖动。
On arrow click, i need to change Object X position smoothly, while still moving by Y axis.(I need to change X position by 1) 在箭头上单击,我需要平滑地更改对象X位置,同时仍然按Y轴移动。(我需要将X位置改变1)
Appreciate for your help! 感谢您的帮助!
Try adding the x axis to Time.smoothDeltaTime;
尝试将x轴添加到
Time.smoothDeltaTime;
in this method, values are averaged over several frames for a more smooth looking effect, it is a preference but sometimes can make a noticeable difference. 在这种方法中,值在几帧上取平均值以获得更平滑的效果,这是一种偏好,但有时会产生明显的差异。
pos2.x += Time.smoothDeltaTime;
First as far as I understand you only want to smooth the X value of the position so you shoudl rather do 首先,据我所知,你只想平滑位置的X值,所以你应该这样做
private IEnumerator Move_Routine(Transform transform, float from, float to)
{
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime;
// only lerp the single float value
var currentX = Mathf.SmoothStep(from, to, t);
// let the current other two values unchanged
transform.position.x = currentX;
yield return null;
}
// Just to be sure there is no under/overshooting I would
// always set the fixed value in the end
transform.position.x = to;
}
However, another issue in your case is that you are dealing with RigidBody. 但是,您的另一个问题是您正在处理RigidBody。
You should not use transform.position =
on rigidbodies at all but rather either playerRigidbody.position =
or playerRigidbody.MovePosition(targetPosition)
你根本不应该在
playerRigidbody.position =
上使用transform.position =
而是使用playerRigidbody.position =
或者playerRigidbody.MovePosition(targetPosition)
A Coroutine is executed every Update
call but you should change rigidbodies only in FixedUpdate
=> you can use WaitForFixedUpdate
in your coroutine 每次
Update
调用都会执行一个Coroutine,但是你应该只在FixedUpdate
更改刚体=>你可以在你的协程中使用WaitForFixedUpdate
A third issue is that you might have multiple Coroutines running at the same time if you press the button again before the movement was finished. 第三个问题是,如果在移动完成之前再次按下按钮,则可能会同时运行多个Coroutines。 => you can solve this by a simply bool flag.
=>你可以通过简单的bool标志解决这个问题。 Alternatively if you want to allow input (eg for moving in the other direction you should
StopCoroutine
the current routine first) 或者,如果您想允许输入(例如,为了向另一个方向移动,您应
StopCoroutine
当前例程)
Therefore the jitter etc. So together: 因此抖动等因此在一起:
private bool alreadyLerping;
private void FixedUpdate()
{
playerRigidbody.velocity = new Vector2(0.0f, 2.0f);
if (Input.GetKeyDown(KeyCode.RightArrow))
{
// only do if not lerping laready otherwise input is ignored
if (newBallPos != 2 && !alreadyLerping)
{
var currentX = transform.position.x;
var targetX = currentX + 1.0f;
StartCoroutine(Move_Routine(currentX, targetX));
}
}
...
}
// I just added an optional duration value
// if you do not pass it it will be 1 second as you had it
// but this way you can still make it faster or slower without having
// to hardcode
// you also don't have to pass in the transform or if you do you should not call it transform
private IEnumerator Move_Routine(float from, float to, float duration = 1.0f)
{
if(alreadyLerping) yield break;
alreadyLerping = true;
var passedTime = 0f;
do
{
yield return new WaitForFixedUpdate();
var lerpfactor = passedTime / duration;
var currentX = Mathf.SmoothStep(from, to, lerpfactor);
playerRigidbody.MovePosition(new Vector3(currentX, transform.position.y, transform.position.z));
passedTime += Time.deltaTime;
} while (passedTime < duration);
// Just to be sure there is no under/overshooting I would
// always set the fixed value in the end
playerRigidbody.MovePosition(new Vector3(to, transform.position.y, transform.position.z));
// release the flag
alreadyLerping = false;
}
or if you want the StopCoroutine
variant 或者如果你想要
StopCoroutine
变种
private IEnumerator currentRoutine;
private void FixedUpdate()
{
playerRigidbody.velocity = new Vector2(0.0f, 2.0f);
if (Input.GetKeyDown(KeyCode.RightArrow))
{
// only do if not lerping laready otherwise input is ignored
if (newBallPos != 2)
{
var currentX = transform.position.x;
var targetX = currentX + 1.0f;
if(currentRoutine!=null) StopCoroutine(currentRoutine);
currentRoutine = Move_Routine(currentX, targetX);
StartCoroutine(currentRoutine);
}
}
...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.