Unity如何从UI列表选中NPC GameObject并执行分配操作
实现方案
1. 扩展Human类(可选但推荐)
建议新增唯一ID字段,避免出现重名NPC时无法正确区分的问题,修改后的类代码如下:
public class Human { public int id; // 新增唯一标识ID public string name; public Human(int id, string name) { this.id = id; this.name = name; } }
后续在HumanPool中生成Human实例时,传入自增的ID值即可。
2. 新增列表项绑定脚本
给你的PlayerInfo预制体新增一个挂载脚本HumanListItem.cs,用来存储当前列表项对应的NPC数据、绑定点击事件,代码如下:
using UnityEngine; using UnityEngine.UI; using TMPro; public class HumanListItem : MonoBehaviour { public Human bindHuman; // 存储当前项对应的NPC实例 [SerializeField] private Button clickBtn; // 点击触发用的按钮 [SerializeField] private TextMeshProUGUI nameTxt; // NPC名称文本 // 生成列表项时调用的初始化方法 public void Init(Human human) { bindHuman = human; nameTxt.text = human.name; // 绑定点击事件 clickBtn.onClick.RemoveAllListeners(); clickBtn.onClick.AddListener(OnItemClick); } // 点击当前项触发的逻辑 void OnItemClick() { // 直接获取到点击的NPC实例,调用分配逻辑即可 Debug.Log($"选中NPC:{bindHuman.name},ID:{bindHuman.id}"); // 示例:调用建筑管理逻辑分配NPC // BuildingManager.Instance.AssignHumanToBuilding(bindHuman, 目标建筑); } }
脚本挂好后,给PlayerInfo预制体添加Button组件,再把脚本里的clickBtn、nameTxt引用对应拖入即可。
3. 修改列表生成逻辑
你原有代码存在一个问题:循环中直接修改了预制体的文本,会导致所有生成的列表项文本和最后一个NPC一致,修改后的代码如下:
HumanPool playerPool; [SerializeField] GameObject PlayerInfo; [SerializeField] Transform SpawnPoint; void Start() { playerPool = FindObjectOfType<HumanPool>(); } void UpdateListOfHumans() { // 清空旧列表 foreach (Transform child in SpawnPoint) { Destroy(child.gameObject); } for (var i = 0; i < playerPool.Humans.Count; i++) { GameObject spawnedItem = Instantiate(PlayerInfo, SpawnPoint, false); // 绑定对应NPC数据 HumanListItem item = spawnedItem.GetComponent<HumanListItem>(); item.Init(playerPool.Humans[i]); } } void OnMouseDown() { UpdateListOfHumans(); }
按上述方案实现后,每个列表项直接绑定了对应NPC实例,点击时可以直接拿到目标NPC,不需要额外遍历列表查找。如果后续需要做数据持久化,也可以通过绑定的ID字段定位NPC,两种方式可以灵活选择。
内容的提问来源于stack exchange,提问作者Aleksandar Jocic
相关产品推荐
相关产品推荐

