备份CatanBuilding瘦身独立工程

This commit is contained in:
JSD\13999
2026-05-26 16:15:54 +08:00
commit 2d0e6a61b7
12001 changed files with 2431925 additions and 0 deletions

View File

@@ -0,0 +1,465 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using cfg;
using Newtonsoft.Json;
using SimpleJSON;
using UnityEditor;
#endif
using UnityEngine;
using Random = System.Random;
namespace Script.EditorScript
{
[ExecuteInEditMode]
public class RandomPropsTemp : MonoBehaviour
{
#if UNITY_EDITOR
[Tooltip("棋子容器")]
public GameObject CubeContainer;
[Tooltip("最终导出的模板数量")]
public int TempCount = 20;
[Tooltip("模板生成上线")]
public int TempMaxCount = 10000;
public InspectorEntry[] RandomPropsList;
[NonSerialized]
public List<List<PropTemp>> ResultTemps = new List<List<PropTemp>>();
/// <summary>
/// 索引 为key,用来支持 随机道具 配置都是一样的道具
/// </summary>
private Dictionary<int, List<PropTemp>> _allPropCanPutDic = new Dictionary<int, List<PropTemp>>();
private CubeScript[] _allCube;
private Tables _tables;
private Tables GetTable()
{
if (_tables == null)
{
_tables = new Tables((string fileName) =>
{
return JSON.Parse(
File.ReadAllText(Application.dataPath + "/ABPackage/pkgFirstPackage/Data/" + fileName + ".json"));
});
}
return _tables;
}
public void ApplyId()
{
for (int i = 0; i < RandomPropsList.Length; i++)
{
if (RandomPropsList[i].PropId <= 0)
{
Debug.LogError("随机道具id==0请检查配置");
continue;
}
if (!GetTable().TbDiggingItemList.DataMap.TryGetValue(RandomPropsList[i].PropId, out DiggingItemList info))
{
Debug.LogError("随机模板 道具id配置错误 请检查!!! 错误id:" + RandomPropsList[i].PropId);
continue;
}
string templateName = GetTable().TbDiggingItemList.Get(RandomPropsList[i].PropId).GridTemplate;
string templateUrl = $"Assets/AssetsPackage/art/DgSand/Scriptable/CubeConfig/{templateName}.asset";
CubeConfigData asset = AssetDatabase.LoadAssetAtPath<CubeConfigData>(templateUrl);
if (asset == null)
{
Debug.LogError("资源id 的模板 没找到,请检查配置!!" + RandomPropsList[i].PropId);
return;
}
RandomPropsList[i].resource = asset;
}
Debug.LogError("随机道具id 已经启用");
}
public void GenerateTempData()
{
ResultTemps.Clear();
_allPropCanPutDic.Clear();
_allCube = CubeContainer.GetComponentsInChildren<CubeScript>();
List<CubeScript> allValidCubes = FindAllValidCubes();
Debug.LogWarning("空格子数量:" + allValidCubes.Count);
//分别存储每种道具 所有的摆放位置
CountPlacements(allValidCubes, RandomPropsList, 0);
//计算出所有道具同时可以存在的组合
List<List<PropTemp>> allValidCombination = CalculateAllPlacements();
Debug.LogWarning("有效组合的总个数:" + allValidCombination.Count);
if (allValidCombination.Count == 0)
{
EditorUtility.DisplayDialog("有效组合的总个数为 0", "请扩大Temp最大数量重新执行", "确定");
}
foreach (var validCombination in allValidCombination)
{
Debug.LogWarning("Valid Combination:");
foreach (var propTemp in validCombination)
{
Debug.LogWarning($"PropId: {propTemp.PropId}, angle: {propTemp.ConfigData.PropDirection},Position: ({propTemp.x}, {propTemp.y})");
}
}
// 最终随机出 最多TempCount 个模板进行存储
if (allValidCombination.Count < TempCount)
{
ResultTemps = allValidCombination;
}
else
{
ResultTemps = GetRandomSelection(allValidCombination, TempCount);
}
}
private List<T> GetRandomSelection<T>(List<T> list, int count)
{
Random random = new Random();
return list.OrderBy(x => random.Next()).Take(count).ToList();
}
/// <summary>
/// 计算每种道具 所有能摆放的位置
/// </summary>
/// <param name="validCubes"></param>
/// <param name="props"></param>
/// <param name="propIndex"></param>
private void CountPlacements(List<CubeScript> validCubes, InspectorEntry[] props, int propIndex)
{
if (propIndex >= props.Length)
{
Debug.LogWarning("所有道具位置处理完毕");
return;
}
List<PropTemp> tempFlagList = new List<PropTemp>();
InspectorEntry prop = props[propIndex];
foreach (var rotatedProp in GetRotations(prop.resource))
{
for (int i = 0; i < validCubes.Count; i++)
{
List<CubeScript> useCube = CheckPropNeedGridData(rotatedProp, validCubes[i].gameObject);
if (useCube == null)
{
continue;
}
bool canPut = GetPropIfCanPut(validCubes, useCube);
if (canPut)
{
PropTemp temp = new PropTemp();
temp.x = (int)validCubes[i].gameObject.transform.localPosition.x;
temp.y = (int)validCubes[i].gameObject.transform.localPosition.y;
temp.PropId = prop.PropId;
temp.ConfigData = rotatedProp.Copy();
temp.SetEmployCube(useCube);
tempFlagList.Add(temp);
Debug.Log("propId::" + prop.PropId + " angle::" + temp.ConfigData.PropDirection + " x::" + temp.x + " y::" + temp.y);
}
}
}
_allPropCanPutDic[propIndex] = tempFlagList;
Debug.LogWarning("所有数据propId" + prop.PropId + " 模板数量::" + _allPropCanPutDic[propIndex].Count);
CountPlacements(validCubes, props, ++propIndex);
}
#region
private List<List<PropTemp>> CalculateAllPlacements()
{
List<List<PropTemp>> allCombinations = new List<List<PropTemp>>();
GenerateCombinations(_allPropCanPutDic, new List<PropTemp>(), allCombinations, 0);
List<List<PropTemp>> validCombinations = new List<List<PropTemp>>();
foreach (var combination in allCombinations)
{
if (IsValidCombination(combination))
{
validCombinations.Add(combination);
}
}
return validCombinations;
}
private void GenerateCombinations(Dictionary<int, List<PropTemp>> allPropCanPutDic, List<PropTemp> currentCombination, List<List<PropTemp>> allCombinations, int currentIndex)
{
if (allCombinations.Count >= TempMaxCount)
{
Debug.LogError("到达模板数量上线,开始检查模板合法性");
return;
}
if (currentIndex >= allPropCanPutDic.Count)
{
allCombinations.Add(new List<PropTemp>(currentCombination));
return;
}
//int propId = allPropCanPutDic.Keys.ElementAt(currentIndex);
foreach (var propTemp in allPropCanPutDic[currentIndex])
{
if (allCombinations.Count >= TempMaxCount)
{
Debug.Log($"到达模板数量上线 {allCombinations.Count},开始检查模板合法性");
return;
}
currentCombination.Add(propTemp);
GenerateCombinations(allPropCanPutDic, currentCombination, allCombinations, currentIndex + 1);
currentCombination.RemoveAt(currentCombination.Count - 1);
}
}
/// <summary>
/// 是否是 有效的组合
/// </summary>
/// <param name="currentCombination"></param>
/// <returns></returns>
private bool IsValidCombination(List<PropTemp> currentCombination)
{
Dictionary<int, bool> dic = new Dictionary<int, bool>();
for (int i = 0; i < currentCombination.Count; i++)
{
List<CubeScript> cubes = currentCombination[i].GetEmployCubes();
foreach (var cube in cubes)
{
if (dic.TryGetValue(cube.GetInstanceID(), out bool value))
{
return false;
}
else
{
dic.Add(cube.GetInstanceID(), true);
}
}
}
return true;
}
#endregion
#region
private IEnumerable<CubeConfigData> GetRotations(CubeConfigData prop)
{
yield return GetDataByRotate(prop, 0);
yield return GetDataByRotate(prop, 90);
yield return GetDataByRotate(prop, 180);
yield return GetDataByRotate(prop, 270);
}
private CubeConfigData GetDataByRotate(CubeConfigData prop, int angle)
{
prop.PropDirection = angle;
return prop;
}
/// <summary>
/// 检查是否能放下道具
/// </summary>
/// <param name="validCubes"></param>
/// <param name="useCube"></param>
/// <returns></returns>
private bool GetPropIfCanPut(List<CubeScript> validCubes, List<CubeScript> useCube)
{
for (int i = 0; i < useCube.Count; i++)
{
bool isOk = false;
for (int j = 0; j < validCubes.Count; j++)
{
if (validCubes[j] == useCube[i])
{
isOk = true;
break;
}
}
if (!isOk)
{
return false;
}
}
return true;
}
/// <summary>
/// 找到所有没有被道具占据的空Cube
/// </summary>
/// <returns></returns>
public List<CubeScript> FindAllValidCubes()
{
List<CubeScript> allInvalidCube = new List<CubeScript>();
for (int i = 0; i < _allCube.Length; i++)
{
if (!_allCube[i].IsBorder && _allCube[i].ConfigData != null && _allCube[i].PropId > 0)
{
CubeConfigData gridData = _allCube[i].ConfigData;
//格子下道具绑定格子
List<CubeScript> cubes = CheckPropNeedGridData(gridData, _allCube[i].gameObject);
if (cubes != null)
{
allInvalidCube = allInvalidCube.Concat(cubes).ToList();
}
else
{
Debug.LogWarning("找到配置的道具 放在空格子上,检查配置");
}
}
}
//找到所有没有被道具占据的空Cube
List<CubeScript> allvalidCube = new List<CubeScript>();
bool finded = false;
for (int i = 0; i < _allCube.Length; i++)
{
CubeScript cur = _allCube[i];
finded = false;
if (!_allCube[i].IsBorder)
{
for (int j = 0; j < allInvalidCube.Count; j++)
{
if (cur == allInvalidCube[j])
{
finded = true;
}
}
if (!finded)
{
allvalidCube.Add(cur);
}
}
}
return allvalidCube;
}
/// <summary>
/// 格子下道具绑定格子
/// </summary>
public List<CubeScript> CheckPropNeedGridData(CubeConfigData data, GameObject startObj)
{
int rows = data.GetArray().GetLength(0);
int cols = data.GetArray().GetLength(1);
List<CubeScript> cubes = new List<CubeScript>();
// 起始
Vector3 startPoint = startObj.transform.localPosition;
int allCount = 0;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
int value = data.GetArray()[i, j];
if (value > 0)
{
allCount++;
// 初始位置
Vector3 positionB = new Vector3(j, i, 0); //空间转换
Vector3 endPosition = startPoint + GetRotatePoint(data.PropDirection, Vector3.zero, positionB);
// Debug.LogWarning($"获取Grid{endPosition.x}" + " col::" + endPosition.y);
CubeScript grid = GetGridItemByRowAndCol((int)Mathf.Round(endPosition.x), (int)Mathf.Round(endPosition.y));
if (grid != null)
{
cubes.Add(grid);
}
}
}
}
if (cubes.Count == allCount)
{
return cubes;
}
else
{
return null;
}
}
public CubeScript GetGridItemByRowAndCol(int row, int col)
{
for (int i = 0; i < _allCube.Length; i++)
{
if (_allCube[i].transform.localPosition.x == row && _allCube[i].transform.localPosition.y == col)
{
return _allCube[i];
}
}
return null;
}
/// <summary>
/// 获取旋转后道具的位置
/// </summary>
/// <param name="angles"></param>
/// <param name="positionA"></param>
/// <param name="positionB"></param>
/// <returns></returns>
private Vector3 GetRotatePoint(int angles, Vector3 positionA, Vector3 positionB)
{
return RotatePointAroundPivot(positionB, positionA, new Vector3(0, 0, -angles));
}
private Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Vector3 angles)
{
Vector3 dir = point - pivot; // 获取点到枢轴的向量
dir = Quaternion.Euler(angles) * dir; // 旋转向量
point = dir + pivot; // 将点移动回枢轴
return point;
}
#endregion
#endif
}
public class PropTemp
{
#if UNITY_EDITOR
public int x;
public int y;
public int PropId;
public CubeConfigData ConfigData;
//使用的格子
private List<CubeScript> _EmployCubes = new List<CubeScript>();
public List<CubeScript> GetEmployCubes()
{
return _EmployCubes;
}
public void AddEmployCube(CubeScript value)
{
_EmployCubes.Add(value);
}
public void SetEmployCube(List<CubeScript> value)
{
_EmployCubes = value;
}
public string ToJson()
{
var settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
return JsonConvert.SerializeObject(new { x = x, y = y, PropId = PropId, ConfigData = ConfigData }, settings);
}
#endif
}
}