Unity技术问询:如何在不同场景间传递已设置的背包物品Sprite
Hey there! Let's break down how to fix your cross-scene inventory sprite issue step by step.
First, let's clarify why your current setup isn't working:
- Your
Itemsscript isn't attached to any scene GameObject, soDontDestroyOnLoad(this)does nothing (it only works on objects that exist in the scene). - When you switch scenes, all non-persistent objects get destroyed, so your item sprite data vanishes with them. Static variables can work for this, but a dedicated persistent manager is cleaner and easier to maintain for inventory systems.
Here's a reliable solution using a singleton persistent manager—this is the go-to approach for cross-scene data sharing in Unity:
Step 1: Create a Persistent Inventory Data Manager
Make a new script called InventoryDataManager, attach it to an empty GameObject in your initial scene (like your main menu or first level), and use this code:
using UnityEngine; using System.Collections.Generic; public class InventoryDataManager : MonoBehaviour { // Singleton instance - access this from anywhere in your code public static InventoryDataManager Instance { get; private set; } // Store all picked items here (custom struct holds all needed data) public List<PickedItem> CollectedItems = new List<PickedItem>(); // Struct to hold cross-scene item data [System.Serializable] public class PickedItem { public int itemID; public string itemName; public string itemDescription; public Sprite itemSprite; } private void Awake() { // Ensure only one instance exists, and it survives scene loads if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } } // Add a new item to the persistent inventory public void AddCollectedItem(int id, string name, string desc, Sprite sprite) { // Prevent duplicate items (optional, adjust based on your needs) var existingItem = CollectedItems.Find(item => item.itemID == id); if (existingItem == null) { CollectedItems.Add(new PickedItem { itemID = id, itemName = name, itemDescription = desc, itemSprite = sprite }); } } }
Step 2: Update Your Items Script to Save Data to the Manager
Modify your Items script to send item data to the manager when picked up (I'll assume you use a trigger for pickup—adjust to your actual pickup logic):
public class Items : MonoBehaviour { public string ItemName; public string ItemText; public int itemInList; public Sprite itemSprite; public Sprite blueberrySprite; public Sprite cheesecakeSprite; public Sprite whitebreadSprite; public Sprite cookiesSprite; // Example pickup logic (triggered when player touches the item) private void OnTriggerEnter(Collider other) { if (other.CompareTag("Player")) { // Set item data first ItemList(); // Save data to the persistent manager InventoryDataManager.Instance.AddCollectedItem(itemInList, ItemName, ItemText, itemSprite); // Remove the item from the scene after pickup Destroy(gameObject); } } public void ItemList() { if(itemInList == 1) { ItemName = "Cheesecake"; ItemText = "A delishious Juicy Cheesecake"; itemSprite = cheesecakeSprite; } if (itemInList == 2) { ItemName = "White Bread"; ItemText = "a basic white loaf that smells amazing"; itemSprite = whitebreadSprite; } if (itemInList == 3) { ItemName = "Cookies"; ItemText = "just plain Chocolatechip cookies, still delishious though"; itemSprite = cookiesSprite; } if (itemInList == 4) { ItemName = "Blueberries"; ItemText = "Big juicy yummy blueberries!"; itemSprite = blueberrySprite; Debug.Log(ItemText); } } }
Step 3: Load Data in Your New Scene's Backpack UI
Create a script for your backpack UI in the new scene, and use this to pull data from the manager:
using UnityEngine; using UnityEngine.UI; public class BackpackUI : MonoBehaviour { // Assign your backpack slot images in the Inspector public Image[] backpackSlots; private void Start() { // Load collected items into the backpack UI if (InventoryDataManager.Instance != null) { for (int i = 0; i < InventoryDataManager.Instance.CollectedItems.Count && i < backpackSlots.Length; i++) { var item = InventoryDataManager.Instance.CollectedItems[i]; backpackSlots[i].sprite = item.itemSprite; backpackSlots[i].enabled = true; // Make sure the image is visible } } } }
Key Notes to Avoid Issues:
- Place all your sprite assets in a
Resourcesfolder (or use Addressables for larger projects) to ensure they're accessible across scenes. - Double-check that your
InventoryDataManagerGameObject exists in your initial scene—this is crucial for it to persist through scene loads. - You can remove the old
gettingIDmethod since we're now storing all necessary data in the manager instead of dynamic GameObjects.
This setup keeps your inventory data alive between scenes, so your backpack sprites will load correctly every time.
内容的提问来源于stack exchange,提问作者Yumaisch

