主要问题是这个循环
while (Vector3.Distance(transform.position, targetPosition) > 0.1f)
{
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, targetPosition, step);
}
这一步会移动您的对象,因为同时不会渲染任何帧。 while 会阻塞整个线程,直到它完成(在这种情况下我并没有那么长),然后在完成后渲染帧。
此外,正如 cmets 中提到的那样,OnGUI 每帧被调用多次,因此情况变得更糟。
正如我还评论的那样,OnGUI 是一种遗留物,除非您确切地知道自己在做什么以及在做什么,否则您不应该再使用它。
宁可使用UI.Button in a Canvas。
如果我没看错,你想在按钮保持按下状态时移动。
不幸的是,没有内置按钮来处理“当按钮保持按下状态”之类的事情,因此您必须使用IPointerDownHandler 和IPointerUpHandler 接口。
把这个类放在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);
}
}