Основная проблема заключается в следующем цикле
while (Vector3.Distance(transform.position, targetPosition) > 0.1f)
{
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, targetPosition, step);
}
Это перемещает ваш объект за один шаг, потому что пока что кадр не отображается. while
скорее блокирует весь поток до тех пор, пока это не будет сделано (что в данном случае не так долго), а затем визуализирует кадр, когда это будет сделано.
Кроме того, как также упоминается в комментариях, OnGUI
называется множественнымраз за кадр, так что становится еще хуже.
Как я уже говорил, OnGUI
является своего рода наследием, и вы не должны больше его использовать, если не знаете точно, как и что вы делаете.
Скорее используйте UI.Button
в Canvas
.
Если я вижу это правильно, вы хотите двигаться, пока кнопка остается нажатой.
К сожалению, нет встроенной кнопки для управления чем-то вроде «пока кнопка остается нажатой», поэтому вам придется использовать интерфейсы IPointerDownHandler
и IPointerUpHandler
.
Putэтот класс для 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);
}
}