Unity中基于排序算法实现球体游戏对象位置交换的脚本问题
解决Unity中按名称排序GameObject并同步位置的问题
嘿,我来帮你搞定这个问题!你当前的代码确实完成了列表的排序,但只是调整了内存里的GameObject引用顺序,场景中的对象位置完全没变化——这就是核心问题所在。咱们一步步来修改,让排序后的球体真正交换位置。
核心思路
要实现视觉上的位置排序,需要做两件事:
- 记录每个对象的目标位置(可以是它们的初始生成位置,也可以是当前排列的位置)
- 排序完成后,把每个对象移动到对应索引的位置上
另外,你的Fill()方法每次点击按钮都会重新实例化一批球体,多次点击会导致场景里堆满重复对象,建议只在初始化时实例化一次。
修改后的完整代码
using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.UI; namespace Assets { public class Gameobjects : MonoBehaviour { public Button s_YourButton; [SerializeField] private GameObject[] deck; // 保存实例化的对象 private List<GameObject> instanciatedObjects; // 保存每个对象的初始位置(排序后会把对象放到对应索引的初始位置) private List<Vector3> originalPositions; void Start() { Button btn = s_YourButton.GetComponent<Button>(); btn.onClick.AddListener(TaskOnClick); // 初始化时只实例化一次对象,避免重复生成 Fill(); } void TaskOnClick() { // 按名称排序对象列表 var sortedObjects = instanciatedObjects.OrderBy(sphere => sphere.name).ToList(); // 遍历排序后的列表,把每个对象移动到对应索引的初始位置 for (int i = 0; i < sortedObjects.Count; i++) { sortedObjects[i].transform.position = originalPositions[i]; } // 可选:更新原列表为排序后的结果(如果后续需要用到排序后的列表) instanciatedObjects = sortedObjects; } public void Fill() { instanciatedObjects = new List<GameObject>(); originalPositions = new List<Vector3>(); for (int i = 0; i < deck.Length; i++) { var newSphere = Instantiate(deck[i]); instanciatedObjects.Add(newSphere); // 记录每个球体生成时的初始位置 originalPositions.Add(newSphere.transform.position); } } } }
代码改动说明
- 添加了
originalPositions列表,用来存储每个球体实例化时的初始位置,作为排序后的目标位置 - 把
Fill()的调用移到Start()里,避免每次点击按钮都生成新的球体 - 在
TaskOnClick()中,排序完成后遍历列表,将每个球体的位置设置为对应索引的初始位置,这样排序后的列表顺序就对应了场景中的位置顺序
进阶优化思路
如果想要更流畅的视觉效果(比如球体平滑移动到目标位置,而不是瞬间跳转),可以用协程实现动画过渡:
IEnumerator MoveToPosition(GameObject obj, Vector3 targetPos, float duration = 0.5f) { Vector3 startPos = obj.transform.position; float elapsedTime = 0; while (elapsedTime < duration) { obj.transform.position = Vector3.Lerp(startPos, targetPos, elapsedTime / duration); elapsedTime += Time.deltaTime; yield return null; } obj.transform.position = targetPos; }
然后在TaskOnClick()里替换位置设置的代码为:
for (int i = 0; i < sortedObjects.Count; i++) { StartCoroutine(MoveToPosition(sortedObjects[i], originalPositions[i])); }
这样点击排序按钮后,球体会平滑地移动到排序后的位置,体验更好~
内容的提问来源于stack exchange,提问作者HumaNSLayeR
相关产品推荐
相关产品推荐

