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

Unity3D仿星露谷物语开发36之锄地动画2

1、目标

当角色锄地之后,地面会显示开垦后的样貌。

2、思路

上一篇中,虽然角色dig了hoe,同时grid属性也改变了,但是没有任何可视化的反馈。我们现在将添加新的功能,动态地将"dug ground"瓷砖添加到"GroundDecoration1"的tilemap上。

将使用如下的tileset进行绘制。

为了设置正确的dug ground tile,我们需要检查下周边的tiles是否被dug,此时存在16种组合方式。

第1、2种组合方式:

第3、4种组合方式:

第5、6种组合方式:

第7、8种组合方式:

第9、10种组合方式:

第11、12种组合方式:

第13、14种组合方式:

第15、16种组合方式:

连接周边grid的情况:

我们将增加"dug ground" tiles到GroundDecoration1 tilemaps。我们将标记GroundDecoration1和GroundDecoration2 tilemap层,以便可以快速定位到他们,这些标记放到Tag.cs脚本中。

修改GridPropertiesManager.cs脚本如下:

修改Player.cs脚本

3、修改Tag.cs脚本

public static class Tags
{public const string BoundsConfiner = "BoundsConfiner";public const string ItemsParentTransform = "ItemsParentTransform";public const string GroundDecoration1 = "GroundDecoration1";public const string GroundDecoration2 = "GroundDecoration2";
}

添加了下面的2个静态变量。

4、修改GridPropertiesManager.cs脚本

