欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 八卦 > Unity3D仿星露谷物语开发44之收集农作物

Unity3D仿星露谷物语开发44之收集农作物

2025/5/19 2:24:35 来源:https://blog.csdn.net/benben044/article/details/148027992  浏览:    关键词:Unity3D仿星露谷物语开发44之收集农作物

1、目标

在土地中挖掘后,洒下种子后逐渐成长,然后使用篮子收集成熟后的农作物,工具栏中也会相应地增加该农作物。

2、修改CropStandard的参数

Assets -> Prefabs -> Crop下的CropStandard,修改其Box Collider 2D的Size(Y)值为0.5。

3、修改GridCursor.cs脚本

添加如下代码:

[SerializeField] private SO_CropDetailsList so_CropDetailsList = null;

在IsCursorValidForTool函数中添加case ItemType.Collecting_tool代码:

private bool IsCursorValidForTool(GridPropertyDetails gridPropertyDetails, ItemDetails itemDetails)
{// Switch on toolswitch (itemDetails.itemType){case ItemType.Hoeing_tool:if (gridPropertyDetails.isDiggable == true && gridPropertyDetails.daysSinceDug == -1){#region Need to get any items at location so we can check if they are reapable// Get world position for cursorVector3 cursorWorldPosition = new Vector3(GetWorldPositionForCursor().x + 0.5f, GetWorldPositionForCursor().y + 0.5f, 0f);// Get list of items at cursor locationList<Item> itemList = new List<Item>();HelperMethods.GetComponentsAtBoxLocation<Item>(out itemList, cursorWorldPosition, Settings.cursorSize, 0f);#endregion// Loop through items found to see if any are reapable type - we are not goint to let the player dig where there are reapable scenary itemsbool foundReapable = false;foreach(Item item in itemList){if(InventoryManager.Instance.GetItemDetails(item.ItemCode).itemType == ItemType.Reapable_scenary){foundReapable = true;break;}}if (foundReapable){return false;}else{return true;}}else{return false;}case ItemType.Watering_tool:if(gridPropertyDetails.daysSinceDug > -1 && gridPropertyDetails.daysSinceWatered == -1){return true;}else{return false;}case ItemType.Collecting_tool:// Check if item can be harvested with item selected, check item is fully grown// Check if seed plantedif(gridPropertyDetails.seedItemCode != -1){// Get crop details for seed CropDetails cropDetails = so_CropDetailsList.GetCropDetails(gridPropertyDetails.seedItemCode);// if crop details foundif(cropDetails != null){// Check if crop fully grownif(gridPropertyDetails.growthDays >= cropDetails.totalGrowthDays){// Check if crop can be harvested with tool selectedif (cropDetails.CanUseToolToHarvestCrop(itemDetails.itemCode)){return true;}else{return false;}}else{return false;}}}return false;default:return false;}}

4、配置UIPanel的信息

Hierarchy -> PersistentScene -> UI -> MainGameUICanvas -> UICanvasGroup -> UIPanel,

配置SO_CropDetailsList的信息:

5、测试光标效果

种植完防风草,然后等待它们成长。

使用basket工具,发现只有成熟的防风草才会显示绿色光标,否则显示红色光标。

6、修改GridPropertiesManager.cs脚本

添加如下代码:

 /// <summary>/// Returns the Crop object at the gridX, gridY position or null if no crop was found/// </summary>/// <param name="gridPropertyDetails"></param>/// <returns></returns>public Crop GetCropObjectAtGridLocation(GridPropertyDetails gridPropertyDetails){Vector3 worldPosition = grid.GetCellCenterWorld(new Vector3Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY, 0));Collider2D[] collider2DArray = Physics2D.OverlapPointAll(worldPosition);// Loop through colliders to get crop game objectCrop crop = null;for(int i = 0; i < collider2DArray.Length; i++){crop = collider2DArray[i].gameObject.GetComponentInParent<Crop>();if (crop != null && crop.cropGridPosition == new Vector2Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY))break;crop = collider2DArray[i].gameObject.GetComponentInChildren<Crop>();if(crop != null && crop.cropGridPosition == new Vector2Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY))break;}return crop;}/// <summary>
/// Returns Crop Details for the provided seedItemCode
/// </summary>
/// <param name="seedItemCode"></param>
/// <returns></returns>
public CropDetails GetCropDetails(int seedItemCode)
{return so_CropDetailList.GetCropDetails(seedItemCode);
}

7、修改Settings.cs脚本

添加如下代码:

    public static float pickAnimationPause = 1f;public static float afterPickAnimationPause = 0.2f;

8、修改Player.cs脚本

添加两个属性

    private WaitForSeconds afterPickAnimationPause;private WaitForSeconds pickAnimationPause;

在Start函数中增加如下代码:

pickAnimationPause = new WaitForSeconds(Settings.pickAnimationPause);
afterPickAnimationPause = new WaitForSeconds(Settings.afterPickAnimationPause);

在ProcessPlayerClickInput函数中增加如下代码:

case ItemType.Collecting_tool:

在ProcessPlayerClickInputTool函数中添加如下代码:

case ItemType.Collecting_tool:if (gridCursor.CursorPositionIsValid){CollectInPlayerDirection(gridPropertyDetails, itemDetails, playerDirection);}break;

添加CollectInPlayerDirection函数代码如下:

private void CollectInPlayerDirection(GridPropertyDetails gridPropertyDetails, ItemDetails equippedItemDetails, Vector3Int playerDirection)
{StartCoroutine(CollectInPlayerDirectionRoutine(gridPropertyDetails, equippedItemDetails, playerDirection));
}

添加CollectInPlayerDirectionRoutine函数代码如下:

private IEnumerator CollectInPlayerDirectionRoutine(GridPropertyDetails gridPropertyDetails, ItemDetails equippedItemDetails, Vector3Int playerDirection)
{PlayerInputIsDisabled = true;playerToolUseDisabled = true;ProcessCropWithEquippedItemInPlayerDirection(playerDirection, equippedItemDetails, gridPropertyDetails);yield return pickAnimationPause; // 执行完ProcessCropWithEquippedItemInPlayerDirection的时间// After animation pauseyield return afterPickAnimationPause;PlayerInputIsDisabled = false;playerToolUseDisabled = false;
}

添加ProcessCropWithEquippedItemInPlayerDirection函数代码如下:

/// <summary>/// Method processes crop with equipped item in player direction/// </summary>/// <param name="playerDirection"></param>/// <param name="equippedItemDetails"></param>/// <param name="gridPropertyDetails"></param>private void ProcessCropWithEquippedItemInPlayerDirection(Vector3Int playerDirection, ItemDetails equippedItemDetails, GridPropertyDetails gridPropertyDetails){switch (equippedItemDetails.itemType){case ItemType.Collecting_tool:if(playerDirection == Vector3Int.right){isPickingRight = true;}else if(playerDirection == Vector3Int.left){isPickingLeft = true;}else if(playerDirection == Vector3Int.up){isPickingUp = true;}else if(playerDirection == Vector3Int.down){isPickingDown = true;}break;case ItemType.none:break;}// Get crop at cursor grid locationCrop crop = GridPropertiesManager.Instance.GetCropObjectAtGridLocation(gridPropertyDetails);// Execute Process Tool Action For cropif(crop != null){switch (equippedItemDetails.itemType){case ItemType.Collecting_tool:crop.ProcessToolAction(equippedItemDetails);break;}}}

此时,Player.cs完整的代码如下:

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;public class Player : SingletonMonobehaviour<Player>
{public GameObject canyonOakTreePrefab;private WaitForSeconds afterUseToolAnimationPause;private WaitForSeconds useToolAnimationPause;private WaitForSeconds afterLiftToolAnimationPause;private WaitForSeconds liftToolAnimationPause;private WaitForSeconds afterPickAnimationPause;private WaitForSeconds pickAnimationPause;private bool playerToolUseDisabled = false;  // 如果玩家正在使用某个道具,其他道具将被禁用private AnimationOverrides animationOverrides;  // 动画重写控制器private GridCursor gridCursor;private Cursor cursor;private List<CharacterAttribute> characterAttributeCustomisationList;  // 目标动作列表[Tooltip("Should be populated in the prefab with the equippped item sprite renderer")][SerializeField] private SpriteRenderer equippedItemSpriteRenderer = null; // 武器的图片// Player attributes that can be swappedprivate CharacterAttribute armsCharacterAttribute;private CharacterAttribute toolCharacterAttribute;private float xInput;private float yInput;private bool isWalking;private bool isRunning;private bool isIdle;private bool isCarrying = false;private ToolEffect toolEffect = ToolEffect.none;private bool isUsingToolRight;private bool isUsingToolLeft;private bool isUsingToolUp;private bool isUsingToolDown;private bool isLiftingToolRight;private bool isLiftingToolLeft;private bool isLiftingToolUp;private bool isLiftingToolDown;private bool isPickingRight;private bool isPickingLeft;private bool isPickingUp;private bool isPickingDown;private bool isSwingToolRight;private bool isSwingToolLeft;private bool isSwingToolUp;private bool isSwingToolDown;private Camera mainCamera;private Rigidbody2D rigidbody2D;private Direction playerDirection;private float movementSpeed;private bool _playerInputIsDisabled = false;public bool PlayerInputIsDisabled { get => _playerInputIsDisabled; set => _playerInputIsDisabled = value; }protected override void Awake(){base.Awake();rigidbody2D = GetComponent<Rigidbody2D>();animationOverrides = GetComponentInChildren<AnimationOverrides>();// Initialise swappable character attributesarmsCharacterAttribute = new CharacterAttribute(CharacterPartAnimator.arms, PartVariantColour.none, PartVariantType.none);toolCharacterAttribute = new CharacterAttribute(CharacterPartAnimator.tool, PartVariantColour.none, PartVariantType.none);// Initialise character attribute listcharacterAttributeCustomisationList = new List<CharacterAttribute>();mainCamera = Camera.main;}private void OnDisable(){EventHandler.BeforeSceneUnloadFadeOutEvent -= DisablePlayerInputAndResetMovement;EventHandler.AfterSceneLoadFadeInEvent -= EnablePlayerInput;}private void OnEnable(){EventHandler.BeforeSceneUnloadFadeOutEvent += DisablePlayerInputAndResetMovement;EventHandler.AfterSceneLoadFadeInEvent += EnablePlayerInput;}private void Start(){gridCursor = FindObjectOfType<GridCursor>();cursor = FindObjectOfType<Cursor>();useToolAnimationPause = new WaitForSeconds(Settings.useToolAnimationPause);afterUseToolAnimationPause = new WaitForSeconds(Settings.afterUseToolAnimationPause);liftToolAnimationPause = new WaitForSeconds(Settings.liftToolAnimationPause);afterLiftToolAnimationPause = new WaitForSeconds(Settings.afterLiftToolAnimationPause);pickAnimationPause = new WaitForSeconds(Settings.pickAnimationPause);afterPickAnimationPause = new WaitForSeconds(Settings.afterPickAnimationPause);}private void Update(){#region  Player Inputif (!PlayerInputIsDisabled){ResetAnimationTrigger();PlayerMovementInput();PlayerWalkInput();PlayerClickInput();PlayerTestInput();// Send event to any listeners for player movement inputEventHandler.CallMovementEvent(xInput, yInput, isWalking, isRunning, isIdle, isCarrying, toolEffect,isUsingToolRight, isUsingToolLeft, isUsingToolUp, isUsingToolDown,isLiftingToolRight, isLiftingToolLeft, isLiftingToolUp, isLiftingToolDown,isPickingRight, isPickingLeft, isPickingUp, isPickingDown,isSwingToolRight, isSwingToolLeft, isSwingToolUp, isSwingToolDown,false, false, false, false);}#endregion Player Input}private void FixedUpdate(){PlayerMovement();}/// <summary>/// 展示拿东西的动画/// </summary>/// <param name="itemCode"></param>public void ShowCarriedItem(int itemCode){ItemDetails itemDetails = InventoryManager.Instance.GetItemDetails(itemCode);if(itemDetails != null){equippedItemSpriteRenderer.sprite = itemDetails.itemSprite;equippedItemSpriteRenderer.color = new Color(1f, 1f, 1f, 1f);// Apply 'carry' character arms customisationarmsCharacterAttribute.partVariantType = PartVariantType.carry;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(armsCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);isCarrying = true;}}public void ClearCarriedItem(){equippedItemSpriteRenderer.sprite = null;equippedItemSpriteRenderer.color = new Color(1f, 1f, 1f, 0f);// Apply base character arms customisationarmsCharacterAttribute.partVariantType = PartVariantType.none;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(armsCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);isCarrying = false;}private void PlayerMovement(){Vector2 move = new Vector2(xInput * movementSpeed * Time.deltaTime, yInput * movementSpeed * Time.deltaTime);rigidbody2D.MovePosition(rigidbody2D.position + move);}private void ResetAnimationTrigger(){toolEffect = ToolEffect.none;isUsingToolRight = false;isUsingToolLeft = false;isUsingToolUp = false;isUsingToolDown = false;isLiftingToolRight = false;isLiftingToolLeft = false;isLiftingToolUp = false;isLiftingToolDown = false;isPickingRight = false;isPickingLeft = false;isPickingUp = false;isPickingDown = false;isSwingToolRight = false;isSwingToolLeft = false;isSwingToolUp = false;isSwingToolDown = false;}private void PlayerMovementInput(){xInput = Input.GetAxisRaw("Horizontal");yInput = Input.GetAxisRaw("Vertical");// 斜着移动if (xInput != 0 && yInput != 0) {xInput = xInput * 0.71f;yInput = yInput * 0.71f;}// 在移动if (xInput != 0 || yInput != 0) {isRunning = true;isWalking = false;isIdle = false;movementSpeed = Settings.runningSpeed;// Capture player direction for save gameif (xInput < 0){playerDirection = Direction.left;}else if (xInput > 0){playerDirection = Direction.right;}else if (yInput < 0){playerDirection = Direction.down;}else{playerDirection = Direction.up;}}else if(xInput == 0 && yInput == 0){isRunning = false;isWalking = false;isIdle = true;}}// 按住Shift键移动为walkprivate void PlayerWalkInput(){if(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)){isRunning = false;isWalking = true;isIdle = false;movementSpeed = Settings.walkingSpeed;}else{isRunning = true;isWalking = false;isIdle = false;movementSpeed = Settings.runningSpeed;}}private void PlayerClickInput(){if (!playerToolUseDisabled){if (Input.GetMouseButton(0)){if (gridCursor.CursorIsEnabled || cursor.CursorIsEnable){// Get Cursor Grid PositionVector3Int cursorGridPosition = gridCursor.GetGridPositionForCursor();// Get Player Grid PositionVector3Int playerGridPosition = gridCursor.GetGridPositionForPlayer();ProcessPlayerClickInput(cursorGridPosition, playerGridPosition);}}}}private void ProcessPlayerClickInput(Vector3Int cursorGridPosition, Vector3Int playerGridPosition){ResetMovement();Vector3Int playerDirection = GetPlayerClickDirection(cursorGridPosition, playerGridPosition);// Get Selected item detailsItemDetails itemDetails = InventoryManager.Instance.GetSelectedInventoryItemDetails(InventoryLocation.player);// Get Grid property details at cursor position (the GridCursor validation routine ensures that grid property details are not null)GridPropertyDetails gridPropertyDetails = GridPropertiesManager.Instance.GetGridPropertyDetails(cursorGridPosition.x, cursorGridPosition.y);if(itemDetails != null){switch (itemDetails.itemType){case ItemType.Seed:if (Input.GetMouseButtonDown(0)){ProcessPlayerClickInputSeed(gridPropertyDetails, itemDetails);}break;case ItemType.Commodity:if (Input.GetMouseButtonDown(0)){ProcessPlayerClickInputCommodity(itemDetails);}break;case ItemType.Watering_tool:case ItemType.Hoeing_tool:case ItemType.Reaping_tool:case ItemType.Collecting_tool:ProcessPlayerClickInputTool(gridPropertyDetails, itemDetails, playerDirection);break;case ItemType.none:break;case ItemType.count:break;default:break;}}}private Vector3Int GetPlayerClickDirection(Vector3Int cursorGridPosition, Vector3Int playerGridPosition) {if(cursorGridPosition.x > playerGridPosition.x){return Vector3Int.right;}else if(cursorGridPosition.x < playerGridPosition.x){return Vector3Int.left;}else if(cursorGridPosition.y > playerGridPosition.y){return Vector3Int.up;}else{return Vector3Int.down;}}private Vector3Int GetPlayerDirection(Vector3 cursorPosition, Vector3 playerPosition){if(cursorPosition.x > playerPosition.x&&cursorPosition.y < (playerPosition.y + cursor.ItemUseRadius / 2f)&&cursorPosition.y > (playerPosition.y - cursor.ItemUseRadius / 2f)){return Vector3Int.right;}else if(cursorPosition.x < playerPosition.x&&cursorPosition.y < (playerPosition.y + cursor.ItemUseRadius / 2f)&&cursorPosition.y > (playerPosition.y - cursor.ItemUseRadius / 2f)){return Vector3Int.left;}else if(cursorPosition.y > playerPosition.y){return Vector3Int.up;}else{return Vector3Int.down;}}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();}}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();}private void ProcessPlayerClickInputCommodity(ItemDetails itemDetails){if(itemDetails.canBeDropped && gridCursor.CursorPositionIsValid){EventHandler.CallDropSelectedItemEvent();}}private void ProcessPlayerClickInputTool(GridPropertyDetails gridPropertyDetails, ItemDetails itemDetails, Vector3Int playerDirection){// Switch on toolswitch (itemDetails.itemType){case ItemType.Hoeing_tool:if (gridCursor.CursorPositionIsValid){HoeGroundAtCursor(gridPropertyDetails, playerDirection);}break;case ItemType.Watering_tool:if (gridCursor.CursorPositionIsValid){WaterGroundAtCursor(gridPropertyDetails, playerDirection);}break;case ItemType.Collecting_tool:if (gridCursor.CursorPositionIsValid){CollectInPlayerDirection(gridPropertyDetails, itemDetails, playerDirection);}break;case ItemType.Reaping_tool:if (cursor.CursorPositionIsValid){playerDirection = GetPlayerDirection(cursor.GetWorldPositionForCursor(), GetPlayerCentrePosition());ReapInPlayerDirectionAtCursor(itemDetails, playerDirection);}break;default:break;}}private void ReapInPlayerDirectionAtCursor(ItemDetails itemDetails, Vector3Int playerDirection){StartCoroutine(ReapInPlayerDirectionAtCursorRoutine(itemDetails, playerDirection));}private IEnumerator ReapInPlayerDirectionAtCursorRoutine(ItemDetails itemDetails, Vector3Int playerDirection){PlayerInputIsDisabled = true;playerToolUseDisabled = true;// Set tool animation to scythe in override animationtoolCharacterAttribute.partVariantType = PartVariantType.scythe;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(toolCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);// Reap in player directionUseToolInPlayerDirection(itemDetails, playerDirection);yield return useToolAnimationPause;PlayerInputIsDisabled = false;playerToolUseDisabled = false;}private void UseToolInPlayerDirection(ItemDetails equippedItemDetails, Vector3Int playerDirection){if (Input.GetMouseButton(0)){switch (equippedItemDetails.itemType){case ItemType.Reaping_tool:if(playerDirection == Vector3Int.right){isSwingToolRight = true;}else if(playerDirection == Vector3Int.left){isSwingToolLeft = true;}else if(playerDirection == Vector3Int.up){isSwingToolUp = true;}else if(playerDirection == Vector3Int.down){isSwingToolDown = true;}break;}// Define centre point of square which will be used for collision testing,检测碰撞的中心点位置Vector2 point = new Vector2(GetPlayerCentrePosition().x + playerDirection.x * (equippedItemDetails.itemUseRadius / 2f),GetPlayerCentrePosition().y + playerDirection.y * (equippedItemDetails.itemUseRadius / 2f));// Define size of the square which will be used for collision testingVector2 size = new Vector2(equippedItemDetails.itemUseRadius, equippedItemDetails.itemUseRadius);// Get Item components with 2D collider located in the square at the centre point defined (2d colliders tested limited to maxCollidersToTestPerReapSwing)Item[] itemArray = HelperMethods.GetComponentsAtBoxLocationNonAlloc<Item>(Settings.maxCollidersToTestPerReapSwing, point, size, 0f);int reapableItemCount = 0;// Loop through all items retrievedfor(int i = itemArray.Length - 1; i >= 0; i--){if(itemArray[i] != null){// Destory item game object if reapableif (InventoryManager.Instance.GetItemDetails(itemArray[i].ItemCode).itemType == ItemType.Reapable_scenary){// Effect positionVector3 effectPosition = new Vector3(itemArray[i].transform.position.x, itemArray[i].transform.position.y + Settings.gridCellSize / 2f,itemArray[i].transform.position.z);// Trigger reaping effectEventHandler.CallHarvestActionEffectEvent(effectPosition, HarvestActionEffect.reaping);Destroy(itemArray[i].gameObject);reapableItemCount++;if (reapableItemCount >= Settings.maxTargetComponentsToDestroyPerReapSwing)break;}}}}}private void WaterGroundAtCursor(GridPropertyDetails gridPropertyDetails, Vector3Int playerDirection) { // Trigger animationStartCoroutine(WaterGroundAtCursorRoutine(playerDirection, gridPropertyDetails));}private IEnumerator WaterGroundAtCursorRoutine(Vector3Int playerDirection, GridPropertyDetails gridPropertyDetails) {PlayerInputIsDisabled = true;playerToolUseDisabled = true;// Set tool animation to watering can in override animationtoolCharacterAttribute.partVariantType = PartVariantType.wateringCan;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(toolCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);toolEffect = ToolEffect.watering;if(playerDirection == Vector3Int.right){isLiftingToolRight = true;}else if(playerDirection == Vector3Int.left){isLiftingToolLeft = true;}else if(playerDirection == Vector3Int.up){isLiftingToolUp = true;}else if(playerDirection == Vector3Int.down){isLiftingToolDown = true;}yield return liftToolAnimationPause;// Set Grid property details for watered groundif(gridPropertyDetails.daysSinceWatered == -1){gridPropertyDetails.daysSinceWatered = 0;}// Set grid property to wateredGridPropertiesManager.Instance.SetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails);// Display watered grid tilesGridPropertiesManager.Instance.DisplayWateredGround(gridPropertyDetails);// After animation pauseyield return afterLiftToolAnimationPause;PlayerInputIsDisabled = false;playerToolUseDisabled = false;}private void CollectInPlayerDirection(GridPropertyDetails gridPropertyDetails, ItemDetails equippedItemDetails, Vector3Int playerDirection){StartCoroutine(CollectInPlayerDirectionRoutine(gridPropertyDetails, equippedItemDetails, playerDirection));}private IEnumerator CollectInPlayerDirectionRoutine(GridPropertyDetails gridPropertyDetails, ItemDetails equippedItemDetails, Vector3Int playerDirection){PlayerInputIsDisabled = true;playerToolUseDisabled = true;ProcessCropWithEquippedItemInPlayerDirection(playerDirection, equippedItemDetails, gridPropertyDetails);yield return pickAnimationPause; // 执行完ProcessCropWithEquippedItemInPlayerDirection的时间// After animation pauseyield return afterPickAnimationPause;PlayerInputIsDisabled = false;playerToolUseDisabled = false;}/// <summary>/// Method processes crop with equipped item in player direction/// </summary>/// <param name="playerDirection"></param>/// <param name="equippedItemDetails"></param>/// <param name="gridPropertyDetails"></param>private void ProcessCropWithEquippedItemInPlayerDirection(Vector3Int playerDirection, ItemDetails equippedItemDetails, GridPropertyDetails gridPropertyDetails){switch (equippedItemDetails.itemType){case ItemType.Collecting_tool:if(playerDirection == Vector3Int.right){isPickingRight = true;}else if(playerDirection == Vector3Int.left){isPickingLeft = true;}else if(playerDirection == Vector3Int.up){isPickingUp = true;}else if(playerDirection == Vector3Int.down){isPickingDown = true;}break;case ItemType.none:break;}// Get crop at cursor grid locationCrop crop = GridPropertiesManager.Instance.GetCropObjectAtGridLocation(gridPropertyDetails);// Execute Process Tool Action For cropif(crop != null){switch (equippedItemDetails.itemType){case ItemType.Collecting_tool:crop.ProcessToolAction(equippedItemDetails);break;}}}private void HoeGroundAtCursor(GridPropertyDetails gridPropertyDetails, Vector3Int playerDirection) {// Trigger animationStartCoroutine(HoeGroundAtCursorRoutine(playerDirection, gridPropertyDetails));}private IEnumerator HoeGroundAtCursorRoutine(Vector3Int playerDirection, GridPropertyDetails gridPropertyDetails){PlayerInputIsDisabled = true;playerToolUseDisabled = true;// Set tool animation to hoe in override animationtoolCharacterAttribute.partVariantType = PartVariantType.hoe;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(toolCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);if(playerDirection == Vector3Int.right){isUsingToolRight = true;}else if(playerDirection == Vector3Int.left){isUsingToolLeft = true;}else if(playerDirection == Vector3Int.up){isUsingToolUp = true;}else if(playerDirection == Vector3Int.down){isUsingToolDown = true;}yield return useToolAnimationPause;// Set Grid property details for dug groundif(gridPropertyDetails.daysSinceDug == -1){gridPropertyDetails.daysSinceDug = 0;}// Set grid property to dugGridPropertiesManager.Instance.SetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails);// Display dug grid tilesGridPropertiesManager.Instance.DisplayDugGround(gridPropertyDetails);// After animation pauseyield return afterUseToolAnimationPause;PlayerInputIsDisabled = false;playerToolUseDisabled = false;}public Vector3 GetPlayerViewportPosition(){// Vector3 viewport position for player (0,0) viewport bottom left, (1,1) viewport top rightreturn mainCamera.WorldToViewportPoint(gameObject.transform.position);}public Vector3 GetPlayerCentrePosition(){return new Vector3(transform.position.x, transform.position.y + Settings.playerCentreYOffset, transform.position.z);}public void DisablePlayerInputAndResetMovement(){DisablePlayerInpupt();ResetMovement();// Send event to any listeners for player movement inputEventHandler.CallMovementEvent(xInput, yInput, isWalking, isRunning, isIdle, isCarrying, toolEffect,isUsingToolRight, isUsingToolLeft, isUsingToolUp, isUsingToolDown,isLiftingToolRight, isLiftingToolLeft, isLiftingToolUp, isLiftingToolDown,isPickingRight, isPickingLeft, isPickingUp, isPickingDown,isSwingToolRight, isSwingToolLeft, isSwingToolUp, isSwingToolDown,false, false, false, false);}private void ResetMovement(){// Reset movementxInput = 0f;yInput = 0f;isRunning = false;isWalking = false;isIdle = true;}public void DisablePlayerInpupt(){PlayerInputIsDisabled = true;}public void EnablePlayerInput(){PlayerInputIsDisabled = false;}/// <summary>/// Temp routine for test input/// </summary>private void PlayerTestInput(){// Trigger Advance Timeif (Input.GetKeyDown(KeyCode.T)){TimeManager.Instance.TestAdvanceGameMinute();}// Trigger Advance Dayif (Input.GetKeyDown(KeyCode.G)){TimeManager.Instance.TestAdvanceGameDay();}// Test scene unload / loadif (Input.GetKeyDown(KeyCode.L)){SceneControllerManager.Instance.FadeAndLoadScene(SceneName.Scene1_Farm.ToString(), transform.position);}// Test object poolif (Input.GetMouseButtonDown(1)){GameObject tree = PoolManager.Instance.ReuseObject(canyonOakTreePrefab, mainCamera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,Input.mousePosition.y, -mainCamera.transform.position.z)), Quaternion.identity);tree.SetActive(true);}}
}

9、修改Crop.cs脚本

完整代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Crop : MonoBehaviour
{[HideInInspector]public Vector2Int cropGridPosition;private int harvestActionCount = 0;public void ProcessToolAction(ItemDetails equippedItemDetails){// 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 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(cropDetails, gridPropertyDetails);}private void HarvestCrop(CropDetails cropDetails, GridPropertyDetails gridPropertyDetails){// Delete crop from grid propertiesgridPropertyDetails.seedItemCode = -1;gridPropertyDetails.growthDays = -1;gridPropertyDetails.daysSinceLastHarvest = -1;gridPropertyDetails.daysSinceWatered = -1;GridPropertiesManager.Instance.SetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails);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);}}}}}

10、修改InventoryManager.cs脚本

添加如下代码:

public void AddItem(InventoryLocation inventoryLocation, int itemCode)
{List<InventoryItem> inventoryList = inventoryLists[(int)inventoryLocation];// Check if inventory already contains the itemint itemPosition = FindItemInInventory(inventoryLocation, itemCode);if(itemPosition != -1){AddItemPosition(inventoryList, itemCode, itemPosition);}else{AddItemPosition(inventoryList, itemCode);}// Send event that inventory has been updatedEventHandler.CallInventoryUpdatedEvent(inventoryLocation, inventoryLists[(int)inventoryLocation]);
}

11、修改SceneItemsManager.cs脚本

增加如下代码:

private void InstantiateSceneItem(int ItemCode, Vector3 position)
{GameObject itemGameObject = Instantiate(itemPrefab, position, Quaternion.identity, parentItem);Item item = itemGameObject.GetComponent<Item>();item.ItemCode = ItemCode;
}

12、修改SO_CropDetailsList的配置

修改10006的配置:

勾选spawnCropProducedAtPlayerPosition,使得收获的农作物在Inventory中展示。

13、运行游戏

防风草种子成熟后,点击篮子进行采摘,则防风草会出现在最后一个Slot中。

如果Slot之前已经有防风草了,则会直接往上加数量。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词