当前位置: 首页 > article >正文

Unity3D仿星露谷物语开发43之农作物生长

1、目标

把防风草种子种在地里,并展示植物种子,防风草种子将随着时间变化而生长成植株。

2、创建Crop.cs脚本

在Assets -> Scripts下创建新的目录命名为Crop,在其下创建新的脚本命名为Crop.cs。

代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Crop : MonoBehaviour
{[HideInInspector]public Vector2Int cropGridPosition;
}

3、创建CropDetails.cs脚本

在Assets -> Scripts -> Crop下创建CropDetails.cs脚本。

代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;[System.Serializable]
public class CropDetails 
{[ItemCodeDescription]public int seedItemCode; // this is the item code for the corresponding seedpublic int[] growthDays; // days growth for each stagepublic int totalGrowthDays; // total growth dayspublic GameObject[] growthPrefab; // prefab to use when instantiating growth stagespublic Sprite[] growthSprite; // growth spritepublic Season[] seasons; // growth seasonspublic Sprite harvestedSprite; // sprite used once harvested[ItemCodeDescription]public int harvestedTransformItemCode; // if the item transform into another item when harvested this item code will be populatedpublic bool hideCropBeforeHarvestedAnimation; // if the crop should be disabled before the harvested animationpublic bool disableCropCollidersBeforeHarvestedAnimation; // if colliders on crop should be disabled to avoid the harvested animation effecting any other game objectspublic bool isHarvestedAnimation; // true if harvested animation to be played on final growth stage prefabpublic bool isHarvestActionEffect = false; // flag to determine whether there is a harvest action effectpublic bool spawnCropProducedAtPlayerPosition;public HarvestActionEffect harvestActionEffect; // the harvest action effect for the crop[ItemCodeDescription]public int[] harvestToolItemCode; // array of item codes for the tools that can harvest or 0 array elements if no tool requiredpublic int[] requiredHarvestActions; // number of harvest actions required for corresponding tool in harvest tool item code array[ItemCodeDescription]public int[] cropProducedItemCode; // array of item codes produced for the harvested croppublic int[] cropProducedMinQuantity; // array of minimum quantities produced for the harvested croppublic int[] cropProducedMaxQuantity; // if max quantity is > min quantity then a random number of crops between min and max are producedpublic int daysToRegrow; // days to regrow next crop or -1 if a single crop/// <summary>/// returns true if the tool item code can be used to harvest this crop, else returns false/// </summary>/// <param name="toolItemCode"></param>/// <returns></returns>public bool CanUseToolToHarvestCrop(int toolItemCode){if(RequiredHarvestActionsForTool(toolItemCode) == -1){return false;}else{return true;}}/// <summary>/// returns -1 if the tool can't be used to harvest this crop, else returns thhe number of harvest actions required by this tool/// </summary>/// <param name="toolItemCode"></param>/// <returns></returns>public int RequiredHarvestActionsForTool(int toolItemCode){for(int i = 0; i < harvestToolItemCode.Length; i++){if (harvestToolItemCode[i] == toolItemCode){return requiredHarvestActions[i];}}return -1;}}

4、创建SO_CropDetailsList.cs脚本

在Assets -> Scripts -> Crop下创建SO_CropDetailsList.cs脚本。

代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;[CreateAssetMenu(fileName ="CropDetailsList", menuName ="Scriptable Objects/Crop/Crop Details List")]
public class SO_CropDetailList : ScriptableObject
{[SerializeField]public List<CropDetails> cropDetails;public CropDetails GetCropDetails(int seedItemCode){return cropDetails.Find(x => x.seedItemCode == seedItemCode);}
}

5、填充防风草作物的数据

(1)制作Crop预制体

第1步,在Hierarchy -> PersistentScene下创建新的物体命名为CropStandard。

第2步,给该物体添加Box Collider 2D组件,并设置参数如下:

第3步,添加Crop组件和Item Nudge组件。

第4步,在CropStandard下创建子物体命名为CropSprite。

第5步,给CropSprite添加Sprite Renderer组件,并且设置参数如下:

如果Sorting Layer未设置未Instances,将导致seed无法正确显示(因为优先级不够)。

第6步,将Hierarchy下的CropStandard拖到Assets -> Prefabs -> Crop目录下,并且删除Hierarchy下的CropStandard。

(2)创建Crop的Scriptable资源

第1步,在Assets -> Scriptable Object Assets 下创建新的目录命名为Crop。

第2步,右击Crop目录,选择Scriptable Objects -> Crop -> Crop Details List,命名为so_CropDetailsList。

第3步,配置so_CropDetailsList的信息如下:

6、防风草生长

(1)优化Tags.cs脚本

添加一个变量:

public const string CropsParentTransform = "CropsParentTransform";

(2)添加Crops对象

首先,加载Scene1_Farm场景

然后,在Hierarchy -> Scene1_Farm下创建新的物体命名为Crops

接着,在Inspector界面下创建新的Tag:CropsParentTransform,并且指定Crops的Tag为新Tag。

最后,Unload Scene1_Farm场景。

对Scene2_Field场景进行同样的操作

(3)优化EventHandler.cs脚本

添加新的事件如下:

// Remove selected item from inventory
public static event Action RemoveSelectedItemFromInventoryEvent;public static void CallRemoveSelectedItemFromInventoryEvent()
{if(RemoveSelectedItemFromInventoryEvent != null){RemoveSelectedItemFromInventoryEvent();}
}

(4)优化GridPropertiesManager.cs脚本

添加变量1:

private Transform cropParentTransform;

修改AfterSceneLoaded函数,添加如下代码:

if(GameObject.FindGameObjectWithTag(Tags.CropsParentTransform) != null)
{cropParentTransform = GameObject.FindGameObjectWithTag(Tags.CropsParentTransform).transform;
}
else
{cropParentTransform = null;
}

添加变量2:

[SerializeField] private SO_CropDetailList so_CropDetailList = null;

修改ClearDisplayGridPropertyDetails函数,添加如下代码:

private void ClearDisplayAllPlantedCrops()
{// Destory all crops in sceneCrop[] cropArray;cropArray = FindObjectsOfType<Crop>();   foreach(Crop crop in cropArray){Destroy(crop.gameObject);}}private void ClearDisplayGridPropertyDetails()
{ClearDisplayGroundDecorations();ClearDisplayAllPlantedCrops();
}

修改DisplayGridPropertyDetails函数,代码如下:

private void DisplayGridPropertyDetails()
{// Loop throught all grid itemsforeach(KeyValuePair<string, GridPropertyDetails> item in gridPropertyDictionary){GridPropertyDetails gridPropertyDetails = item.Value;DisplayDugGround(gridPropertyDetails);DisplayWateredGround(gridPropertyDetails);DisplayPlantedCrop(gridPropertyDetails);}
}public void DisplayPlantedCrop(GridPropertyDetails gridPropertyDetails)
{if(gridPropertyDetails.seedItemCode > -1){// get crop detailsCropDetails cropDetails = so_CropDetailList.GetCropDetails(gridPropertyDetails.seedItemCode);// prefab to useGameObject cropPrefab;// instantiate crop prefab at grid locationint growthStages = cropDetails.growthDays.Length;int currentGrowthStage = 0;int daysCounter = cropDetails.totalGrowthDays;// 找出目前所处的成长阶段for(int i = growthStages - 1; i >= 0; i--){if(gridPropertyDetails.growthDays >= daysCounter){currentGrowthStage = i;break;}daysCounter = daysCounter - cropDetails.growthDays[i];}cropPrefab = cropDetails.growthPrefab[currentGrowthStage];Sprite growthSprite = cropDetails.growthSprite[currentGrowthStage];Vector3 worldPosition = groundDecoration2.CellToWorld(new Vector3Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY, 0));worldPosition = new Vector3(worldPosition.x + Settings.gridCellSize / 2, worldPosition.y, worldPosition.z);GameObject cropInstance = Instantiate(cropPrefab, worldPosition, Quaternion.identity);cropInstance.GetComponentInChildren<SpriteRenderer>().sprite = growthSprite;cropInstance.transform.SetParent(cropParentTransform);cropInstance.GetComponent<Crop>().cropGridPosition = new Vector2Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY);}
}

修改AdvanceDay函数,代码如下:

private void AdvanceDay(int gameYear, Season gameSeason, int gameDay, string gameDayyOfWeek, int gameHour, int gameMinute, int gameSecond)
{// Clear Display All Grid Property DetailsClearDisplayGridPropertyDetails();// loop through all scenes - by looping through all gridproperty in the arrayforeach(SO_GridProperties so_GridProperties in so_gridPropertiesArray){// Get gridpropertydetails dictionary for sceneif(GameObjectSave.sceneData.TryGetValue(so_GridProperties.sceneName.ToString(), out SceneSave sceneSave)){if(sceneSave.gridPropertyDetailsDictionary != null){for(int i = sceneSave.gridPropertyDetailsDictionary.Count - 1; i >= 0; i--){KeyValuePair<string, GridPropertyDetails> item = sceneSave.gridPropertyDetailsDictionary.ElementAt(i);GridPropertyDetails gridPropertyDetails = item.Value;#region Update all grid properties to reflect the advance in the day// if a crop is plantedif(gridPropertyDetails.growthDays > -1){gridPropertyDetails.growthDays += 1;}// if ground is watered, then clear waterif(gridPropertyDetails.daysSinceWatered > -1){gridPropertyDetails.daysSinceWatered = -1;}// Set gridpropertydetailsSetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails, sceneSave.gridPropertyDetailsDictionary);#endregion Update all grid properties to reflect the advance in the day}}}}// Display grid property details to reflect changed valuesDisplayGridPropertyDetails();
}

(5)优化Player.cs脚本

优化ProcessPlayerClickInput函数,代码如下:

修改ProcessPlayerClickInputSeed函数如下:

private void ProcessPlayerClickInputSeed(GridPropertyDetails gridPropertyDetails, ItemDetails itemDetails)
{if(itemDetails.canBeDropped && gridCursor.CursorPositionIsValid && gridPropertyDetails.daysSinceDug > -1 && gridPropertyDetails.seedItemCode == -1){PlantSeedAtCursor(gridPropertyDetails, itemDetails);}else if (itemDetails.canBeDropped && gridCursor.CursorPositionIsValid){EventHandler.CallDropSelectedItemEvent();}
}

添加PlantSeedAtCursor函数如下:

 private void PlantSeedAtCursor(GridPropertyDetails gridPropertyDetails, ItemDetails itemDetails){// update grid properties with seed detailsgridPropertyDetails.seedItemCode = itemDetails.itemCode;gridPropertyDetails.growthDays = 0;// Display planted crop at grid property detailsGridPropertiesManager.Instance.DisplayPlantedCrop(gridPropertyDetails);// Remove item from inventoryEventHandler.CallRemoveSelectedItemFromInventoryEvent();}

(6)优化UIInventorySlot.cs脚本

修改OnEnable代码,

 private void OnEnable(){EventHandler.AfterSceneLoadEvent += SceneLoaded;EventHandler.RemoveSelectedItemFromInventoryEvent += RemoveSelectedItemFromInventory;EventHandler.DropSelectedItemEvent += DropSelectedItemAtMousePosition;}

修改OnDisable代码:

private void OnDisable()
{EventHandler.AfterSceneLoadEvent -= SceneLoaded;EventHandler.RemoveSelectedItemFromInventoryEvent -= RemoveSelectedItemFromInventory;EventHandler.DropSelectedItemEvent -= DropSelectedItemAtMousePosition;
}

添加RemoveSelectedItemFromInventory函数代码:

 private void RemoveSelectedItemFromInventory(){if(itemDetails != null && isSelected){int itemCode = itemDetails.itemCode;// Remove item from players inventoryInventoryManager.Instance.RemoveItem(InventoryLocation.player, itemCode);// If no more of iitem then clear selectedif(InventoryManager.Instance.FindItemInInventory(InventoryLocation.player, itemCode) == -1){ClearSelectedItem();}}}

(7)补充配置信息

配置GridPropertiesManager的So_Crop Detail List信息如下:

7、运行游戏

先用Hoe挖一块地

然后洒下Parsnip的种子

按下G键可以加速时间,此时就可以看到防风草生长的过程。

相关文章:

Unity3D仿星露谷物语开发43之农作物生长

1、目标 把防风草种子种在地里&#xff0c;并展示植物种子&#xff0c;防风草种子将随着时间变化而生长成植株。 2、创建Crop.cs脚本 在Assets -> Scripts下创建新的目录命名为Crop&#xff0c;在其下创建新的脚本命名为Crop.cs。 代码如下&#xff1a; using System.C…...

从0到1上手Kafka:开启分布式消息处理之旅

目录 一、Kafka 是什么 二、Kafka 的基础概念 2.1 核心术语解读 2.2 工作模式剖析 三、Kafka 的应用场景 四、Kafka 与其他消息队列的比较 五、Kafka 的安装与配置 5.1 环境准备 5.2 安装步骤 5.3 常见问题及解决 六、Kafka 的基本操作 6.1 命令行工具使用 6.1.1 …...

GTS-400 系列运动控制器板卡介绍(三十四)---运动程序多线程累加求和

运动控制器函数库的使用 运动控制器驱动程序、dll 文件、例程、Demo 等相关文件请通过固高科技官网下载,网 址为:www.googoltech.com.cn/pro_view-3.html 1 Windows 系统下动态链接库的使用 在 Windows 系统下使用运动控制器,首先要安装驱动程序。在安装前需要提前下载运动…...

Python爬虫如何应对网站的反爬加密策略?

在当今的互联网环境中&#xff0c;网络爬虫已经成为数据采集的重要工具之一。然而&#xff0c;随着网站安全意识的不断提高&#xff0c;反爬虫技术也越来越复杂&#xff0c;尤其是数据加密策略的广泛应用&#xff0c;给爬虫开发者带来了巨大的挑战。本文将详细介绍Python爬虫如…...

第一次经历项目上线

这几天没写csdn&#xff0c;因为忙着项目上线的问题&#xff0c;我这阶段改了非常多的前端bug哈哈哈哈&#xff0c;说几个比较好的bug思想&#xff01; 这个页面算是我遇到的比较大的bug&#xff0c;因为我一开始的逻辑都写好了&#xff0c;询价就是在点击快递公司弹出弹框的时…...

Conda配置完全指南——Windows系统Anaconda/Miniconda的安装、配置、基础使用、清理缓存空间和Pycharm/VSCode配置指南

本文同步发布在个人博客&#xff1a; Conda配置完全指南Conda 是一个开源的跨平台包管理与环境管理工具&#xff0c;广泛应用于数据科学、机器学习及 Python 开发领域。它不仅能帮助用户快速安装、更新和卸载第三方库&#xff0c;还能创建相互隔离的虚拟环境&#xff0c;解决不…...

Quasar组件 Carousel走马灯

通过对比两个q-carousel组件来&#xff0c;了解该组件的属性 官方文档请参阅&#xff1a;Carousel 预览 源代码 <template><div class"q-pa-md"><div class"q-gutter-md"><q-carouselv-model"slide"transition-prev&quo…...

AI日报 - 2024年5月17日

&#x1f31f; 今日概览 (60秒速览) ▎&#x1f916; 大模型前沿 | OpenAI推出自主编码代理Codex&#xff1b;Google DeepMind发布Gemini驱动的编码代理AlphaEvolve&#xff0c;能设计先进算法&#xff1b;Meta旗舰AI模型Llama 4 Behemoth发布推迟。 Codex能并行处理多任务&…...

R语言数据框(datafram)数据的构建及简单分析

代码完成的功能&#xff1a; 创建数据集&#xff08;数据框&#xff09;&#xff0c; 写入到文件中&#xff0c; 显示数据&#xff0c; 分组计算平均年龄&#xff0c; 在Rstudio中&#xff0c;创建R markdown或R notebook文件运行。以下是添加了注释的完整R代码&#xff0…...

风控域——风控决策引擎系统设计

摘要 本文详细介绍了风控决策引擎系统的设计与应用。决策引擎系统是一种智能化工具&#xff0c;可自动化、数据驱动地辅助或替代人工决策&#xff0c;广泛应用于金融、医疗、营销、风控等领域。文章阐述了决策引擎的核心功能&#xff0c;包括自动化决策、动态规则管理、实时处…...

CAPL Class: TcpSocket (此类用于实现 TCP 网络通信 )

目录 Class: TcpSocketacceptopenclosebindconnectgetLastSocketErrorgetLastSocketErrorAsStringlistenreceivesendsetSocketOptionshutdown函数调用的基本流程服务器端的基本流程客户端的基本流程Class: TcpSocket学习笔记。来自CANoe帮助文档。 Class: TcpSocket accept /…...

数据分析 —— 数据预处理

一、什么是数据预处理 数据预处理&#xff08;Data Preprocessing&#xff09;是数据分析和机器学习中至关重要的步骤&#xff0c;旨在将原始数据转换为更高质量、更适合分析或建模的形式。由于真实世界的数据通常存在不完整、不一致、噪声或冗余等问题&#xff0c;预处理可以…...

软件架构风格系列(4):事件驱动架构

文章目录 前言一、从“用户下单”场景看懂事件驱动核心概念&#xff08;一&#xff09;什么是事件驱动架构&#xff1f;&#xff08;二&#xff09;核心优势&#xff1a;解耦与异步的双重魔法 二、架构设计图&#xff1a;三要素构建事件流转闭环三、Java实战&#xff1a;从简单…...

windows系统各版本下载

以下各版本Windows系统链接来自网友整理&#xff0c;请通过迅雷或者其他支持ED2K或BT的下载工具进行下载。 注&#xff1a;以下为原版系统&#xff0c;未激活、非破解版&#xff0c;仅供下载体验学习&#xff0c;请勿从事商业活动。 Windows 11 Windows 11 (consumer editions…...

arduino平台读取鼠标光电传感器

鼠标坏掉了&#xff0c;大抵是修不好了。&#xff08;全剧终—&#xff09; 但是爱动手的小明不会浪费这个鼠标&#xff0c;确认外观没有明显烧毁痕迹后&#xff0c;尝试从电路板上利用光电传感器进行位移的测量&#xff0c;光电传感器&#xff08;型号&#xff1a;FCT3065&am…...

【Linux网络】网络层

网络层 在复杂的网络环境中确定一个合适的路径 IP 协议 IPV4 点分十进制[0,255].[0,255].[0,255].[0,255]IPV6 IP地址目标网格目标主机 基本概念 主机:配有IP地址,但是不进行路由控制的设备;路由器:即配有IP地址,又能进行路由控制;节点:主机和路由器的统称。 两个问题 路…...

力扣-98.验证二叉搜索树

题目描述 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 class Solutio…...

5.17本日总结

一、英语 复习list2list29 二、数学 学习14讲部分内容 三、408 学习计组1.2内容 四、总结 高数和计网明天结束当前章节&#xff0c;计网内容学完之后主要学习计组和操作系统 五、明日计划 英语&#xff1a;复习lsit3list28&#xff0c;完成07年第二篇阅读 数学&#…...

大模型学习:Deepseek+dify零成本部署本地运行实用教程(超级详细!建议收藏)

文章目录 大模型学习&#xff1a;Deepseekdify零成本部署本地运行实用教程&#xff08;超级详细&#xff01;建议收藏&#xff09;一、Dify是什么二、Dify的安装部署1. 官网体验2. 本地部署2.1 linux环境下的Docker安装2.2 Windows环境下安装部署DockerDeskTop2.3启用虚拟机平台…...

VSCode launch.json 配置参数详解

使用 launch.json 配置调试环境时&#xff0c;会涉及到多个参数&#xff0c;用于定义调试器的行为和目标执行环境。以下是一些常用的配置参数&#xff1a; 1、"type" &#xff1a;指定调试器的类型&#xff0c;例如 "node" 表示 Node.js 调试器&#xff0…...

pytest多种断言类型封装为自动化断言规则库

以下是将多种断言类型封装为自动化断言规则库的完整实现方案,包含基础验证规则和扩展机制: import re import time from jsonschema import validate, ValidationError from typing import Dict, Any, Optional, Callableclass ResponseValidator:"""自动...

Oracle数据库如何进行冷备份和恢复

数据库的冷备份指的是数据库处于关闭或者MOUNT状态下的备份&#xff0c;备份文件包括数据文件、日志文件和控制文件。数据库冷备份所用的时间主要受数据库大小和磁盘I/O性能的影响。由于数据库需要关闭才能进行冷备份&#xff0c;所以这种备份技术并不适用724小时的系统。尽管冷…...

LeetCode Hot100 (2、3、4、5、6、8、9、12)

题2--字母异或位分词 class Solution { public:vector<vector<string>> groupAnagrams(vector<string>& strs) {// 一开始的思路是&#xff0c;对于其中的一个单词&#xff0c;遍历所有排序组合&#xff0c;然后判断这些组合是否在哈希表里//&#xff0…...

FastMCP:为大语言模型构建强大的上下文和工具服务

FastMCP&#xff1a;为大语言模型构建强大的上下文和工具服务 在人工智能快速发展的今天&#xff0c;大语言模型&#xff08;LLM&#xff09;已经成为许多应用的核心。然而&#xff0c;如何让这些模型更好地与外部世界交互&#xff0c;获取实时信息&#xff0c;执行特定任务&am…...

数据结构(3)线性表-链表-单链表

我们学习过顺序表时&#xff0c;一旦对头部或中间的数据进行处理&#xff0c;由于物理结构的连续性&#xff0c;为了不覆盖&#xff0c;都得移&#xff0c;就导致时间复杂度为O&#xff08;n&#xff09;&#xff0c;还有一个潜在的问题就是扩容&#xff0c;假如我们扩容前是10…...

Java Solon v3.3.0 发布(国产优秀应用开发基座)

Solon 框架&#xff01; Solon 是新一代&#xff0c;Java 企业级应用开发框架。从零开始构建&#xff08;No Java-EE&#xff09;&#xff0c;有灵活的接口规范与开放生态。采用商用友好的 Apache 2.0 开源协议&#xff0c;是“杭州无耳科技有限公司”开源的根级项目&#xff…...

23种设计模式概述详述(C#代码示例)

文章目录 1. 引言1.1 设计模式的价值1.2 设计模式的分类 2. 面向对象设计原则2.1 单一职责原则 (SRP)2.2 开放封闭原则 (OCP)2.3 里氏替换原则 (LSP)2.4 接口隔离原则 (ISP)2.5 依赖倒置原则 (DIP)2.6 合成复用原则 (CRP)2.7 迪米特法则 (LoD) 3. 创建型设计模式3.1 单例模式 (…...

数字化工厂升级引擎:Modbus TCP转Profinet网关助力打造柔性生产系统

在当今的工业自动化领域&#xff0c;通信协议扮演着至关重要的角色。Modbus TCP和Profinet是两种广泛使用的工业通信协议&#xff0c;它们分别在不同的应用场景中发挥着重要作用。然而&#xff0c;有时我们可能需要将这两种协议进行转换&#xff0c;以实现不同设备之间的无缝通…...

FPGA生成随机数的方法

FPGA生成随机数的方法&#xff0c;目前有以下几种: 1、震荡采样法 实现方式一&#xff1a;通过低频时钟作为D触发器的时钟输入端&#xff0c;高频时钟作为D触发器的数据输入端&#xff0c;使用高频采样低频&#xff0c;利用亚稳态输出随机数。 实现方式二&#xff1a;使用三个…...

【Linux C/C++开发】轻量级关系型数据库SQLite开发(包含性能测试代码)

前言 之前的文件分享过基于内存的STL缓存、环形缓冲区&#xff0c;以及基于文件的队列缓存mqueue、hash存储、向量库annoy存储&#xff0c;这两种属于比较原始且高效的方式。 那么&#xff0c;有没有高级且高效的方式呢。有的&#xff0c;从数据角度上看&#xff0c;&#xff0…...