我怎样才能变换 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,(先保存场景以防万一),然后 运行 它。
我已经将代码应用于 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,(先保存场景以防万一),然后 运行 它。