C# 无法使用MoveToward或Lerp平滑移动gemeObject

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;

我是一个极端的业余爱好者,目标很简单。在OnGui中,我有一个按钮。我想当按下这个按钮移动它所连接的游戏对象时,以平滑的方式向右移动一段距离。我已经成功地设定了我想要移动的距离,但我无法使移动平稳以挽救我的生命

    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);
    }
}