Unity如何通过代码永久为对象分配Tag 重启后不重置
问题根源
- 运行时修改GameObject的Tag、组件属性属于内存临时变更,编辑器下退出播放模式、正式版游戏重启后,所有运行时改动都会回退到场景/预制体的初始配置,不会自动永久留存
- 原脚本硬绑定单个
StationBox对象,没有抽象通用逻辑,无法复用给所有站点方块,批量维护成本极高
通用实现方案
提前在Unity的Tag配置中添加Uncreated、Created两个自定义Tag,所有初始站点方块默认设置为Uncreated、名称文本留空即可。
实现核心逻辑:给所有站点方块挂载统一组件,用PlayerPrefs做轻量本地持久化存储,记录每个站点的创建状态、站点名称;游戏启动时自动读取存储数据,初始化对应方块的Tag和显示内容;点击方块时动态传入当前操作的站点对象,一套逻辑适配所有站点,无需重复编写脚本。
站点核心组件脚本(挂载到所有站点方块对象上)
using UnityEngine; using UnityEngine.UI; public class Station : MonoBehaviour { [Header("站点配置,每个方块需保证ID唯一")] public string stationId; public Text nameDisplayText; public bool IsCreated { get; private set; } public string StationName { get; private set; } private StationUIController _uiController; private void Awake() { // 嫌手动填ID麻烦可以保留下面这行,自动用坐标生成唯一ID stationId = $"{transform.position.x}_{transform.position.z}"; // 读取本地存储初始化站点状态 IsCreated = PlayerPrefs.GetInt($"Station_Created_{stationId}", 0) == 1; StationName = PlayerPrefs.GetString($"Station_Name_{stationId}", string.Empty); if (IsCreated) { tag = "Created"; nameDisplayText.text = StationName; } else { tag = "Uncreated"; nameDisplayText.text = string.Empty; } } private void Start() { _uiController = FindObjectOfType<StationUIController>(); } private void OnMouseDown() { // 3D碰撞体点击自动触发,UGUI按钮可直接绑定事件传this引用 _uiController.OnStationClicked(this); } // 创建站点时调用,持久化保存状态 public void MarkAsCreated(string inputName) { if (string.IsNullOrWhiteSpace(inputName)) return; IsCreated = true; StationName = inputName; tag = "Created"; nameDisplayText.text = inputName; PlayerPrefs.SetInt($"Station_Created_{stationId}", 1); PlayerPrefs.SetString($"Station_Name_{stationId}", inputName); PlayerPrefs.Save(); } // 后续做删除站点功能时直接调用 public void ResetToUncreated() { IsCreated = false; StationName = string.Empty; tag = "Uncreated"; nameDisplayText.text = string.Empty; PlayerPrefs.DeleteKey($"Station_Created_{stationId}"); PlayerPrefs.DeleteKey($"Station_Name_{stationId}"); PlayerPrefs.Save(); } }
UI控制脚本(挂载到场景UI空物体上即可,全局只需要一个)
using UnityEngine; using UnityEngine.UI; public class StationUIController : MonoBehaviour { public InputField stationNameInput; public GameObject createStationWindow; public GameObject editStationWindow; private Station _currentOperateStation; // 站点点击时触发,传入对应站点组件引用 public void OnStationClicked(Station clickedStation) { _currentOperateStation = clickedStation; stationNameInput.text = string.Empty; CloseAllWindows(); if (clickedStation.IsCreated) { editStationWindow.SetActive(true); stationNameInput.text = clickedStation.StationName; // 编辑站点的逻辑可以在这里扩展 } else { createStationWindow.SetActive(true); } } // 绑定到创建窗口的确认按钮 public void OnConfirmCreate() { if (_currentOperateStation == null) return; _currentOperateStation.MarkAsCreated(stationNameInput.text.Trim()); createStationWindow.SetActive(false); } // 绑定到所有窗口的取消/关闭按钮 public void CloseAllWindows() { createStationWindow.SetActive(false); editStationWindow.SetActive(false); } }
配置步骤
- 所有站点方块挂载
Station组件,拖入自身用来显示站点名的Text组件引用;如果是3D方块记得加碰撞体,否则OnMouseDown不会触发 - 场景新建空物体挂载
StationUIController组件,拖入对应的输入框、创建/编辑窗口的引用 - 将创建窗口的确认按钮点击事件绑定到
OnConfirmCreate方法,窗口关闭按钮绑定到CloseAllWindows方法即可
注意:如果后续需要扩展站点属性(比如所属线路、出入口数量、换乘标记),直接在
Station脚本中新增对应字段,按照同样的读写逻辑存入PlayerPrefs即可。需要清空所有存档重置站点时,直接删除所有Station_前缀的PlayerPrefs键就行,不需要逐个修改场景对象。
内容的提问来源于stack exchange,提问作者Ilya
相关产品推荐
相关产品推荐

