效果演示
文章目录
- 效果演示
- 系列目录
- 前言
- 新增简单的泛型单例
- 消耗品
- 源码
- 完结
系列目录
前言
欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第25篇中,我们将探索如何用unity制作一个3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱等功能,我会附带项目源码,以便你更好理解它。
新增简单的泛型单例
我们会有有很多单例,如果每个单例都去写会很麻烦,所以我们定义泛型单例模式 Singleton,我们将所有的单例都继承这个泛型单例,就省略很多重复的工作
//简单的泛型单例
public class Singleton<T> : MonoBehaviour where T : Singleton<T>
{
private static T instance;
public static T Instance
{
get
{
if (instance == null)
{
instance = FindObjectOfType<T>();
if (instance == null)
{
GameObject obj = new GameObject(typeof(T).Name);
instance = obj.AddComponent<T>();
}
}
return instance;
}
}
public void Awake() {
if(instance == null){
instance = this as T;
//确保单例对象在场景切换时不会被销毁
DontDestroyOnLoad(gameObject);
}else{
Destroy(gameObject);
}
}
}
调用例子:
public class MySingletonClass : Singleton<MySingletonClass>
{
// 添加自己的方法和属性
}
消耗品
新增玩家健康类控制脚本
public class PlayerHealth : MonoBehaviour
{
[SerializeField] private int health = 0; // 玩家健康值
[SerializeField] private int food = 0; // 玩家食物值
[SerializeField] private int water = 0; // 玩家水分值
// 增加健康值
public void AddHealth(int addedHealth)
{
health += addedHealth;
}
// 增加食物值
public void AddFood(int addedFood)
{
food += addedFood;
}
// 增加水分值
public void AddWater(int addedWater)
{
water += addedWater;
}
}
因为物品都会配置为预制体,如果我们直接在物品上挂载配置触发的事件,变为预制体后事件配置数据会丢失,所以我们可以新增物品事件管理器类ItemEventManager ,动态的绑定相关事件到对应物品上
// 物品事件管理器类
public class ItemEventManager : Singleton<ItemEventManager>
{
[SerializeField] private List<ItemReferences> itemReferences = new List<ItemReferences>(); // 物品引用列表
// 获取物品事件
public UnityEvent GetItemEvents(Item item)
{
ItemReferences itemRef = itemReferences.Find(x => x.item.name == item.name); // 查找物品引用
return (itemRef != null && itemRef.events != null) ? itemRef.events : null; // 返回物品事件,如果为空则返回 null
}
}
// 物品引用类
[System.Serializable]
public class ItemReferences
{
public Item item; // 物品引用
public UnityEvent events; // 物品事件
}
比如我们配置苹果使用可以加人物5饱食度和5水分值
修改Item,绑定对应的事件和使用物品功能
[Header("使用物品")]
public bool removeOneOnUse;// 是否是一次性物品
public UnityEvent myEvent;// 使用物品时触发的事件
private void Start()
{
// 从物品事件管理器中获取该物品对应的物品事件
UnityEvent newEvent = ItemEventManager.Instance.GetItemEvents(this);
if (newEvent != null) myEvent = newEvent;
}
private void OnDisable()
{
// 如果该物品不在场景中并且其使用物品事件没有任何持续事件,则直接返回
if (!gameObject.scene.isLoaded || myEvent.GetPersistentEventCount() != 0) return;
UnityEvent newEvent = ItemEventManager.Instance.GetItemEvents(this);
if (newEvent != null) myEvent = newEvent;
}
//使用物品
public void UseItem()
{
if (myEvent.GetPersistentEventCount() > 0)
{
myEvent.Invoke();// 触发使用物品事件
if (removeOneOnUse) currentQuantity--;// 根据设置决定是否减少物品数量
}
}
解释:
GetPersistentEventCount 是 Unity 中的方法,用于获取 UnityEvent 中持久化(persistent)事件的数量。在这里,它用于检查一个物品的使用事件中是否包含任何持久化的事件。
Unity 的事件系统允许您在编辑器中将方法绑定到事件,这些绑定在运行时会被称为“持久化”事件。GetPersistentEventCount 方法用于获取 UnityEvent 中已经绑定的持久化事件的数量,以便在代码中进行相应的逻辑处理。
在上述代码中,myEvent.GetPersistentEventCount() 用于检查 myEvent 中是否有持久化事件的绑定。如果事件绑定的数量不为 0,则说明该物品的使用事件已经被设置过,因此在禁用时不需要重新获取事件。
勾选苹果为一次性物品,及消耗品
修改Inventory
public void Update()
{
//...
if (Input.GetMouseButtonDown(0))
{
attemptToUseItem();//使用物品
}
}
//使用物品
private void attemptToUseItem()
{
if (curHotbarIndex == -1) return;
Item curItem = hotbarSlots[curHotbarIndex].getItem();// 获取选中的快捷栏中的物品
if (curItem && curItem.myEvent.GetPersistentEventCount() != 0)
{
curItem.UseItem();// 使用物品
if (curItem.currentQuantity != 0)
hotbarSlots[curHotbarIndex].updateData();// 更新快捷栏数据
else
hotbarSlots[curHotbarIndex].setItem(null);// 如果物品数量为0,清空快捷栏中的物品
enableHotbarItem(curHotbarIndex);// 再次激活快捷栏中的物品
}
}
效果
运行看物品事件是否绑定上了
拿在手上点击使用
源码
源码不出意外的话我会放在最后一节
完结
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注
,以便我第一时间收到反馈,你的每一次支持
都是我不断创作的最大动力。当然如果你发现了文章中存在错误
或者有更好的解决方法
,也欢迎评论私信告诉我哦!
好了,我是向宇
,https://xiangyu.blog.csdn.net
一位在小公司默默奋斗的开发者,出于兴趣爱好,最近开始自学unity,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!php是工作,unity是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~