C# 无法使用MoveToward或Lerp平滑移动gemeObject
我是一个极端的业余爱好者,目标很简单。在OnGui中,我有一个按钮。我想当按下这个按钮移动它所连接的游戏对象时,以平滑的方式向右移动一段距离。我已经成功地设定了我想要移动的距离,但我无法使移动平稳以挽救我的生命C# 无法使用MoveToward或Lerp平滑移动gemeObject,c#,unity3d,vector,C#,Unity3d,Vector,我是一个极端的业余爱好者,目标很简单。在OnGui中,我有一个按钮。我想当按下这个按钮移动它所连接的游戏对象时,以平滑的方式向右移动一段距离。我已经成功地设定了我想要移动的距离,但我无法使移动平稳以挽救我的生命 private void OnGUI() { if (GUI.Button(new Rect(165, 300, 150, 350), "right")) { var pos = transform.position;
private void OnGUI()
{
if (GUI.Button(new Rect(165, 300, 150, 350), "right"))
{
var pos = transform.position;
float rightMovement = pos.x + 0.5f;
Vector3 targetPosition = new Vector3(rightMovement, transform.position.y, transform.position.z);
while (Vector3.Distance(transform.position, targetPosition) > 0.1f)
{
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, targetPosition, step);
}
Debug.Log("Clicked rightMovement");
}
速度=5f这是我感觉最接近目标的地方。当前,它移动距离,但仅在单个帧中移动。我还尝试使用内部代码基本相同的IEnumerator,只是从OnGui内部调用said IEnumerator,但没有效果。主要问题是这个循环
while (Vector3.Distance(transform.position, targetPosition) > 0.1f)
{
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, targetPosition, step);
}
这将在一个步骤中移动对象,因为不会同时渲染任何帧。while会阻塞整个线程,直到它完成为止,我认为在这种情况下,它不会太长,然后在完成时渲染帧
此外,正如在注释中提到的,OnGUI在每帧中被调用多次,因此情况变得更糟 正如我还评论的那样,OnGUI是一种遗产,你不应该再使用它,除非你知道自己到底在做什么,怎么做 而是使用一个 如果我看对了,你想在按钮按下的时候移动 不幸的是,没有内置的按钮来处理诸如while按钮保持按下这样的事情,因此您必须使用和ipointernuphandler接口 将此类放在UI.Button对象上
正如您所意识到的,整个循环将在一帧内完成。IEnumerator方法是正确的。您能发布您的代码吗?OnGUI在每帧中被调用多次。Time.deltaTime是帧之间的时间。这可能是导致它不平滑的原因。不要使用OnGUI,因为它是遗留的。。。而是使用UI.Button
public class MoveButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler
{
public enum Alignment
{
Global,
Local
}
// Configure here the movement step per second in all three axis
public Vector3 moveStep;
// Here reference the object that shall be move by this button
public Transform targetObject;
// Configure here wether you want the movement in
// - Global = World-Space
// - Local = Object's Local-Space
public Alignment align;
private Button button;
private void Awake ()
{
button = GetComponent<Button>();
}
//Detect current clicks on the GameObject (the one with the script attached)
public void OnPointerDown(PointerEventData pointerEventData)
{
// Ignore if button is disabled
if(!button.interactible) return;
StartCoroutine (Move());
}
public void OnPointerUp(PointerEventData pointerEventData)
{
StopAllCoroutines();
}
public void OnPointerExit(PointerEventData pointerEventData)
{
StopAllCoroutines();
}
// Actually not really needed but I'm not sure right now
// if it is required for OnPointerExit to work
// E.g. PointerDown doesn't work if PointerUp is not present as well
public void OnPointerEnter(PointerEventData pointerEventData)
{
}
// And finally to the movement
private IEnumerator Move()
{
// Whut? Looks dangerous but is ok as long as you yield somewhere
while(true)
{
// Depending on the alignment move one step in the given direction and speed/second
if(align == Alignment.Global)
{
targetObject.position += moveStep * Time.deltaTime;
}
else
{
targetObject.localPosition += moveStep * Time.deltaTime;
}
// Very important! This tells the routine to "pause"
// render this frame and continue from here
// in the next frame.
// without this Unity freezes so careful ;)
yield return null;
}
}
}
private bool isPressed;
private void OnGUI()
{
isPressed = GUI.Button(new Rect(165, 300, 150, 350), "right");
}
private void Update()
{
if(!isPressed) return;
var pos = transform.position;
var targetPosition = pos + Vector3.right * 0.5f;
if (Vector3.Distance(transform.position, targetPosition) > 0.1f)
{
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, targetPosition, step);
}
}