// 修改public为private
private Grid grid;// 添加变量
private Tilemap groundDecoration1;
private Tilemap groundDecoration2;
[SerializeField] private Tile[] dugGround = null;// 添加函数private void ClearDisplayGroundDecorations(){// Remove ground decorationsgroundDecoration1.ClearAllTiles();groundDecoration2.ClearAllTiles();}private void ClearDisplayGridPropertyDetails(){ClearDisplayGroundDecorations();}private void ConnectDugGround(GridPropertyDetails gridPropertyDetails)
{// Select tile based on surrounding dug tilesTile dugTile0 = SetDugTile(gridPropertyDetails.gridX, gridPropertyDetails.gridY);groundDecoration1.SetTile(new Vector3Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY, 0), dugTile0);// Set 4 tiles if dug surrounding current tile - up, down, left, right now that this central tile has been dugGridPropertyDetails adjacentGridPropertyDetails;adjacentGridPropertyDetails = GetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY + 1);if(adjacentGridPropertyDetails != null && adjacentGridPropertyDetails.daysSinceDug > -1){Tile dugTile1 = SetDugTile(gridPropertyDetails.gridX, gridPropertyDetails.gridY + 1);groundDecoration1.SetTile(new Vector3Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY + 1, 0), dugTile1);}adjacentGridPropertyDetails = GetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY - 1);if (adjacentGridPropertyDetails != null && adjacentGridPropertyDetails.daysSinceDug > -1){Tile dugTile2 = SetDugTile(gridPropertyDetails.gridX, gridPropertyDetails.gridY - 1);groundDecoration1.SetTile(new Vector3Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY - 1, 0), dugTile2);}adjacentGridPropertyDetails = GetGridPropertyDetails(gridPropertyDetails.gridX - 1, gridPropertyDetails.gridY);if (adjacentGridPropertyDetails != null && adjacentGridPropertyDetails.daysSinceDug > -1){Tile dugTile3 = SetDugTile(gridPropertyDetails.gridX - 1, gridPropertyDetails.gridY);groundDecoration1.SetTile(new Vector3Int(gridPropertyDetails.gridX - 1, gridPropertyDetails.gridY, 0), dugTile3);}adjacentGridPropertyDetails = GetGridPropertyDetails(gridPropertyDetails.gridX + 1, gridPropertyDetails.gridY);if (adjacentGridPropertyDetails != null && adjacentGridPropertyDetails.daysSinceDug > -1){Tile dugTile4 = SetDugTile(gridPropertyDetails.gridX + 1, gridPropertyDetails.gridY);groundDecoration1.SetTile(new Vector3Int(gridPropertyDetails.gridX + 1, gridPropertyDetails.gridY, 0), dugTile4);}
}private Tile SetDugTile(int xGrid, int yGrid)
{// Get whether surrounding tiles(up,down,left,right) are dug or notbool upDug = IsGridSquareDug(xGrid, yGrid + 1);bool downDug = IsGridSquareDug(xGrid, yGrid - 1);bool leftDug = IsGridSquareDug(xGrid - 1, yGrid);bool rightDug = IsGridSquareDug(xGrid + 1, yGrid);#region Set appropriate tile based on whether surrounding tiles are dug or notif(!upDug && !downDug &&  !rightDug && !leftDug){return dugGround[0];}else if(!upDug && downDug && rightDug && !leftDug){return dugGround[1];}else if(!upDug && downDug && rightDug && leftDug){return dugGround[2];}else if(!upDug && downDug && !rightDug && leftDug){return dugGround[3];}else if(!upDug && downDug && !rightDug && !leftDug){return dugGround[4];}else if(upDug && downDug && rightDug && !leftDug){return dugGround[5];}else if(upDug && downDug && rightDug && leftDug){return dugGround[6];}else if(upDug && downDug && !rightDug && leftDug){return dugGround[7];}else if(upDug && downDug && !rightDug && !leftDug){return dugGround[8];}else if(upDug && !downDug && rightDug && !leftDug){return dugGround[9];}else if(upDug && !downDug && rightDug && leftDug){return dugGround[10];}else if(upDug && !downDug && !rightDug && leftDug){return dugGround[11];}else if(upDug && !downDug && !rightDug && !leftDug){return dugGround[12];}else if(!upDug && !downDug && rightDug && !leftDug){return dugGround[13];}else if(!upDug && !downDug && rightDug && leftDug){return dugGround[14];}else if(!upDug && !downDug && !rightDug && leftDug){return dugGround[15];}return null;#endregion Set appropriate tile based on whether surrounding tiles are dug or not}private bool IsGridSquareDug(int xGrid, int yGrid)
{GridPropertyDetails gridPropertyDetails = GetGridPropertyDetails(xGrid, yGrid);if(gridPropertyDetails == null){return false;}else if(gridPropertyDetails.daysSinceDug > -1){return true;}else{return false;}
}private void DisplayGridPropertyDetails()
{// Loop throught all grid itemsforeach(KeyValuePair<string, GridPropertyDetails> item in gridPropertyDictionary){GridPropertyDetails gridPropertyDetails = item.Value;DisplayDugGround(gridPropertyDetails);}
}// 优化ISaveableRestoreScene函数public void ISaveableRestoreScene(string sceneName){// Get sceneSave for scene - it exists since we created it in initialiseif(GameObjectSave.sceneData.TryGetValue(sceneName, out SceneSave sceneSave)){// get grid property details dictionary - it exists since we created it in initialiseif(sceneSave.gridPropertyDetailsDictionary != null){gridPropertyDictionary = sceneSave.gridPropertyDetailsDictionary;}// If grid properties existif(gridPropertyDictionary.Count > 0){// grid property details found for the current scene destroy existing ground decorationClearDisplayGridPropertyDetails();// Instantiate grid property details for current sceneDisplayGridPropertyDetails();}}}// 优化AfterSceneLoaded函数
private void AfterSceneLoaded()
{// Get Gridgrid = GameObject.FindObjectOfType<Grid>();// Get tilemapsgroundDecoration1 = GameObject.FindGameObjectWithTag(Tags.GroundDecoration1).GetComponent<Tilemap>();groundDecoration2 = GameObject.FindGameObjectWithTag(Tags.GroundDecoration2).GetComponent<Tilemap>();
}

完整的代码如下:

using System.Collections;
using System.Collections.Generic;
using JetBrains.Annotations;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Tilemaps;[RequireComponent(typeof(GenerateGUID))]
public class GridPropertiesManager : SingletonMonobehaviour<GridPropertiesManager>, ISaveable
{private Tilemap groundDecoration1;private Tilemap groundDecoration2;private Grid grid;private Dictionary<string, GridPropertyDetails> gridPropertyDictionary;[SerializeField] private SO_GridProperties[] so_gridPropertiesArray = null;[SerializeField] private Tile[] dugGround = null;private string _iSaveableUniqueID;private GameObjectSave _gameObjectSave;public string ISaveableUniqueID { get { return _iSaveableUniqueID; } set { _iSaveableUniqueID = value; } }public GameObjectSave GameObjectSave { get { return _gameObjectSave; } set { _gameObjectSave = value; } }protected override void Awake(){base.Awake();ISaveableUniqueID = GetComponent<GenerateGUID>().GUID;GameObjectSave = new GameObjectSave();}private void OnEnable(){ISaveableRegister();EventHandler.AfterSceneLoadEvent += AfterSceneLoaded;}private void OnDisable() {ISaveableDeregister();EventHandler.AfterSceneLoadEvent -= AfterSceneLoaded;}private void AfterSceneLoaded(){// Get Gridgrid = GameObject.FindObjectOfType<Grid>();// Get tilemapsgroundDecoration1 = GameObject.FindGameObjectWithTag(Tags.GroundDecoration1).GetComponent<Tilemap>();groundDecoration2 = GameObject.FindGameObjectWithTag(Tags.GroundDecoration2).GetComponent<Tilemap>();}public void ISaveableDeregister(){SaveLoadManager.Instance.iSaveableObjectList.Remove(this);}public void ISaveableRegister(){SaveLoadManager.Instance.iSaveableObjectList.Add(this);}public void ISaveableRestoreScene(string sceneName){// Get sceneSave for scene - it exists since we created it in initialiseif(GameObjectSave.sceneData.TryGetValue(sceneName, out SceneSave sceneSave)){// get grid property details dictionary - it exists since we created it in initialiseif(sceneSave.gridPropertyDetailsDictionary != null){gridPropertyDictionary = sceneSave.gridPropertyDetailsDictionary;}// If grid properties existif(gridPropertyDictionary.Count > 0){// grid property details found for the current scene destroy existing ground decorationClearDisplayGridPropertyDetails();// Instantiate grid property details for current sceneDisplayGridPropertyDetails();}}}public void ISaveableStoreScene(string sceneName){// Remove sceneSave for sceneGameObjectSave.sceneData.Remove(sceneName);// Create sceneSave for sceneSceneSave sceneSave = new SceneSave();// create & add dict grid property details dictionarysceneSave.gridPropertyDetailsDictionary = gridPropertyDictionary;// Add scene save to game object scene dataGameObjectSave.sceneData.Add(sceneName, sceneSave);}private void Start(){InitialiseGridProperties();}private void ClearDisplayGroundDecorations(){// Remove ground decorationsgroundDecoration1.ClearAllTiles();groundDecoration2.ClearAllTiles();}private void ClearDisplayGridPropertyDetails(){ClearDisplayGroundDecorations();}public void DisplayDugGround(GridPropertyDetails gridPropertyDetails){// Dugif(gridPropertyDetails.daysSinceDug > -1){ConnectDugGround(gridPropertyDetails);}}private void ConnectDugGround(GridPropertyDetails gridPropertyDetails){// Select tile based on surrounding dug tilesTile dugTile0 = SetDugTile(gridPropertyDetails.gridX, gridPropertyDetails.gridY);groundDecoration1.SetTile(new Vector3Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY, 0), dugTile0);// Set 4 tiles if dug surrounding current tile - up, down, left, right now that this central tile has been dugGridPropertyDetails adjacentGridPropertyDetails;adjacentGridPropertyDetails = GetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY + 1);if(adjacentGridPropertyDetails != null && adjacentGridPropertyDetails.daysSinceDug > -1){Tile dugTile1 = SetDugTile(gridPropertyDetails.gridX, gridPropertyDetails.gridY + 1);groundDecoration1.SetTile(new Vector3Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY + 1, 0), dugTile1);}adjacentGridPropertyDetails = GetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY - 1);if (adjacentGridPropertyDetails != null && adjacentGridPropertyDetails.daysSinceDug > -1){Tile dugTile2 = SetDugTile(gridPropertyDetails.gridX, gridPropertyDetails.gridY - 1);groundDecoration1.SetTile(new Vector3Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY - 1, 0), dugTile2);}adjacentGridPropertyDetails = GetGridPropertyDetails(gridPropertyDetails.gridX - 1, gridPropertyDetails.gridY);if (adjacentGridPropertyDetails != null && adjacentGridPropertyDetails.daysSinceDug > -1){Tile dugTile3 = SetDugTile(gridPropertyDetails.gridX - 1, gridPropertyDetails.gridY);groundDecoration1.SetTile(new Vector3Int(gridPropertyDetails.gridX - 1, gridPropertyDetails.gridY, 0), dugTile3);}adjacentGridPropertyDetails = GetGridPropertyDetails(gridPropertyDetails.gridX + 1, gridPropertyDetails.gridY);if (adjacentGridPropertyDetails != null && adjacentGridPropertyDetails.daysSinceDug > -1){Tile dugTile4 = SetDugTile(gridPropertyDetails.gridX + 1, gridPropertyDetails.gridY);groundDecoration1.SetTile(new Vector3Int(gridPropertyDetails.gridX + 1, gridPropertyDetails.gridY, 0), dugTile4);}}private Tile SetDugTile(int xGrid, int yGrid){// Get whether surrounding tiles(up,down,left,right) are dug or notbool upDug = IsGridSquareDug(xGrid, yGrid + 1);bool downDug = IsGridSquareDug(xGrid, yGrid - 1);bool leftDug = IsGridSquareDug(xGrid - 1, yGrid);bool rightDug = IsGridSquareDug(xGrid + 1, yGrid);#region Set appropriate tile based on whether surrounding tiles are dug or notif(!upDug && !downDug &&  !rightDug && !leftDug){return dugGround[0];}else if(!upDug && downDug && rightDug && !leftDug){return dugGround[1];}else if(!upDug && downDug && rightDug && leftDug){return dugGround[2];}else if(!upDug && downDug && !rightDug && leftDug){return dugGround[3];}else if(!upDug && downDug && !rightDug && !leftDug){return dugGround[4];}else if(upDug && downDug && rightDug && !leftDug){return dugGround[5];}else if(upDug && downDug && rightDug && leftDug){return dugGround[6];}else if(upDug && downDug && !rightDug && leftDug){return dugGround[7];}else if(upDug && downDug && !rightDug && !leftDug){return dugGround[8];}else if(upDug && !downDug && rightDug && !leftDug){return dugGround[9];}else if(upDug && !downDug && rightDug && leftDug){return dugGround[10];}else if(upDug && !downDug && !rightDug && leftDug){return dugGround[11];}else if(upDug && !downDug && !rightDug && !leftDug){return dugGround[12];}else if(!upDug && !downDug && rightDug && !leftDug){return dugGround[13];}else if(!upDug && !downDug && rightDug && leftDug){return dugGround[14];}else if(!upDug && !downDug && !rightDug && leftDug){return dugGround[15];}return null;#endregion Set appropriate tile based on whether surrounding tiles are dug or not}private bool IsGridSquareDug(int xGrid, int yGrid){GridPropertyDetails gridPropertyDetails = GetGridPropertyDetails(xGrid, yGrid);if(gridPropertyDetails == null){return false;}else if(gridPropertyDetails.daysSinceDug > -1){return true;}else{return false;}}private void DisplayGridPropertyDetails(){// Loop throught all grid itemsforeach(KeyValuePair<string, GridPropertyDetails> item in gridPropertyDictionary){GridPropertyDetails gridPropertyDetails = item.Value;DisplayDugGround(gridPropertyDetails);}}/// <summary>/// This initialises the grid property dictionary with the values from the SO_GridProperties assets and stores the values for each scene in/// GameObjectSave sceneData/// </summary>private void InitialiseGridProperties(){// loop through all gridproperties in the arrayforeach(SO_GridProperties so_GridProperties in so_gridPropertiesArray){// Create dictionary of grid property detailsDictionary<string, GridPropertyDetails> gridPropertyDictionary = new Dictionary<string, GridPropertyDetails>();// Populate grid property dictionary - Iterate through all the grid properties in the so gridproperties listforeach(GridProperty gridProperty in so_GridProperties.gridPropertyList){GridPropertyDetails gridPropertyDetails;gridPropertyDetails = GetGridPropertyDetails(gridProperty.gridCoordinate.x, gridProperty.gridCoordinate.y, gridPropertyDictionary);if(gridPropertyDetails == null){gridPropertyDetails = new GridPropertyDetails();}switch (gridProperty.gridBoolProperty){case GridBoolProperty.diggable:gridPropertyDetails.isDiggable = gridProperty.gridBoolValue;break;case GridBoolProperty.canDropItem:gridPropertyDetails.canDropItem = gridProperty.gridBoolValue;break;case GridBoolProperty.canPlaceFurniture:gridPropertyDetails.canPlaceFurniture = gridProperty.gridBoolValue;break;case GridBoolProperty.isPath:gridPropertyDetails.isPath = gridProperty.gridBoolValue;break;case GridBoolProperty.isNPCObstacle:gridPropertyDetails.isNPCObstacle = gridProperty.gridBoolValue;break;default:break; }SetGridPropertyDetails(gridProperty.gridCoordinate.x, gridProperty.gridCoordinate.y, gridPropertyDetails, gridPropertyDictionary);}// Create scene save for this gameobjectSceneSave sceneSave = new SceneSave();// Add grid property dictionary to scene save datasceneSave.gridPropertyDetailsDictionary = gridPropertyDictionary;// If starting scene set the griProertyDictionary member variable to the current iterationif(so_GridProperties.sceneName.ToString() == SceneControllerManager.Instance.startingSceneName.ToString()){this.gridPropertyDictionary = gridPropertyDictionary;}// Add scene save to game object scene dataGameObjectSave.sceneData.Add(so_GridProperties.sceneName.ToString(), sceneSave);}}/// <summary>/// Returns the gridPropertyDetails at the gridlocation fro the supplied dictionary,/// or null if no properties exist at that location/// </summary>/// <param name="gridX"></param>/// <param name="gridY"></param>/// <param name="gridPropertyDictionary"></param>/// <returns></returns>public GridPropertyDetails GetGridPropertyDetails(int gridX, int gridY, Dictionary<string, GridPropertyDetails> gridPropertyDictionary){// Construct key from coordinatestring key = "x" + gridX + "y" + gridY;GridPropertyDetails gridPropertyDetails;// Check if grid property details exist for coordinate and retrieveif (!gridPropertyDictionary.TryGetValue(key, out gridPropertyDetails)){// if not foundreturn null;}else{return gridPropertyDetails;}}public GridPropertyDetails GetGridPropertyDetails(int gridX, int gridY){return GetGridPropertyDetails(gridX, gridY, gridPropertyDictionary);}/// <summary>/// Set the grid property details to gridPropertyDetails fro the tile at (gridX, gridY) for current scene/// </summary>/// <param name="gridX"></param>/// <param name="gridY"></param>/// <param name="gridPropertyDetails"></param>public void SetGridPropertyDetails(int gridX, int gridY, GridPropertyDetails gridPropertyDetails){SetGridPropertyDetails(gridX, gridY, gridPropertyDetails, gridPropertyDictionary);}/// <summary>/// Set the grid property details to gridPropertyDetails for the title at (gridX, gridY) for the gridPropertyDictionary./// </summary>/// <param name="gridX"></param>/// <param name="gridY"></param>/// <param name="gridPropertyDetails"></param>/// <param name="gridPropertyDictionary"></param>public void SetGridPropertyDetails(int gridX, int gridY, GridPropertyDetails gridPropertyDetails, Dictionary<string, GridPropertyDetails> gridPropertyDictionary){// Construct key from coordinatestring key = "x" + gridX + "y" + gridY;gridPropertyDetails.gridX = gridX;gridPropertyDetails.gridY = gridY;// Set value gridPropertyDictionary[key] = gridPropertyDetails;}}

5、修改Player.cs脚本

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

6、设置绘图

(1)创建新的Palette

Create New Palette,并且命名为DugGround,保存到Assets -> Tilemap -> Tile Palettes下。

(2)创建新的Tiles

在Assets -> Sprites -> Sprite Textures -> Tile Sprites 下找到DugGround.

将DugGround拖到右边的Palette中,弹出的目录选择Assets -> Tilemap -> Tiles,创建新的目录Dug Ground,保存到该目录下。

左边灰色为Dug后的grid图案,右边银色为Water之后的grid图案。

7、配置Tile信息

点击Assets -> Tilemap -> Tiles -> Dug Ground,然后点击Open。

点击PersistentScene -> GridPropertiesManager,将Dug Ground中灰色的图片拖入到Dug Ground的List中。

8、添加Tag

点击GridPropertiesManager,点击Add Tag。

添加GroundDecoration1和GroundDecoration2两个Tag。

然后依次给Scene1/Scene2/Scene3场景Tilemap Grid下的GroundDecoration1和GroundDecoration2对象设置GroundDecoration1和GroundDecoration2两个Tag。

设置Prefabs -> Maps -> Tilemap Grid下的GroundDecoration1和GroundDecoration2对象设置GroundDecoration1和GroundDecoration2两个Tag。

9、运行游戏

相关文章:

  • 【C++】类和对象之日期类的实现(构造、运算符重载)
  • 机器学习中的“三态模型“:过拟合、欠拟合和刚刚好
  • 在FVM(有限体积法)的CFD仿真中,AI和机器学习的应用
  • 关于进程状态
  • 计算机组成原理笔记(十七)——4.2定点加减运算
  • docker配置skywalking 监控springcloud应用
  • Laravel-vite+vue开发前端模板
  • MIT6.S081-lab4
  • 如何在 Ubuntu 上安装 Apache CouchDB ?
  • 【数据结构和算法】1. 数据结构和算法简介、二分搜索
  • Apache Parquet 文件组织结构
  • MACOS 中聚焦使用技巧
  • 医药采购系统平台第10天02:按药品分类的统计按供货商统计按医院统计统计数据的导出DWR的配置和应用
  • 通过 WebSocket 接收和播放 WSS 协议视频流
  • AES (高级加密标准)
  • 大模型在胆管结石(无胆管炎或胆囊炎)预测及治疗方案制定中的应用研究
  • OpenCV 边缘检测(Edge Detection)cv2.Canny
  • Spring源码中关于抽象方法且是个空实现这样设计的思考
  • 剑指Offer(数据结构与算法面试题精讲)C++版——day16
  • OpenCSG AutoHub v0.5.0 版本发布
  • 成功卫冕!孙颖莎4比0战胜蒯曼,获澳门世界杯女单冠军
  • 山西一国道发生塌陷,造成4车追尾2人死亡
  • 明查|俄罗斯征兵部门突袭澡堂抓捕壮丁?
  • 四川省委统战部副部长(正厅级)张荣履新峨眉电影集团“一把手”
  • 为博眼球竟编造一女孩被活埋,公安机关公布10起谣言案件
  • 巡视杭州市工作动员会召开,市长姚高员表态