如何在游戏对象之间增加相等的距离?

时间:2019-09-09 17:14:02

标签: c# unity3d

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

public class DropDown : MonoBehaviour
{
    public GameObject dropdownPrefab;
    public int numberOfObjects;
    public float speed = 1.5f;
    public float duration = 5f;
    public Vector3 startPos;
    public Vector3 endPos;
    public float distanceToMove = 2f;
    public float gap;

    private List<GameObject> dropDownObjects = new List<GameObject>();
    private List<Vector3> endPositions = new List<Vector3>();

    private void Start()
    {
        for (int i = 0; i < numberOfObjects; i++)
        {
            dropDownObjects.Add(Instantiate(dropdownPrefab, transform.parent));
            endPositions.Add(new Vector3(dropDownObjects[i].transform.position.x, 
                dropDownObjects[i].transform.position.y + i + 2, 
                dropDownObjects[i].transform.position.z) - Vector3.up * distanceToMove);
        }

        startPos = dropDownObjects[0].transform.position;
    }

    private void OnMouseDown()
    {
        StartCoroutine(StartDropObjects());
    }

    private IEnumerator StartDropObjects()
    {
        for (int i = 0; i < dropDownObjects.Count; i++)
        {
            // Random wait period before rotation starts
            if (i == 0)
            {
                //yield return new WaitForSeconds(0);
            }
            else
            {
                //yield return new WaitForSeconds(Random.Range(0, 2f));
            }

            yield return new WaitForSeconds(2f);

            StartCoroutine(Drop(dropDownObjects[i].transform, duration, endPositions[i]));
        }
    }

    private IEnumerator Drop(Transform objectToDrop, float duration, Vector3 endpos)
    {
        float t = 0.0f;

        while (t < duration)
        {
            t += Time.deltaTime;
            objectToDrop.transform.position = Vector3.MoveTowards(objectToDrop.transform.position, endpos, speed * Time.deltaTime);

            yield return null;
        }
    }
}

对象应该向下移动,但是在这种情况下,当我添加间隙时,间隙为i + 2,例如,如果I = 0,则间隙为2,则I = 1,因此间隙将为3,则I = 2的差距是4。

endPositions.Add(new Vector3(dropDownObjects[i].transform.position.x, 
                    dropDownObjects[i].transform.position.y + i + 2, 
                    dropDownObjects[i].transform.position.z) - Vector3.up * distanceToMove);

但是我希望对象之间具有相等的间隙。例如,如果我将间隙值设置为1,则对象之间将有相等的间距/间隙,如果间隙值为5,则每两个对象之间的间隙/间隙将等于5。

现在的问题是我每次都增加1,所以差距不相等。

在执行操作时,对象也在向上移动而不是向下移动:+ i + 2

Gaps

在屏幕快照中,对象向上移动而不是向下移动,顶部的两个对象看起来彼此太近了。差距并不相等。

但是想法是,当对象移动到目标目的地endPositions时,每个对象将根据间隙移动到其on endPosition。

所以最终对象应该是这样的:

Moved Objects

第一个是最底部的那个。最后一个是顶部的那个。 第一个dropDownObjects [0]对象移到了最远的endPosition的endPosition。在这种情况下,distanceToMove设置为2。

然后dropDownObjects 1移至他的distanceToMove-差距。等等。这是逻辑,最终所有对象移动之后,它们将具有相等的间隙。

第一个移动的对象是应该到达distnaceToMove的对象。

2 个答案:

答案 0 :(得分:1)

问题不在这里:

endPositions.Add(new Vector3(dropDownObjects[i].transform.position.x, 
                dropDownObjects[i].transform.position.y + i + 2, 
                dropDownObjects[i].transform.position.z) - Vector3.up * distanceToMove);

但是这里:

private IEnumerator Drop(Transform objectToDrop, float duration, Vector3 endpos)
{
    float t = 0.0f;

    while (t < duration)
    {
        t += Time.deltaTime;
        objectToDrop.transform.position = Vector3.MoveTowards(objectToDrop.transform.position, endpos, speed * Time.deltaTime);

        yield return null;
    }
}

因为所有对象都使用相同的持续时间,但是它们的距离不同。最后的对象没有时间完成它们的移动。

您可以通过将方法Drop(...)更改为以下代码来进行检查:

private IEnumerator Drop(Transform objectToDrop, float duration, Vector3 endpos)
{
    while (objectToDrop.transform.position != endpos)
    {
        objectToDrop.transform.position = Vector3.MoveTowards(objectToDrop.transform.position, endpos, speed * Time.deltaTime);
        yield return null;
    }
}

答案 1 :(得分:0)

我将更改您确定endPositions的方式,以使其更易于配置。

我将定义一个起始距离和一个最大距离,您可以使用minDistanceToMovemaxDistanceToMove在起始距离和Mathf.Lerp t之间进行插值,从而以编程方式计算间隙之(float)i/(numberOfObjects-1)

public float minDistanceToMove = 0.5f;
public float maxDistanceToMove = 2f;

private void Start()
{
    for (int i = 0; i < numberOfObjects; i++)
    {
        dropDownObjects.Add(Instantiate(dropdownPrefab, transform.parent));

        float t = (float)i/(numberOfObjects-1);
        float distDown = Mathf.Lerp(minDistanceToMove,maxDistanceToMove,t);

        endPositions.Add(new Vector3(dropDownObjects[i].transform.position.x, 
            dropDownObjects[i].transform.position.y, 
            dropDownObjects[i].transform.position.z) - Vector3.up * distDown);
    }

    startPos = dropDownObjects[0].transform.position;
}

或者,您可以仅设置minDistanceToMove和间隙大小,然后以这种方式计算distDown

public float minDistanceToMove = 0.5f;
public float gapSize = 0.5f;

private void Start()
{
    for (int i = 0; i < numberOfObjects; i++)
    {
        dropDownObjects.Add(Instantiate(dropdownPrefab, transform.parent));

        float distDown = minDistanceToMove + gapSize * i;

        endPositions.Add(new Vector3(dropDownObjects[i].transform.position.x, 
            dropDownObjects[i].transform.position.y, 
            dropDownObjects[i].transform.position.z) - Vector3.up * distDown);
    }

    startPos = dropDownObjects[0].transform.position;
}

无论哪种方式,您都需要将Drop更改为持续很长时间才能将面板放到目的地:

private IEnumerator Drop(Transform objectToDrop, float duration, Vector3 endpos)
{
    // duration is unused. It is in the method signature here to avoid 
    // confusion when swapping with the alternative below

    while (objectToDrop.transform.position != endPos)
    {
        objectToDrop.transform.position = Vector3.MoveTowards(
                objectToDrop.transform.position, endpos, speed * Time.deltaTime);

        yield return null;
    }
}

或者,您可以使每个面板采用给定的持续时间,并计算遍历该距离所需的速度:

private IEnumerator Drop(Transform objectToDrop, float duration, Vector3 endpos)
{ 
    float mySpeed = Vector3.Distance(
            objectToDrop.transform.position, endpos) / duration;

    while (objectToDrop.transform.position != endPos)
    {
        objectToDrop.transform.position = Vector3.MoveTowards(
                objectToDrop.transform.position, endpos, mySpeed * Time.deltaTime);

        yield return null;
    }
}