我怎样才能变换 3 个对象以交换位置,但确保它们不会移动到一个对象已经要去的位置?

How can I transform 3 objects to swap positions, but make sure they aren't moving to a position an object is already going to?

我已经将代码应用于 3 个对象。到目前为止,这段代码交换了三个杯子,以便它们交换位置。代码获取杯子的开始位置,然后是每个杯子的结束位置。所有 3 个结束位置实际上是其他杯子的开始位置,因为我希望它们交换到与其他杯子相同的确切位置。更新功能使得如果杯子的结束位置(随机选择)不等于它的开始位置,它会随机移动到另外两个不是它开始位置的点之一。

我在弄清楚一些事情时遇到了困难,并且尝试了一些事情,但我认为我的代码不正确。我想:

让杯子随机移动到它们的新位置,但不要将一个杯子移动到另一个杯子已经移动到的位置。 (当前播放动画时,2 个杯子可能会移动到 3 个位置中的同一个位置)。

我只是不确定该往哪个方向走。我也希望这个动画继续播放,让杯子继续随机交换位置。在弄清楚这一点的方向上也有一点帮助。

这就是我想要的最终结果:http://i249.photobucket.com/albums/gg240/OldNewby4507/shell-game-animated.gif

提前致谢。

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

    public class NewBehaviourScript : MonoBehaviour
    {
        private Vector3 startPos;
        private float lerp = 0, duration = 1;
        public Vector3[] endPos = new Vector3[3];
        int index;
        Vector3 theNewPos;

        void Start ()
        {
            startPos = transform.position;
            endPos [0] = GameObject.Find ("object1").transform.position;
            endPos [1] = GameObject.Find ("object2").transform.position;
            endPos [2] = GameObject.Find ("object3").transform.position;
            index = Random.Range (0, endPos.Length);
            theNewPos = endPos[index];

        }

        void Update() {

            if (theNewPos != startPos) { 
                lerp += Time.deltaTime / duration;
                transform.position = Vector3.Lerp (startPos, theNewPos, lerp);

            }

        }
    }

我认为你必须为你的杯子编写这样的代码:

using UnityEngine;

public class Cup : MonoBehaviour
{
    public Vector3 startPos;
    private float lerp = 0, duration = 1;
    Vector3 theNewPos;

    void Awake()
    {
        startPos = transform.position;
        theNewPos = transform.position;
    }

    void Start()
    {

    }

    void Update()
    {
        float thresholdSqr = 0.01f;

        if ((theNewPos - transform.position).sqrMagnitude > thresholdSqr)
        {
            lerp += Time.deltaTime / duration;
            transform.position = Vector3.Lerp(startPos, theNewPos, lerp);
        }
        else
        {
            transform.position = theNewPos;
            startPos = transform.position;
        }
    }

    public void MoveToSpot(Vector3 pos)
    {
        theNewPos = pos;
        lerp = 0f;
    }
}

然后使用如下代码的全局游戏对象 Shaker:

using UnityEngine;
using System.Linq;

public class Shaker : MonoBehaviour
{    
    Cup[] cups;
    Vector3[] spots;

    void Start()
    {
        cups = GameObject.FindObjectsOfType<Cup>();
        spots = cups.Select(c => c.startPos).ToArray();
    }

    void Update()
    {

    }

    void Shake()
    {
        int[] newIndices = Enumerable.Repeat(-1, cups.Length).ToArray();

        for (int i = 0; i < cups.Length; i++) //there could be another random sort algorithm, for example to make that every cup would move to another spot.
        {
            int free = cups.Length - i;
            int j = Random.Range(0, free);

            for (int k = j; k < cups.Length; k++)
            {
                if (newIndices[k] == -1)
                {
                    newIndices[k] = i;
                    break;
                }
            }
        }

        for (int i = 0; i < cups.Length; i++)
        {
            cups[i].MoveToSpot(spots[newIndices[i]]);
        }
    }
}

如果要将此脚本添加到每个对象,请执行以下操作。这只需要一个脚本,它被添加到每个 cup 对象中。

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

public class rotateCups : MonoBehaviour
{
    private float lerp = 0f, speed = 5f;
    static List<Vector3> listOfCupPositions, shuffleList;
    Vector3 theNewPos, startPos;
    readonly int shuffleSpeed = 100;
    int shuffle = 0;

    void Start()
    {
        if (null == listOfCupPositions)
        {
            // These lists are global to each cup
            listOfCupPositions = new List<Vector3>();
            shuffleList = new List<Vector3>();
        }
        theNewPos = startPos = transform.position;
        listOfCupPositions.Add(theNewPos); // Add this cup to the main list
    }

    void Update()
    {
        if (startPos != theNewPos)
        {
            lerp += Time.deltaTime * speed;
            lerp = Mathf.Clamp(lerp, 0f, 1f); // keep lerp between the values 0..1
            transform.position = Vector3.Lerp(startPos, theNewPos, lerp);
            if (lerp >= 1f)
            {
                startPos = theNewPos;
                lerp = 0f;
            }
        }
    }

    void LateUpdate()
    {
        if (--shuffle <= 0)
        { 
            // Shuffle the cups
            shuffle = shuffleSpeed;
            if (0 == shuffleList.Count)
                shuffleList = listOfCupPositions.ToList(); // refresh shuffle positions

            // Loop until we get a position this cup isn't, 
            // or unless there's only one spot left in shuffle list, 
            // use it (ie don't move this cup this round)
            int index;
            do
            {
                index = Random.Range(0, shuffleList.Count);
            } while (startPos == shuffleList[index] && shuffleList.Count > 1);

            // give this cup a new position
            theNewPos = shuffleList[index];
            shuffleList.RemoveAt(index); // remove position from shuffle list so it isn't duplicated to another cup
        }
    }
}

这是一件有趣的小事,值得一看。为了测试这个,我添加了一个立方体、胶囊和一个球体,将它们移动到 3 个独立的点,为每个点添加脚本,然后在选择相机的情况下,按 ctrl+shift+F 使其与我的视角相同编辑 window,(先保存场景以防万一),然后 运行 它。