【unity小技巧】封装一套 Unity 的植物生长系统

文章目录

前言

如果你对制作生存模拟经营游戏感兴趣,那么其中比较重要的功能之一应该就是植物生长系统,本文就来封装一个植物生长系统,方便后面使用,这里我参考了youtube上JD Dev的方法。

系统通过三个核心脚本实现:

  1. PlantSO脚本化对象存储植物名称、生长阶段预制体、生长时间等数据;
  2. PlantObject控制器管理植物生长状态,处理阶段切换和实例化;
  3. TimeManager时间管理器统一控制所有植物的生长进度。测试使用不同形状的立方体和圆形模拟植物各生长阶段,通过GIF展示了植物从种子到成熟的动态生长效果。该方案采用模块化设计,便于扩展不同植物类型和生长逻辑,适用于农场模拟等游戏开发场景。

实践

1、植物脚本化对象,用于存储植物数据

csharp 复制代码
using UnityEngine;
using System.Collections.Generic;

// 植物脚本化对象,用于存储植物数据
[CreateAssetMenu(fileName = "PlantSO", menuName = "Data/PlantSo")]
public class PlantSO : ScriptableObject
{
    public string PlantName; // 植物名称
    public List<GameObject> PlantPrefabs; // 植物各阶段预制体列表
    public float CropTime; // 每个生长阶段所需时间
    public int CropReward; // 收获奖励
    
    // 最大生长阶段数(根据预制体数量自动计算)
    public int MaxStage { get { return PlantPrefabs.Count; } }
    
    // 根据阶段获取植物预制体
    public GameObject GetPlantByStage(int stage)
    {
        if (stage >= MaxStage)
        {
            return null;
        }
        return PlantPrefabs[stage];
    }
}

2、植物生长控制器

csharp 复制代码
using UnityEngine;

// 植物生长控制器
public class PlantObject : MonoBehaviour
{
    [SerializeField] private PlantSO plant; // 关联的植物数据
    private int currentStage; // 当前生长阶段
    private float currentTime; // 当前阶段已生长时间
    private GameObject currentPlant; // 当前显示的植物对象

    // 初始化
    private void Start()
    {
        TimeManager.instance.RegisterPlant(this);
        currentPlant = Instantiate(plant.GetPlantByStage(currentStage), transform);
    }

    // 检查植物生长状态(由TimeManager定期调用)
    public void CheckPlant(float deltaTime)
    {
        currentTime += deltaTime;

        // 检查是否达到生长时间
        if (currentTime > plant.CropTime)
        {
            currentStage++;
            currentTime = 0;

            // 销毁当前植物并实例化下一阶段的植物
            Destroy(currentPlant);
            // 检查是否还有下一阶段
            GameObject nextStagePrefab = plant.GetPlantByStage(currentStage);
            if (nextStagePrefab)
            {
                currentPlant = Instantiate(nextStagePrefab, transform);
                Debug.Log($"当前阶段: {currentStage}");
            }
            else
            {   
                Debug.Log($"植物已完全成熟,收获奖励: {plant.CropReward}");
                // 通知TimeManager立即移除自己
                TimeManager.instance.UnregisterPlant(this);
            }
            
        }
    }

    // 检查是否已达到最大生长阶段
    public bool HasMaxLevel()
    {
        return currentStage >= plant.MaxStage;
    }
}

3、时间管理器,控制所有植物的生长

csharp 复制代码
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

// 时间管理器,控制所有植物的生长
public class TimeManager : MonoBehaviour
{
    private List<PlantObject> plantObjects = new List<PlantObject>();
    public static TimeManager instance;

    // 初始化单例
    private void Awake()
    {
        if (instance == null)
            instance = this;
    }

    // 注册植物到管理列表
    public void RegisterPlant(PlantObject plantObject)
    {
        plantObjects.Add(plantObject);
    }

    // 从管理列表移除植物
    public void UnregisterPlant(PlantObject plantObject)
    {
        plantObjects.Remove(plantObject);
    }

    // 每帧更新所有植物的生长状态
    private void Update()
    {
        foreach (PlantObject plantObject in plantObjects.ToList())
        {
            plantObject.CheckPlant(Time.deltaTime);
        }

        // 移除已经完成生长的植物
        plantObjects.RemoveAll(x => x.HasMaxLevel());
    }
}

4、调用测试

我们新增两种测试植物,不同大小的立方体和圆形作为测试,模拟植物生长的不同阶段

挂载脚本

效果

参考

https://www.youtube.com/watch?v=aG_HMFWPDaM\&t=1s


专栏推荐

地址
【unity游戏开发入门到精通------C#篇】
【unity游戏开发入门到精通------unity通用篇】
【unity游戏开发入门到精通------unity3D篇】
【unity游戏开发入门到精通------unity2D篇】
【unity实战】
【制作100个Unity游戏】
【推荐100个unity插件】
【实现100个unity特效】
【unity框架/工具集开发】
【unity游戏开发------模型篇】
【unity游戏开发------InputSystem】
【unity游戏开发------Animator动画】
【unity游戏开发------UGUI】
【unity游戏开发------联网篇】
【unity游戏开发------优化篇】
【unity游戏开发------shader篇】
【unity游戏开发------编辑器扩展】
【unity游戏开发------热更新】
【unity游戏开发------网络】

完结

好了,我是向宇,博客地址:https://xiangyu.blog.csdn.net,如果学习过程中遇到任何问题,也欢迎你评论私信找我。

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

相关推荐
金銀銅鐵1 天前
[Python] 模 n 乘法的逆元计算器
python·数学·游戏
金銀銅鐵2 天前
借助 Pygame 探索最大公约数的规律
python·数学·游戏
雨落倾城夏未凉4 天前
第四章c#方法-参数数组和可选参数(16)
后端·c#
唐青枫5 天前
线程不是越多越快:C#.NET Thread 生命周期、同步与后台工作线程实战
c#·.net
唐青枫6 天前
别只会反射:C#.NET Emit 动态生成代码实战详解
c#·.net
咕白m6256 天前
.NET 环境下 Word 超链接批量提取方案
c#·.net
用户91721561902116 天前
C# 通信协议增量解析:用状态机处理半包和粘包
c#
nujnewnehc6 天前
不会 py, 用 ai 写了个游戏辅助的感受
人工智能·游戏
小码编匠7 天前
C# 工控上位机必备:数据转换工具类与十个核心模块
后端·c#·.net
jump_jump7 天前
为了重玩金庸群侠传,我研究了一下 Ruffle 怎么复活 Flash
游戏·rust·github