玩家不要缓慢移动(平稳)

时间:2019-05-13 01:34:52

标签: c# unity3d coroutine

我在游戏中有一个问题,当我在InputField中写“ LEFT”并单击UI按钮时,多维数据集移动“ LEFT”并吃硬币(向上,向下,向右相同),我的问题是当我将此代码写在玩家移动下方但不像消失在声明它的位置那样缓慢地消失

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

public class GameManager : MonoBehaviour
{
    public InputField mainInputField;
    //public float speed;

    public GameObject Player;
    public Button Click_me;

    public float smoothing = 1f;
    public Transform TargetRight1;
    public Transform TargetRight2;
    public Transform TargetUP;

    // Start is called before the first frame update
    void Start()
    {

    }

    public void SubmitName()
    {
        string[] lines = mainInputField.text.Split('\n');
        for (int i = 0; i < lines.Length; i++)
        {
            if (lines[i] == "UP")
            {
                // moveUP();
                StartCoroutine(MyCoroutineUP(TargetUP));
            }
            else if (lines[i] == "DOWN")
            {
                //MoveDown();
            }
            else if (lines[i] == "LEFT")
            {
                //MoveLeft();
            }
            else if (lines[i] == "RIGHT")
            {
                StartCoroutine(MyCoroutineUP(TargetRight1));
            }
        }
        // Click_me.interactable = false;
    }

    IEnumerator MyCoroutineUP(Transform target)
    {
        while (Vector3.Distance(Player.transform.position, target.position) > 0.05f)
        {
            Player.transform.position = Vector3.Lerp(Player.transform.position, target.position, smoothing * Time.deltaTime);       
        }

        yield return null;
    }  
}

知道我是否将yield return null;放在while循环中

while (Vector3.Distance(Player.transform.position, target.position) > 0.05f)
{
    Player.transform.position = Vector3.Lerp(Player.transform.position, target.position, smoothing * Time.deltaTime);
    yield return null;
}

玩家慢慢移动并获得硬币,但是例如,如果我有2个以上的ligne,我写了LEFT,那么当我在第一行中调用该函数时,while循环将无法正常工作。对不起,我的英语

Game image

1 个答案:

答案 0 :(得分:2)

您将获得并发协同程序。

听起来您实际上要问的是如何堆叠多个命令并使其一个接一个地工作。这变得有些复杂,但听起来像是Queue

的完美用例
private readonly Queue<Transform> _commands = new Queue<Transform>();

public void SubmitName()
{
    var lines = mainInputField.text.Split('\n');
    mainInputField.text = "";
    foreach (var line in lines)
    {
        switch (line)
        {
            case "UP":
                // adds a new item to the end of the Queue
                _commands.Enqueue(TargetUp);
                break;

            case "DOWN":
                _commands.Enqueue(TargetDown);
                break;

            case "LEFT":
                _commands.Enqueue(TargetLeft);
                break;

            case "RIGHT":
                _commands.Enqueue(TargetRight);
                break;
        }
    }

    StartCoroutine(WorkCommands());
}

private IEnumerator WorkCommands()
{
    // block input
    Click_me.interactable = false;

    // run this routine until all commands are handled
    while (_commands.Count > 0)
    {
        // returns the first element and at the same time removes it from the queue
        var target = _commands.Dequeue();

        // you can simply yield another IEnumerator
        // this makes it execute and at the same time waits until it finishes
        yield return MovementCoroutine(target);
    }

    // when done allow input again
    Click_me.interactable = true;
}

对于忍耐本身:

我不会那么喜欢。这样开始运动很快,最终变慢,但从未真正达到目标位置。如果那是您想要的内容,那么我还是建议您做类似的事情

private IEnumerator MovementCoroutine(Transform target)
{
    var startPos = transform.position;
    var targetPos = target.position;

    var timePassed = 0f;

    do
    {
        var lerpFactor = Mathf.SmoothStep(0, 1, timePassed / smoothing);
        transform.position = Vector3.Lerp(startPos, targetPos, lerpFactor);

        timePassed += Time.deltaTime;
        yield return null;
    }
    while(timePassed < smoothing);

    // just to be sure there is no over or undershooting
    // in the end set the correct target position
    transform.position = targetPos;
}

然后在smoothing中,您将以总秒数设置时间。我认为这可以给您更多的控制权。 SmoothStep使得进出的动作仍然轻松。

如果您愿意,还可以考虑当前距离,以始终使对象以差不多相同的速度移动,而不管通过添加/更改目标位置有多近或远

    var distance = Vector3.Distance(startPos, targetPos);
    var duration = smoothing * distance;

    do
    {
        var lerpFactor = Mathf.SmoothStep(0, 1, timePassed / duration);

        ...
    }
    while (timePassed < duration);

现在在smoothing中,您希望以秒为单位设置对象移动1个Unity单位所需的时间。


我不知道您对课程目标的确切设置,但这就是将目标附加到播放器(以便它们随之移动)的样子

enter image description here

相关问题