Unity中点击箭头时让玩家向右或向左移动

问题描述 投票:0回答:1

我正在编写一个脚本,如果单击向右箭头,玩家就会以恒定的速度向屏幕右侧移动,然后在离开屏幕后停止。 (同样,如果点击向左箭头,玩家会以匀速向屏幕左侧移动,离开屏幕后停止。)

但是,当我添加代码后,我遇到了一个问题,玩家移动得很慢,一点一点。另外,我不确定我的代码是否简洁。

我使用了 while 循环将玩家移动到目标位置,但代码严重超载了计算机,迫使我关闭 Unity。我担心这会导致计算机出现问题。该代码造成了严重的滞后,我不知道是什么原因造成的。请帮助我...

这是我的代码:(逻辑包括使用方向键移动)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class PlayerManager : MonoBehaviour
{
    public float speed = 500f;
    public float runSpeed = 200f;

    public GameObject player;
    public GameObject rightArrow;
    public GameObject leftArrow;

    private Vector2 movement; 
    private bool isRunning;
    private Animator anim;
    private Rigidbody2D rb;

    private void Start()
    {
        anim = player.GetComponent<Animator>();
        rb = player.GetComponent<Rigidbody2D>();
    }

    
    private void Update()
    {
        // Get input
        movement.x = Input.GetAxisRaw("Horizontal");
        movement.y = Input.GetAxisRaw("Vertical");
        isRunning = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);

        
        if (Input.GetMouseButtonDown(0))
        {
            Vector2 worldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector2.zero);

            if (hit.collider != null)
            {
                if (hit.collider.gameObject == rightArrow)
                {
                    int clickX = 1;
                    ArrowClick(clickX);
                }
                else if (hit.collider.gameObject == leftArrow)
                {
                    int clickX = -1;
                    ArrowClick(clickX);
                }
            }
        }
    }

    public void ArrowClick(int _clickX)
    {
        Vector2 target = new Vector2(100 * _clickX, 0);
        while (true)
        {
            player.transform.position
            = Vector2.MoveTowards(player.transform.position, target, 10);
        }
    }


    private void FixedUpdate()
    {
        // Move the character
        float currentSpeed = isRunning ? speed * runSpeed : speed;
        Vector2 velocity = movement.normalized * currentSpeed;
        rb.MovePosition(rb.position + velocity * Time.fixedDeltaTime);

        
    }

    private void LateUpdate()
    {
        // Update animator
        anim.SetFloat("DirX", movement.x);
        anim.SetFloat("DirY", movement.y);
        anim.SetBool("Idle", movement.magnitude == 0);

        
    }
}
c# unity-game-engine click
1个回答
0
投票

您创建了一个没有退出条件的无限循环(

while (true)
永远不会是
false
...),因此当Unity看起来没有响应时,它仍在执行
while (true)
内的代码。以及结束。以及结束。等等

其次,像这样的循环移动对象(或实际上做任何事情)将在单个帧内发生,这将导致您的对象传送到目的地。

您可以使用协程同时解决这两个问题,它是可以暂停和恢复执行的单段代码(函数):

public IEnumerator ArrowClick(int _clickX)
{
    float speed = 10;
    Vector2 target = new Vector2(100 * _clickX, 0);
    
    // Changed "while true" to be "while far from the destination"
    while (Vector2.Distance(player.transform.position, target) > 0.05f)
    {
        // Changed from hardcoded "10" to rather be based on the "Time.deltaTime": enables framerate independence (player will move the same amount in a second, regardless of FPS)
        player.transform.position = Vector2.MoveTowards(player.transform.position, target, speed * Time.deltaTime);
 
        // Tells the game to wait a frame before continuing execution
        yield return null;
    }
}

然后可以这样开始:

// This is a class variable, put it at the top
Coroutine playerMoveRoutine;

//Inside your click code
if (hit.collider.gameObject == rightArrow)
{
    int clickX = 1;
    // If we're already moving, cancel that coroutine so the two don't execute at the same time
    if (playerMoveRoutine != null)
    {
        StopCoroutine(playerMoveRoutine);
    }
    playerMoveRoutine = StartCoroutine(ArrowClick(clickX));
}
else if (hit.collider.gameObject == leftArrow)
{
    int clickX = -1;
    // If we're already moving, cancel that coroutine so the two don't execute at the same time
    if (playerMoveRoutine != null)
    {
        StopCoroutine(playerMoveRoutine);
    }
    playerMoveRoutine = StartCoroutine(ArrowClick(clickX));
}
© www.soinside.com 2019 - 2024. All rights reserved.