1、目標
種植一棵橡樹,從種子變成大樹。
然后可以使用斧頭砍伐橡樹。
2、刪除totalGrowthDays字段
修改growthDays的含義,定義每個值為到達當前階段的累加天數。此時最后一個階段就是totalGrowthDays的含義。所以就可以刪除totalGrowthDays字段。
(1)修改SO_CropDetailsList的配置信息
修改前的GrowthDays的配置信息:
修改后的GrowthDays的配置信息:
每個值換成了累加的方式。
(2)修改CropDetails.cs腳本
刪除totalGrowthDays字段。
(3)修改GridPropertiesManager.cs腳本
找出目前所處的成長階段換成如下的代碼:
// 找出目前所處的成長階段
for (int i = growthStages - 1; i >= 0; i--)
{if (gridPropertyDetails.growthDays >= cropDetails.growthDays[i]){currentGrowthStage = i;break;}
}
(3)修改GridCursor.cs腳本
Check if crop fully grown的邏輯修改如下:
3、修改CropStandard預制體的配置
修改CropSprite的Sprite Sort Point為Pivot。
修改CropHarvestedSprite的Sprite Sort Point為Pivot,Order in Layer為1。
調整完成后,收獲的防風草會顯示在Player之前,如下所示:
4、動畫系統
已有的動畫為:
查看TreeFallingLeft節點:
根級別的Sprite Renderer值為0,被禁用了。
子級別有Top和Trunk兩個Sprite Renderer組件。
這就要求動畫綁定的預設體有同樣的結構。
5、創建橡樹預設體
(1)創建CropTreeCanyonOak
在Hierarchy -> PersistentScene下新創建一個物體命名為CropTreeCanyonOak。
添加Box Collider 2D組件和Crop組件,相關配置信息如下:
(2)創建CropSprite
在CropTreeCanyonOak下創建子物體命名為CropSprite。
添加Sorting Group、Sprite Renderer、Animator組件,相應的配置信息如下:
雙擊Animator下的Controller(Tree),在Animation界面可以看到相關配置被黃色高亮顯示,這表明animator識別不到相關的對象。
(3)創建Trunk
在CropSprite下創建物體命名為Trunk,添加組件信息如下:
Auto Tiling(自動貼片)的作用:要是你把 Box Collider 2D 組件添加到使用了瓦片精靈的 Sprite(精靈)上,并且開啟了 Auto Tiling,這個組件就能夠依據精靈的瓦片布局,自動對碰撞體的形狀和大小進行調整。
- 貼合瓦片形狀:它會按照精靈所使用的瓦片圖集的邊界,自動調整碰撞體的輪廓,讓碰撞檢測與精靈的視覺外觀精準匹配。
- 處理多瓦片精靈:當精靈由多個瓦片組合而成時,Auto Tiling 能夠自動生成一個覆蓋所有瓦片的組合碰撞體,而無需你手動去調整每個瓦片的碰撞體。
- 提升效率:對于復雜的瓦片地圖,開啟 Auto Tiling 可以節省大量手動設置碰撞體的時間,避免逐個為瓦片添加碰撞體。
添加完成后,Animation下的Trunk立馬置灰(正常狀態)。
(4)創建Top
在CropSprite下創建子物體命名為Top,添加相關組件的配置信息如下:
添加完成后,Animation下的Top立馬置灰(正常狀態)。
(5)查看特效
點擊CropSprite,點擊Animation下的播放,可以看到特效。
(6)移動Prefab
將CropTreeCanyonOak從Hierarchy移動到Assets -> Prefabs -> Crop下。
并且刪除Hierarchy下的CropTreeCanyonOak。
6、SO_CropDetailsList添加配置
因為Growth Prefab第5個Prefab已經有圖片信息,所以Growth Sprite第5個不再需要圖片信息。
7、運行游戲1
首先挖5塊土,然后放入橡木種子。
走過未成熟的橡木時,樹木會左右晃動。經過成熟的橡木后方時,會有褪色的效果。
接下來處理使用斧頭砍伐成年橡樹的邏輯。
8、修改GridCursor.cs腳本
修改IsCursorValidForTool函數,添加下面一行代碼:
9、修改Player.cs腳本
在ProcessPlayerClickInput函數中添加一行代碼:
在ProcessPlayerClickInputTool函數中,添加一個case如下:
case ItemType.Chopping_tool:if (gridCursor.CursorPositionIsValid){ChopInPlayerDirection(gridPropertyDetails, itemDetails, playerDirection);}break;
添加ChopInPlayerDirection函數如下:
private void ChopInPlayerDirection(GridPropertyDetails gridPropertyDetails, ItemDetails itemDetails, Vector3Int playerDirection)
{// Trigger animationStartCoroutine(ChopInPlayerDirectionRoutine(gridPropertyDetails, itemDetails, playerDirection));
}
添加ChopInPlayerDirectionRoutine函數如下:
private IEnumerator ChopInPlayerDirectionRoutine(GridPropertyDetails gridPropertyDetails, ItemDetails equippedItemDetails, Vector3Int playerDirection)
{PlayerInputIsDisabled = true;playerToolUseDisabled = true;// Set tool animation to axe in override animationtoolCharacterAttribute.partVariantType = PartVariantType.axe;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(toolCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);ProcessCropWithEquippedItemInPlayerDirection(playerDirection, equippedItemDetails, gridPropertyDetails);yield return useToolAnimationPause;// After animation pause yield return useToolAnimationPause;PlayerInputIsDisabled = false;playerToolUseDisabled = false;
}
修改ProcessCropWithEquippedItemInPlayerDirection如下,添加了對case?ItemType.Chopping_tool的支持。
private void ProcessCropWithEquippedItemInPlayerDirection(Vector3Int playerDirection, ItemDetails equippedItemDetails, GridPropertyDetails gridPropertyDetails)
{switch (equippedItemDetails.itemType){case ItemType.Chopping_tool: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;}break;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.Chopping_tool:crop.ProcessToolAction(equippedItemDetails, isUsingToolRight, isUsingToolLeft, isUsingToolDown, isUsingToolUp);break;case ItemType.Collecting_tool:crop.ProcessToolAction(equippedItemDetails, isPickingRight, isPickingLeft, isPickingDown, isPickingUp);break;}}
}
10、運行游戲2
存在一個問題:就是砍樹的時候,用的不是斧頭,而是鋤頭。這是因為使用了默認的Tool即Hoe。
之前,當玩家攜帶一個道具時,我們為動畫創建了一些腳本對象資產,以便可以在攜帶道具和不攜帶之間切換。
現在,我們需要對use tool動畫做類似的事情,以便在axe和hoe兩個工具之間切換。
11、新建Animation Type
在Assets -> Scriptable Object Assets -> Animation -> Animation Types下新建tool目錄,在其下再創建目錄NoneAxe。
該目錄右擊,Create -> Scriptable Objects -> Animation -> Animation Type,重命名為ToolNoneAxeUseToolDown。
配置ToolNoneAxeUseToolDown的相關信息:
以同樣的方式,分別創建ToolNoneAxeUseToolLeft、ToolNoneAxeUseToolRight、ToolNoneAxeUseToolUp。
比如ToolNoneAxeUseToolRight的參數如下:
在tool目錄下再創建目錄NoneHoe,相應地創建4個AnimationType,比如ToolNoneHoeUseToolDown如下:
在tool目錄下再創建目錄NoneScythe,相應地創建4個AnimationType,比如ToolNoneScytheSwingToolDown如下:
在tool目錄下再創建目錄NoneWateringCan,相應地創建4個AnimationType,比如ToolNoneWateringCanLiftToolUp如下:
新建完畢后,將上面16個添加到Player的CharacterCustomiser下:
添加完畢后,相應的數量從24變為40。
12、運行游戲3
再次砍樹,發現正確使用了斧頭這個工具