Unity:类塔科夫,塔防网格构建
类塔科夫,塔防网格构建
前往我的博客免费查看
这个项目中实现了一个通用背包系统,主要应用于物品管理,可以在多个游戏类型中灵活运用。它的核心功能包含:
- 网格容量系统:类似塔科夫(Tarkov)和生化危机(Resident Evil),通过二维网格管理背包中的物品位置和大小。
实际为三维
- 负重系统:可选加入负重指标,类似绝地求生(PUBG)中的背包容量管理,限制玩家携带物品的总重量。
- 堆叠机制:支持物品堆叠,采用最大堆叠容量和当前容量的逻辑,灵活处理物品的数量管理。
- 预览功能:物品的预览和实际形态分离,允许为同一物品设置不同的模型以提高显示和渲染效率。
- 实例化物品:支持在背包中放置独立的实例化物品,每个物品都有独立的逻辑和行为。
- 通用性和扩展性:系统采用了双层泛型封装,底层框架可以用作塔防、即时战略或模拟经营类游戏的核心物品管理系统。
底层框架构建
底层网格系统构建使用泛型类 GridXY<TGridObject>
,它提供了背包的核心管理功能。以下是该系统的核心实现:
// 泛型,满足扩展需求;
public class GridXY<TGridObject>
{// 定义基本信息大小private int width; private int height; private float cellSize; private Vector3 originPosition; private TGridObject[,] gridArray;// 背包内容管理器,提供物品查询支持private Dictionary<string, int> Bag;public GridXY(******){// 初始化背包}// 提供基础操作public int GetWidth() { return width; } public int GetHeight() { return height; }//.......// 提供底层核心操作// 设置物品public void SetGridObject(int x, int y, TGridObject value) { if (x >= 0 && y >= 0 && x < width && y < height) { gridArray[x, y] = value;}}// 获取物品public TGridObject GetGridObject(int x, int y) { if (x >= 0 && y >= 0 && x < width && y < height) { return gridArray[x, y]; } else { return default(TGridObject); }}// 取出物品public int OutObjectCount(String name, int number) { if (Bag.ContainsKey(name)) { int tem = Bag[name]; if (tem > number) { Bag[name] -= number; return number; } Bag.Remove(name); return tem; } return 0; }// 放入物品public void InObjectCount(String name, int number) { if (Bag.ContainsKey(name)) { Bag[name] += number; Debug.LogWarning(name + "还有" + Bag[name]); return; } Bag.Add(name, number); }}
物品泛型的实现
系统中的物品通过 PlacedObjectTypeSO
实现,允许物品以脚本化对象(ScriptableObject)
的形式进行定义,从而方便管理物品的属性和行为。
public class PlacedObjectTypeSO : ScriptableObject
{public string nameString; // 分别为背包外实例,背包内实例,预览放置实例;// 解决部分模型过于精细或背包过大造成的卡顿;public Transform usePrefab; public Transform prefab; public Transform visual; public int width; public int height; public int number; public int maxNumber; public int ID;//物品的放置位置相关public List<Vector2Int> GetGridPositionList(Vector2Int offset, Dir dir){};public Vector2Int GetRotationOffset(Dir dir){};
}public class PlacedObject_Done : MonoBehaviour
{// 部分信息private Vector2Int origin; private PlacedObjectTypeSO.Dir dir; // 堆叠相关信息private bool canStack; // 疑似冗余信息private int number = 1; private int maxNumber = 1;// 创建物品public static PlacedObject_Done Create(){Transform placedObjectTransform = Instantiate(*****){};PlacedObject_Done placedObject = placedObjectTransform.GetCom<>();// 从SO文件创建placedObject.Setup(placedObjectTypeSO, origin, dir);return placedObject;}// 信息初始化private void Setup(****) { this.placedObjectTypeSO = placedObjectTypeSO; this.origin = origin; this.dir = dir; // 堆叠内容 this.number = placedObjectTypeSO.number; this.maxNumber = placedObjectTypeSO.maxNumber; if (maxNumber != number) { canStack = true; }}// 物品的核心信息// 根据选择判断占地信息;public List<Vector2Int> GetGridPositionList() { return placedObjectTypeSO.GetGridPositionList(origin, dir); }// 物品的特定操作// 堆叠,且尝试返回剩余值public int Stack(int number) { this.number += number; Debug.Log(this.number); if (this.number > maxNumber) { int temp = this.number - maxNumber; this.number = maxNumber; return temp; } return 0; }// 设置数值等public int GetNumber() { return number; } public void SetNumber(int number) { this.number = number; }
}
核心控制层实现
GridSystemXY
负责控制背包网格的运作。它提供了多个核心操作,例如放置物品、堆叠物品等。
public class GridSystemXY : MonoBehaviour
{// 具体放置的类型,如不习惯,可以解耦独立。public class GridObject{private GridXY<GridObject> grid; private int x; private int y; public PlacedObject_Done placedObject; // 物品构建时,物品持有当前所在背包的引用;public GridObject(GridXY<GridObject> grid, int x, int y) { this.grid = grid; this.x = x; this.y = y; placedObject = null; }// 提供配套的操作public void SetPlacedObject(PlacedObject_Done placedObject) { this.placedObject = placedObject; }public bool CanBuild(PlacedObjectTypeSO placedObjectTypeSO){};public bool CanStack(PlacedObjectTypeSO placedObjectTypeSO){};public int Stack(){};}public static GridSystemXY Instance { get; private set; }// 背包管理器,应对多个背包;public Dictionary<int, GridXY<GridSystemXY.GridObject>> gridDictionary;// 当前操作的背包private GridXY<GridObject> grid;// 当前操作的物品private PlacedObjectTypeSO.Dir dir; private PlacedObjectTypeSO placedObjectTypeSO;// 移动位置时的逻辑。 private bool isSwitchingMode = false; private List<Vector2Int> tempGridPositionList = null;// 备份数据 private int number;// 初始化private void Awake() { Instance = this; gridDictionary = new Dictionary<int, GridXY<GridSystemXY.GridObject>>(); int gridWidth = 3; int gridHeight = 4; float cellSize = 10f; AddGrid(1, grid); AddGrid(2, grid); placedObjectTypeSO = null; }// 部分系统// 放置系统private void Build(){foreach(var ID in gridDictionary){//获取鼠标位置,查看是否可以放置}if (canBuild){// 堆叠放置if(canStack){int tem = targetGridObject.Stack(number);if(tem > 0){//未完全放置,仅更新当前数量return;}}// 放置{// 指定位置创建物品placedObject = PlacedObject_Done.Create(****);}// 松开;DeselectObjectType();}}}