Unity3D仿星露谷物语开发45之收集农作物特效
1、目的
收集农作物的特效制作。
2、动画制作
(1)已有动画系统
在Assets -> Animation -> Crop -> Standard下有Crop的动画信息。
harvestleft/harvestright:比如防风草收获时的动效
usetoolleft/usetoolright:需要借助工具才能收获的动销,比如使用斧头砍树,树会左右晃动
点击CropPickedLeft的Animation Clip,选择Unity Model,点击播放,没有任何反应。我们需要根据这个Clip进行定制。
在Animation界面中,CropHarvestLeft使用了CropPickedLeft动画,CropHarvestRight使用了CropPickedRight动画,但是都使用了同一个Sprite游戏对象。
我们需要修改标准预制作物(Prefabs下的CropStandard),在其中增加一些额外的东西,同时符合原有的动画结构。
(2)修改Prefab
Assets -> Prefabs -> Crop,给CropSprite添加动画器组件。
我们需要一个子游戏对象,在这个游戏对象的根级别下面,创建新物体命名为CropHarvestedSprite,这个游戏对象就是Animator要操纵的游戏物体。
添加Sprite Renderer组件,并且修改Sorting Layer为Instances。
3、修改Crop.cs脚本
[Tooltip("This should be populated from child gameobject")]
[SerializeField] private SpriteRenderer cropHarvestedSpriteRenderer = null;
接下来就是用代码来触发动画特效。
添加其他修改后,完整的代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Crop : MonoBehaviour
{[HideInInspector]public Vector2Int cropGridPosition;[Tooltip("This should be populated from child gameobject")][SerializeField] private SpriteRenderer cropHarvestedSpriteRenderer = null;private int harvestActionCount = 0;public void ProcessToolAction(ItemDetails equippedItemDetails, bool isToolRight, bool isToolLeft, bool isToolDown, bool isToolUp){// Get grid property detailsGridPropertyDetails gridPropertyDetails = GridPropertiesManager.Instance.GetGridPropertyDetails(cropGridPosition.x, cropGridPosition.y);if (gridPropertyDetails == null)return;// Get seed item detailsItemDetails seedItemDetails = InventoryManager.Instance.GetItemDetails(gridPropertyDetails.seedItemCode);if(seedItemDetails == null) return;// Get crop detailsCropDetails cropDetails = GridPropertiesManager.Instance.GetCropDetails(seedItemDetails.itemCode);if (cropDetails == null) return;// Get animator for crop if presentAnimator animator = GetComponentInChildren<Animator>();// Trigger tool animationif(animator != null){if(isToolRight || isToolUp){animator.SetTrigger("usetoolright");}else if(isToolLeft || isToolDown){animator.SetTrigger("usetoolleft");}}// Get required harvest actions for tool(收获此农作物所需的操作次数)int requiredHarvestActions = cropDetails.RequiredHarvestActionsForTool(equippedItemDetails.itemCode);if (requiredHarvestActions == -1) return;// Increment harvest action countharvestActionCount++;// Check if required harvest actions madeif (harvestActionCount >= requiredHarvestActions)HarvestCrop(isToolRight, isToolUp, cropDetails, gridPropertyDetails, animator);}private void HarvestCrop(bool isUsingToolRight, bool isUsingToolUp, CropDetails cropDetails, GridPropertyDetails gridPropertyDetails, Animator animator){// Is there a harvested animationif(cropDetails.isHarvestedAnimation && animator != null){// if harvest sprite then add to sprite rendererif(cropDetails.harvestedSprite != null){if(cropHarvestedSpriteRenderer != null){cropHarvestedSpriteRenderer.sprite = cropDetails.harvestedSprite; // 一张图片}}if(isUsingToolRight || isUsingToolUp){animator.SetTrigger("harvestright");}else{animator.SetTrigger("harvestleft");}}// Delete crop from grid propertiesgridPropertyDetails.seedItemCode = -1;gridPropertyDetails.growthDays = -1;gridPropertyDetails.daysSinceLastHarvest = -1;gridPropertyDetails.daysSinceWatered = -1;// Should the crop be hidden before the harvested animationif (cropDetails.hideCropBeforeHarvestedAnimation){GetComponentInChildren<SpriteRenderer>().enabled = false;}GridPropertiesManager.Instance.SetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails);// Is there a harvested animation - Destory this crop game object after animation completedif(cropDetails.isHarvestedAnimation && animator != null){StartCoroutine(ProcessHarvestedActionsAfterAnimation(cropDetails, gridPropertyDetails, animator));}else{HarvestActions(cropDetails, gridPropertyDetails);}}private IEnumerator ProcessHarvestedActionsAfterAnimation(CropDetails cropDetails, GridPropertyDetails gridPropertyDetails, Animator animator){while (!animator.GetCurrentAnimatorStateInfo(0).IsName("Harvested")){// 等待动画播放完毕yield return null;}HarvestActions(cropDetails, gridPropertyDetails);}private void HarvestActions(CropDetails cropDetails, GridPropertyDetails gridPropertyDetails){SpawnHarvestedItems(cropDetails);Destroy(gameObject); // destory当前Crop类所挂载的实例}private void SpawnHarvestedItems(CropDetails cropDetails){// Spawn the item(s) to be producedfor(int i = 0; i < cropDetails.cropProducedItemCode.Length; i++){int cropsToProduce;// Calculate how many crops to produceif (cropDetails.cropProducedMinQuantity[i] == cropDetails.cropProducedMaxQuantity[i] ||cropDetails.cropProducedMaxQuantity[i] < cropDetails.cropProducedMinQuantity[i]){cropsToProduce = cropDetails.cropProducedMinQuantity[i];}else{cropsToProduce = Random.Range(cropDetails.cropProducedMinQuantity[i], cropDetails.cropProducedMaxQuantity[i] + 1);}for(int j = 0; j < cropsToProduce; j++){Vector3 spawnPosition;if (cropDetails.spawnCropProducedAtPlayerPosition){// Add item to the players inventoryInventoryManager.Instance.AddItem(InventoryLocation.player, cropDetails.cropProducedItemCode[i]);}else{// Random positionspawnPosition = new Vector3(transform.position.x + Random.Range(-1f, 1f), transform.position.y + Random.Range(-1f, 1f), 0f);SceneItemsManager.Instance.InstantiateSceneItem(cropDetails.cropProducedItemCode[i], spawnPosition);}}}}}
4、修改Player.cs脚本
修改ProcessCropWithEquippedItemInPlayerDirection函数,根据ProcessToolAction的调整,相应增加4个参数如下:
5、修改CropStandard预制体信息
6、运行游戏
此时收集防风草,就看到了防风草升起来的动效了。
7、优化脚本
当种植防风草种子的时候,程序运行正常。
当种植其他中的时候,程序就会报错,报错信息如下:
这是因为我们的So_CropDetailsList只配置了10006这一个种子的信息,所以获取不到其他种子的信息。
(1)优化Play.cs脚本
针对PlantSeedAtCursor函数添加校验:
(2)优化GridPropertiesManager.cs脚本
针对DisplayPlantedCrop函数添加校验:
此时,种植橡木种子不会报错,当然也不会有任何效果。