一、开发操作
1、创建Iventory Manager 文件管理数据,并添加InventoryManager脚本
2、创建ItemBase文件,添加Item脚本
二、脚本编程
1、InventoryManager C#文件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MFarm.Iventory
{
public class InventoryManager : Singleton<InventoryManager>
{
public ItemDataList_SO itemDataList_SO;
public ItemDetails GetItemDetails(int ID)
{
return itemDataList_SO.itemDetailsList.Find(i=>i.itemID==ID);
}
}
}
这段代码定义了一个名为 InventoryManager 的类,用于管理游戏中的物品,是单例模式的实现类。
-
namespace MFarm.Inventory { },定义了该类所在的命名空间为MFarm.Iventory,这是一种组织代码的方式,用于避免不同类之间命名冲突的情况。 -
public class InventoryManager : Singleton<InventoryManager> { },定义了一个名为InventoryManager的公共类,并继承自Singleton<InventoryManager>类,从而实现单例模式。InventoryManager类有以下两个字段和方法:public ItemDataList_SO itemDataList_SO;,定义了一个公共的ItemDataList_SO类型的字段itemDataList_SO,用于存储所有物品的详细信息列表。public ItemDetails GetItemDetails(int ID) { },定义了一个公共方法GetItemDetails,它接收一个整数类型的参数ID,用于根据物品 ID 号获取该物品的详细信息。在该方法内部,它使用itemDataList_SO.itemDetailsList.Find()方法来查找并返回itemDataList_SO中符合条件的物品详细信息。其中,itemDataList_SO.itemDetailsList表示从ItemDataList_SO中获取物品详细信息列表,而Find(i=>i.itemID==ID)表示在该列表中查找符合itemID与参数ID相等的物品详细信息。
-
Singleton<InventoryManager>则是一个自定义的泛型类,实现了单例模式。它具有以下功能:private static T _instance;,定义了一个私有静态泛型字段_instance,用于存储单例对象的引用。public static T Instance { get { return _instance; } },定义了一个公共静态泛型属性Instance,用于获取单例对象的唯一入口。如果_instance为 null,则通过GameObject.FindObjectOfType<T>()方法查找场景中是否已经存在该类型的单例对象。如果不存在,则使用new GameObject().AddComponent<T>()方法创建一个新的游戏对象并添加该类型的组件,将其作为单例对象并返回;否则直接返回已存在的单例对象。
-
ItemDataList_SO和ItemDetails是两个自定义的数据结构,分别表示物品列表和物品详细信息。其中,itemDetailsList是ItemDataList_SO的公共字段,表示物品详细信息的列表。ItemDetails包括了物品的 ID 号、物品名称、物品图标和物品描述等相关信息。
综上,InventoryManager 类是一个用于管理游戏中的物品的类,使用单例模式实现。它包括了存储所有物品的详细信息列表、根据物品 ID 号获取物品详细信息的方法以及单例对象的创建和获取等功能。ItemDataList_SO 和 ItemDetails 是两个用于存储物品数据的结构体,分别表示物品列表和物品详细信息。
2、Singleton C#文件,单例
using UnityEngine;
public class Singleton <T>: MonoBehaviour where T : Singleton <T>
{
private static T instance;
public static T Instance
{
get => instance;
}
protected virtual void Awake()
{
if (instance != null)
Destroy(gameObject);
else
instance = (T)this;
}
protected virtual void OnDestory()
{
if(instance==this)
instance = null;
}
}
这段代码实现了一个单例模式的基类 Singleton<T>,使用泛型来实现多个不同类的单例。下面是逐行解释每个参数的含义和功能:
using UnityEngine;引入 Unity 引擎的命名空间。public class Singleton<T> : MonoBehaviour where T : Singleton<T>定义了一个公共类Singleton<T>,它继承自 Unity 引擎的组件(Component)基类MonoBehaviour,并使用泛型类型参数<T>,确保只有继承自Singleton <T>的子类才能使用此单例模板。定义中使用where T : Singleton<T>约束,强制所有声明为Singleton<T>泛型类型参数的类都必须继承自Singleton<T>。private static T instance;定义一个私有静态字段instance,用于存储单例对象的唯一实例。public static T Instance { get => instance; }定义一个公共静态属性Instance,它返回instance字段的值。在其他类中只需调用Singleton<T>.Instance即可获取T类型的唯一实例对象。protected virtual void Awake()定义了一个受保护的虚方法Awake(),它在脚本对象被创建时自动调用。在该方法中,如果instance字段已经被赋值,说明该类型的对象已经存在,当前对象不是唯一实例,因此需要销毁该对象;否则将当前对象的引用赋值给instance字段。protected virtual void OnDestroy()定义了一个受保护的虚方法OnDestroy(),它在脚本对象被销毁时自动调用。在该方法中,如果instance字段的值等于当前对象,则将instance字段置为null,以确保下次获取单例对象的时候能够重新创建新的实例。
这段代码实现了基于泛型的单例模式,可以用于多个不同的类中。Singleton<T> 类中定义了一个静态的 instance 字段,用于保存唯一实例的引用,并提供了一个公共的 Instance 属性,让其他类可以获取这个唯一实例。在 Awake() 方法中,会判断 instance 是否已经被赋值,如果是,则销毁当前对象,如果不是,则将当前对象的引用赋值给 instance 字段。在 OnDestroy() 方法中,会判断 instance 是否等于当前对象,如果是,则将 instance 置为 null,以便下次获取实例时可以再次创建。
3、Item C#文件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MFarm.Iventory
{
public class Item : MonoBehaviour
{
public int itemID;
private SpriteRenderer spriteRenderer;
private ItemDetails itemDetails;
private BoxCollider2D coll;
private void Awake()
{
spriteRenderer = GetComponentInChildren <SpriteRenderer>();
coll = GetComponent<BoxCollider2D>();
}
private void Start()
{
if (itemID !=0)
{
Init(itemID );
}
}
public void Init(int ID)
{
itemID = ID;
itemDetails = InventoryManager.Instance.GetItemDetails(itemID);
if (itemDetails != null)
{
spriteRenderer.sprite = itemDetails.itemOnWorldSprite != null ? itemDetails.itemOnWorldSprite :itemDetails.itemIcon ;
//修改Box Collider尺寸
Vector2 newSize = new Vector2(spriteRenderer.sprite.bounds.size.x, spriteRenderer.sprite.bounds.size.y);
coll.size = newSize;
coll.offset = new Vector2(0,spriteRenderer.sprite.bounds .center.y );
}
}
}
}
这段代码定义了一个名为 Item 的类,用于在游戏中表示一个物品。
-
namespace MFarm.Iventory { },定义了该类所在的命名空间为MFarm.Iventory,这是一种组织代码的方式,用于避免不同类之间命名冲突的情况。 -
public class Item : MonoBehaviour { },定义了一个名为Item的公共类,并继承自MonoBehaviour类,从而使该类可以被添加到 Unity 的 GameObject 上。Item类有以下四个成员:public int itemID;,定义了一个公共整数类型的字段itemID,表示该物品的 ID 号。private SpriteRenderer spriteRenderer;,定义了一个私有的SpriteRenderer类型的字段spriteRenderer,用于引用和修改该物品的 Sprite 渲染组件。private ItemDetails itemDetails;,定义了一个私有的ItemDetails类型的字段itemDetails,用于存储该物品的详细信息。private BoxCollider2D coll;,定义了一个私有的BoxCollider2D类型的字段coll,用于引用和修改该物品的碰撞盒组件。private void Awake() { },定义了一个私有方法Awake(),它会在对象被创建后立即执行。在该方法内部,它使用GetComponentInChildren<T>()方法来获取该物品的 Sprite 渲染组件和碰撞盒组件,分别存储到spriteRenderer和coll字段中。private void Start() { },定义了一个私有方法Start(),它会在对象被启用后立即执行。在该方法内部,如果itemID不为 0,则调用Init(itemID)方法来初始化该物品的数据。public void Init(int ID) { },定义了一个公共方法Init,它接收一个整数类型的参数ID,用于初始化该物品的数据。在该方法内部,它首先将ID存储到itemID字段中,并调用InventoryManager.Instance.GetItemDetails(itemID)方法来获取该物品的详细信息。如果成功获取到了详细信息,则根据详细信息中的 Sprite 渲染组件来更新该物品的 Sprite 渲染器,并根据 Sprite 渲染器的尺寸动态修改碰撞盒的大小和偏移量。
Item 类是一个用于表示游戏中物品的类,它包含了物品的 ID 号、Sprite 渲染器、碰撞盒组件以及物品的详细信息等数据。在 Awake() 方法中,它使用 GetComponentInChildren<T>() 方法获取该物品的 Sprite 渲染器和碰撞盒组件;在 Start() 方法中,如果该物品的 ID 号不为 0,则调用 Init(itemID) 方法来初始化该物品的数据;在 Init(int ID) 方法中,它使用 InventoryManager.Instance.GetItemDetails(itemID) 方法获取该物品的详细信息,并根据详细信息来更新该物品的 Sprite 渲染器和碰撞盒组件,以便在游戏中正确地显示该物品的外观和尺寸。