fix:1、多语言优化。2、添加死局检查脚本
This commit is contained in:
Binary file not shown.
+79
-79
@@ -195,9 +195,9 @@ public class WebViewObject : MonoBehaviour
|
|||||||
case "SetKeyboardVisible":
|
case "SetKeyboardVisible":
|
||||||
SetKeyboardVisible(s.Substring(i + 1));
|
SetKeyboardVisible(s.Substring(i + 1));
|
||||||
break;
|
break;
|
||||||
case "RequestFileChooserPermissions":
|
// case "RequestFileChooserPermissions":
|
||||||
RequestFileChooserPermissions();
|
// // RequestFileChooserPermissions();
|
||||||
break;
|
// break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,82 +219,82 @@ public class WebViewObject : MonoBehaviour
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Called from Java native plugin to request permissions for the file chooser.
|
/// Called from Java native plugin to request permissions for the file chooser.
|
||||||
public void RequestFileChooserPermissions()
|
// public void RequestFileChooserPermissions()
|
||||||
{
|
// {
|
||||||
var permissions = new List<string>();
|
// var permissions = new List<string>();
|
||||||
using (var version = new AndroidJavaClass("android.os.Build$VERSION"))
|
// using (var version = new AndroidJavaClass("android.os.Build$VERSION"))
|
||||||
{
|
// {
|
||||||
if (version.GetStatic<int>("SDK_INT") >= 33)
|
// if (version.GetStatic<int>("SDK_INT") >= 33)
|
||||||
{
|
// {
|
||||||
if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_IMAGES"))
|
// if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_IMAGES"))
|
||||||
{
|
// {
|
||||||
permissions.Add("android.permission.READ_MEDIA_IMAGES");
|
// permissions.Add("android.permission.READ_MEDIA_IMAGES");
|
||||||
}
|
// }
|
||||||
if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_VIDEO"))
|
// if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_VIDEO"))
|
||||||
{
|
// {
|
||||||
permissions.Add("android.permission.READ_MEDIA_VIDEO");
|
// permissions.Add("android.permission.READ_MEDIA_VIDEO");
|
||||||
}
|
// }
|
||||||
if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_AUDIO"))
|
// if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_AUDIO"))
|
||||||
{
|
// {
|
||||||
permissions.Add("android.permission.READ_MEDIA_AUDIO");
|
// permissions.Add("android.permission.READ_MEDIA_AUDIO");
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageRead))
|
// if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageRead))
|
||||||
{
|
// {
|
||||||
permissions.Add(Permission.ExternalStorageRead);
|
// permissions.Add(Permission.ExternalStorageRead);
|
||||||
}
|
// }
|
||||||
if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite))
|
// if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite))
|
||||||
{
|
// {
|
||||||
permissions.Add(Permission.ExternalStorageWrite);
|
// permissions.Add(Permission.ExternalStorageWrite);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (!Permission.HasUserAuthorizedPermission(Permission.Camera))
|
// if (!Permission.HasUserAuthorizedPermission(Permission.Camera))
|
||||||
{
|
// {
|
||||||
permissions.Add(Permission.Camera);
|
// permissions.Add(Permission.Camera);
|
||||||
}
|
// }
|
||||||
if (permissions.Count > 0)
|
// if (permissions.Count > 0)
|
||||||
{
|
// {
|
||||||
#if UNITY_2020_2_OR_NEWER
|
// #if UNITY_2020_2_OR_NEWER
|
||||||
var grantedCount = 0;
|
// var grantedCount = 0;
|
||||||
var deniedCount = 0;
|
// var deniedCount = 0;
|
||||||
var callbacks = new PermissionCallbacks();
|
// var callbacks = new PermissionCallbacks();
|
||||||
callbacks.PermissionGranted += (permission) =>
|
// callbacks.PermissionGranted += (permission) =>
|
||||||
{
|
// {
|
||||||
grantedCount++;
|
// grantedCount++;
|
||||||
if (grantedCount + deniedCount == permissions.Count)
|
// if (grantedCount + deniedCount == permissions.Count)
|
||||||
{
|
// {
|
||||||
StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count));
|
// StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count));
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
callbacks.PermissionDenied += (permission) =>
|
// callbacks.PermissionDenied += (permission) =>
|
||||||
{
|
// {
|
||||||
deniedCount++;
|
// deniedCount++;
|
||||||
if (grantedCount + deniedCount == permissions.Count)
|
// if (grantedCount + deniedCount == permissions.Count)
|
||||||
{
|
// {
|
||||||
StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count));
|
// StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count));
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
callbacks.PermissionDeniedAndDontAskAgain += (permission) =>
|
// callbacks.PermissionDeniedAndDontAskAgain += (permission) =>
|
||||||
{
|
// {
|
||||||
deniedCount++;
|
// deniedCount++;
|
||||||
if (grantedCount + deniedCount == permissions.Count)
|
// if (grantedCount + deniedCount == permissions.Count)
|
||||||
{
|
// {
|
||||||
StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count));
|
// StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count));
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
Permission.RequestUserPermissions(permissions.ToArray(), callbacks);
|
// Permission.RequestUserPermissions(permissions.ToArray(), callbacks);
|
||||||
#else
|
// #else
|
||||||
StartCoroutine(RequestFileChooserPermissionsCoroutine(permissions.ToArray()));
|
// StartCoroutine(RequestFileChooserPermissionsCoroutine(permissions.ToArray()));
|
||||||
#endif
|
// #endif
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
StartCoroutine(CallOnRequestFileChooserPermissionsResult(true));
|
// StartCoroutine(CallOnRequestFileChooserPermissionsResult(true));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#if UNITY_2020_2_OR_NEWER
|
#if UNITY_2020_2_OR_NEWER
|
||||||
#else
|
#else
|
||||||
|
|||||||
+87
-87
@@ -214,9 +214,9 @@ namespace Gree.UnityWebView
|
|||||||
case "SetKeyboardVisible":
|
case "SetKeyboardVisible":
|
||||||
SetKeyboardVisible(s.Substring(i + 1));
|
SetKeyboardVisible(s.Substring(i + 1));
|
||||||
break;
|
break;
|
||||||
case "RequestFileChooserPermissions":
|
// case "RequestFileChooserPermissions":
|
||||||
RequestFileChooserPermissions();
|
// RequestFileChooserPermissions();
|
||||||
break;
|
// break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,90 +239,90 @@ namespace Gree.UnityWebView
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Called from Java native plugin to request permissions for the file chooser.
|
/// Called from Java native plugin to request permissions for the file chooser.
|
||||||
public void RequestFileChooserPermissions()
|
// public void RequestFileChooserPermissions()
|
||||||
{
|
// {
|
||||||
var permissions = new List<string>();
|
// var permissions = new List<string>();
|
||||||
using (var version = new AndroidJavaClass("android.os.Build$VERSION"))
|
// using (var version = new AndroidJavaClass("android.os.Build$VERSION"))
|
||||||
{
|
// {
|
||||||
if (version.GetStatic<int>("SDK_INT") >= 33)
|
// if (version.GetStatic<int>("SDK_INT") >= 33)
|
||||||
{
|
// {
|
||||||
if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_IMAGES"))
|
// if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_IMAGES"))
|
||||||
{
|
// {
|
||||||
permissions.Add("android.permission.READ_MEDIA_IMAGES");
|
// permissions.Add("android.permission.READ_MEDIA_IMAGES");
|
||||||
}
|
// }
|
||||||
if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_VIDEO"))
|
// if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_VIDEO"))
|
||||||
{
|
// {
|
||||||
permissions.Add("android.permission.READ_MEDIA_VIDEO");
|
// permissions.Add("android.permission.READ_MEDIA_VIDEO");
|
||||||
}
|
// }
|
||||||
if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_AUDIO"))
|
// if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_AUDIO"))
|
||||||
{
|
// {
|
||||||
permissions.Add("android.permission.READ_MEDIA_AUDIO");
|
// permissions.Add("android.permission.READ_MEDIA_AUDIO");
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageRead))
|
// if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageRead))
|
||||||
{
|
// {
|
||||||
permissions.Add(Permission.ExternalStorageRead);
|
// permissions.Add(Permission.ExternalStorageRead);
|
||||||
}
|
// }
|
||||||
if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite))
|
// if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite))
|
||||||
{
|
// {
|
||||||
permissions.Add(Permission.ExternalStorageWrite);
|
// permissions.Add(Permission.ExternalStorageWrite);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
#if UNITYWEBVIEW_ANDROID_ENABLE_CAMERA
|
// #if UNITYWEBVIEW_ANDROID_ENABLE_CAMERA
|
||||||
if (!Permission.HasUserAuthorizedPermission(Permission.Camera) && mAllowVideoCapture)
|
// if (!Permission.HasUserAuthorizedPermission(Permission.Camera) && mAllowVideoCapture)
|
||||||
{
|
// {
|
||||||
permissions.Add(Permission.Camera);
|
// permissions.Add(Permission.Camera);
|
||||||
}
|
// }
|
||||||
#endif
|
// #endif
|
||||||
#if UNITYWEBVIEW_ANDROID_ENABLE_MICROPHONE
|
// #if UNITYWEBVIEW_ANDROID_ENABLE_MICROPHONE
|
||||||
if (!Permission.HasUserAuthorizedPermission(Permission.Microphone) && mAllowAudioCapture)
|
// if (!Permission.HasUserAuthorizedPermission(Permission.Microphone) && mAllowAudioCapture)
|
||||||
{
|
// {
|
||||||
permissions.Add(Permission.Microphone);
|
// permissions.Add(Permission.Microphone);
|
||||||
}
|
// }
|
||||||
#endif
|
// #endif
|
||||||
if (permissions.Count > 0)
|
// if (permissions.Count > 0)
|
||||||
{
|
// {
|
||||||
#if UNITY_2020_2_OR_NEWER
|
// #if UNITY_2020_2_OR_NEWER
|
||||||
var grantedCount = 0;
|
// var grantedCount = 0;
|
||||||
var deniedCount = 0;
|
// var deniedCount = 0;
|
||||||
var callbacks = new PermissionCallbacks();
|
// var callbacks = new PermissionCallbacks();
|
||||||
callbacks.PermissionGranted += (permission) =>
|
// callbacks.PermissionGranted += (permission) =>
|
||||||
{
|
// {
|
||||||
grantedCount++;
|
// grantedCount++;
|
||||||
if (grantedCount + deniedCount == permissions.Count)
|
// if (grantedCount + deniedCount == permissions.Count)
|
||||||
{
|
// {
|
||||||
StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count));
|
// StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count));
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
callbacks.PermissionDenied += (permission) =>
|
// callbacks.PermissionDenied += (permission) =>
|
||||||
{
|
// {
|
||||||
deniedCount++;
|
// deniedCount++;
|
||||||
if (grantedCount + deniedCount == permissions.Count)
|
// if (grantedCount + deniedCount == permissions.Count)
|
||||||
{
|
// {
|
||||||
StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count));
|
// StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count));
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
callbacks.PermissionDeniedAndDontAskAgain += (permission) =>
|
// callbacks.PermissionDeniedAndDontAskAgain += (permission) =>
|
||||||
{
|
// {
|
||||||
deniedCount++;
|
// deniedCount++;
|
||||||
if (grantedCount + deniedCount == permissions.Count)
|
// if (grantedCount + deniedCount == permissions.Count)
|
||||||
{
|
// {
|
||||||
StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count));
|
// StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count));
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
Permission.RequestUserPermissions(permissions.ToArray(), callbacks);
|
// Permission.RequestUserPermissions(permissions.ToArray(), callbacks);
|
||||||
#else
|
// #else
|
||||||
StartCoroutine(RequestFileChooserPermissionsCoroutine(permissions.ToArray()));
|
// StartCoroutine(RequestFileChooserPermissionsCoroutine(permissions.ToArray()));
|
||||||
#endif
|
// #endif
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
StartCoroutine(CallOnRequestFileChooserPermissionsResult(true));
|
// StartCoroutine(CallOnRequestFileChooserPermissionsResult(true));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#if UNITY_2020_2_OR_NEWER
|
#if UNITY_2020_2_OR_NEWER
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -0,0 +1,507 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using ChillConnect;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 关卡死局检测工具(Unity编辑器下使用)
|
||||||
|
/// </summary>
|
||||||
|
public class ArrowGameValidator
|
||||||
|
{
|
||||||
|
// ========== 方向转换工具 ==========
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 方向字符串转行列偏移量
|
||||||
|
/// </summary>
|
||||||
|
private static (int dRow, int dCol) DirToOffset(string dir)
|
||||||
|
{
|
||||||
|
return dir switch
|
||||||
|
{
|
||||||
|
"up" => (-1, 0),
|
||||||
|
"down" => (1, 0),
|
||||||
|
"left" => (0, -1),
|
||||||
|
"right" => (0, 1),
|
||||||
|
_ => (0, 0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// pointId 转 (row, col)
|
||||||
|
/// </summary>
|
||||||
|
private static (int row, int col) PointIdToRowCol(int pointId, int totalCols)
|
||||||
|
{
|
||||||
|
int row = pointId / totalCols;
|
||||||
|
int col = pointId % totalCols;
|
||||||
|
return (row, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// (row, col) 转 pointId
|
||||||
|
/// </summary>
|
||||||
|
private static int RowColToPointId(int row, int col, int totalCols)
|
||||||
|
{
|
||||||
|
return row * totalCols + col;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 核心检测逻辑 ==========
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构建所有箭头占用的网格点集合
|
||||||
|
/// 返回: Dictionary<pointId, List<arrowId>> —— 每个网格点被哪些箭头占用
|
||||||
|
/// </summary>
|
||||||
|
private static Dictionary<int, List<int>> BuildGridOccupation(LevelConfig config)
|
||||||
|
{
|
||||||
|
var gridOccupation = new Dictionary<int, List<int>>();
|
||||||
|
int totalCols = config.gridCols;
|
||||||
|
|
||||||
|
foreach (var arrow in config.arrows)
|
||||||
|
{
|
||||||
|
int curPointId = arrow.startPoint;
|
||||||
|
|
||||||
|
// 起点也加入占用
|
||||||
|
if (!gridOccupation.ContainsKey(curPointId))
|
||||||
|
gridOccupation[curPointId] = new List<int>();
|
||||||
|
gridOccupation[curPointId].Add(arrow.id);
|
||||||
|
|
||||||
|
// 沿路径逐步添加占用
|
||||||
|
foreach (string dir in arrow.path)
|
||||||
|
{
|
||||||
|
var (row, col) = PointIdToRowCol(curPointId, totalCols);
|
||||||
|
var (dRow, dCol) = DirToOffset(dir);
|
||||||
|
row += dRow;
|
||||||
|
col += dCol;
|
||||||
|
|
||||||
|
// 边界检查
|
||||||
|
if (row < 0 || row >= config.gridRows || col < 0 || col >= config.gridCols)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"箭头 {arrow.id} 路径超出网格边界");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
curPointId = RowColToPointId(row, col, totalCols);
|
||||||
|
|
||||||
|
if (!gridOccupation.ContainsKey(curPointId))
|
||||||
|
gridOccupation[curPointId] = new List<int>();
|
||||||
|
gridOccupation[curPointId].Add(arrow.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return gridOccupation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取箭头的最终方向(头部朝向)
|
||||||
|
/// </summary>
|
||||||
|
private static string GetFinalDirection(ArrowConfig arrow)
|
||||||
|
{
|
||||||
|
if (arrow.path != null && arrow.path.Count > 0)
|
||||||
|
return arrow.path[arrow.path.Count - 1];
|
||||||
|
return "up"; // 默认向上
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取箭头头部的网格位置 (pointId)
|
||||||
|
/// </summary>
|
||||||
|
private static int GetArrowHeadPointId(ArrowConfig arrow, int totalCols)
|
||||||
|
{
|
||||||
|
int curPointId = arrow.startPoint;
|
||||||
|
foreach (string dir in arrow.path)
|
||||||
|
{
|
||||||
|
var (row, col) = PointIdToRowCol(curPointId, totalCols);
|
||||||
|
var (dRow, dCol) = DirToOffset(dir);
|
||||||
|
curPointId = RowColToPointId(row + dRow, col + dCol, totalCols);
|
||||||
|
}
|
||||||
|
return curPointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构建依赖图:检测每个箭头前方被哪些其他箭头阻挡
|
||||||
|
/// 返回: 邻接表 —— blockedBy[arrowId] = List of arrowIds that block it
|
||||||
|
/// 即:要消除 arrowId,必须先消除 blockedBy[arrowId] 中的箭头
|
||||||
|
/// </summary>
|
||||||
|
private static Dictionary<int, HashSet<int>> BuildDependencyGraph(
|
||||||
|
LevelConfig config,
|
||||||
|
Dictionary<int, List<int>> gridOccupation)
|
||||||
|
{
|
||||||
|
var blockedBy = new Dictionary<int, HashSet<int>>();
|
||||||
|
int totalCols = config.gridCols;
|
||||||
|
int totalRows = config.gridRows;
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
foreach (var arrow in config.arrows)
|
||||||
|
{
|
||||||
|
blockedBy[arrow.id] = new HashSet<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var arrow in config.arrows)
|
||||||
|
{
|
||||||
|
string finalDir = GetFinalDirection(arrow);
|
||||||
|
int headPointId = GetArrowHeadPointId(arrow, totalCols);
|
||||||
|
var (headRow, headCol) = PointIdToRowCol(headPointId, totalCols);
|
||||||
|
var (dRow, dCol) = DirToOffset(finalDir);
|
||||||
|
|
||||||
|
// 沿最终方向逐格扫描
|
||||||
|
int curRow = headRow + dRow;
|
||||||
|
int curCol = headCol + dCol;
|
||||||
|
|
||||||
|
while (curRow >= 0 && curRow < totalRows && curCol >= 0 && curCol < totalCols)
|
||||||
|
{
|
||||||
|
int curPointId = RowColToPointId(curRow, curCol, totalCols);
|
||||||
|
|
||||||
|
// 检查该网格点是否被其他箭头占用
|
||||||
|
if (gridOccupation.TryGetValue(curPointId, out var occupyingArrows))
|
||||||
|
{
|
||||||
|
foreach (int occupyingArrowId in occupyingArrows)
|
||||||
|
{
|
||||||
|
// 不能阻挡自己
|
||||||
|
if (occupyingArrowId != arrow.id)
|
||||||
|
{
|
||||||
|
// occupyingArrow 阻挡了当前箭头
|
||||||
|
// 要消除当前箭头,必须先消除 occupyingArrow
|
||||||
|
blockedBy[arrow.id].Add(occupyingArrowId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curRow += dRow;
|
||||||
|
curCol += dCol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return blockedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 使用拓扑排序检测是否有环(死局)
|
||||||
|
/// 返回: (isSolvable, unsolvableArrowIds)
|
||||||
|
/// </summary>
|
||||||
|
private static (bool isSolvable, List<int> unsolvableArrowIds) DetectDeadlock(
|
||||||
|
LevelConfig config,
|
||||||
|
Dictionary<int, HashSet<int>> blockedBy)
|
||||||
|
{
|
||||||
|
// 计算每个箭头的入度(被多少箭头阻挡)
|
||||||
|
var inDegree = new Dictionary<int, int>();
|
||||||
|
foreach (var arrow in config.arrows)
|
||||||
|
{
|
||||||
|
inDegree[arrow.id] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建反向邻接表:谁依赖于我
|
||||||
|
var dependents = new Dictionary<int, List<int>>();
|
||||||
|
foreach (var arrow in config.arrows)
|
||||||
|
{
|
||||||
|
dependents[arrow.id] = new List<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var kvp in blockedBy)
|
||||||
|
{
|
||||||
|
int arrowId = kvp.Key;
|
||||||
|
foreach (int blockerId in kvp.Value)
|
||||||
|
{
|
||||||
|
// arrowId 依赖 blockerId
|
||||||
|
// blockerId -> arrowId
|
||||||
|
dependents[blockerId].Add(arrowId);
|
||||||
|
inDegree[arrowId]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kahn 拓扑排序
|
||||||
|
var queue = new Queue<int>();
|
||||||
|
foreach (var arrow in config.arrows)
|
||||||
|
{
|
||||||
|
if (inDegree[arrow.id] == 0)
|
||||||
|
{
|
||||||
|
queue.Enqueue(arrow.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int removedCount = 0;
|
||||||
|
while (queue.Count > 0)
|
||||||
|
{
|
||||||
|
int current = queue.Dequeue();
|
||||||
|
removedCount++;
|
||||||
|
|
||||||
|
foreach (int dependent in dependents[current])
|
||||||
|
{
|
||||||
|
inDegree[dependent]--;
|
||||||
|
if (inDegree[dependent] == 0)
|
||||||
|
{
|
||||||
|
queue.Enqueue(dependent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果所有箭头都能被移除,则可解
|
||||||
|
if (removedCount == config.arrows.Count)
|
||||||
|
{
|
||||||
|
return (true, new List<int>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找出无法移除的箭头(入度 > 0 的)
|
||||||
|
var unsolvableArrows = new List<int>();
|
||||||
|
foreach (var arrow in config.arrows)
|
||||||
|
{
|
||||||
|
if (inDegree[arrow.id] > 0)
|
||||||
|
{
|
||||||
|
unsolvableArrows.Add(arrow.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (false, unsolvableArrows);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从环路中提取所有涉及的箭头ID
|
||||||
|
/// </summary>
|
||||||
|
private static List<int> ExtractCycleArrowIds(
|
||||||
|
LevelConfig config,
|
||||||
|
Dictionary<int, HashSet<int>> blockedBy,
|
||||||
|
List<int> unsolvableArrows)
|
||||||
|
{
|
||||||
|
// 从不可解的箭头出发,DFS找出所有在环路中的箭头
|
||||||
|
var allCycleNodes = new HashSet<int>();
|
||||||
|
|
||||||
|
foreach (int startId in unsolvableArrows)
|
||||||
|
{
|
||||||
|
if (allCycleNodes.Contains(startId))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// 尝试从 startId 出发找环
|
||||||
|
var visited = new HashSet<int>();
|
||||||
|
var inStack = new HashSet<int>();
|
||||||
|
var path = new List<int>();
|
||||||
|
|
||||||
|
if (FindCycle(startId, blockedBy, visited, inStack, path, out var cycleNodes))
|
||||||
|
{
|
||||||
|
foreach (int node in cycleNodes)
|
||||||
|
{
|
||||||
|
allCycleNodes.Add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allCycleNodes.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DFS寻找环路
|
||||||
|
/// </summary>
|
||||||
|
private static bool FindCycle(
|
||||||
|
int current,
|
||||||
|
Dictionary<int, HashSet<int>> blockedBy,
|
||||||
|
HashSet<int> visited,
|
||||||
|
HashSet<int> inStack,
|
||||||
|
List<int> path,
|
||||||
|
out List<int> cycleNodes)
|
||||||
|
{
|
||||||
|
visited.Add(current);
|
||||||
|
inStack.Add(current);
|
||||||
|
path.Add(current);
|
||||||
|
|
||||||
|
if (blockedBy.TryGetValue(current, out var blockers))
|
||||||
|
{
|
||||||
|
foreach (int blocker in blockers)
|
||||||
|
{
|
||||||
|
if (!visited.Contains(blocker))
|
||||||
|
{
|
||||||
|
if (FindCycle(blocker, blockedBy, visited, inStack, path, out cycleNodes))
|
||||||
|
{
|
||||||
|
inStack.Remove(current);
|
||||||
|
path.RemoveAt(path.Count - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (inStack.Contains(blocker))
|
||||||
|
{
|
||||||
|
// 找到环
|
||||||
|
int cycleStartIndex = path.IndexOf(blocker);
|
||||||
|
cycleNodes = path.GetRange(cycleStartIndex, path.Count - cycleStartIndex);
|
||||||
|
inStack.Remove(current);
|
||||||
|
path.RemoveAt(path.Count - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inStack.Remove(current);
|
||||||
|
path.RemoveAt(path.Count - 1);
|
||||||
|
cycleNodes = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 公共接口 ==========
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检测单个关卡是否可解
|
||||||
|
/// </summary>
|
||||||
|
public static ValidationResult ValidateLevel(LevelConfig config)
|
||||||
|
{
|
||||||
|
var result = new ValidationResult
|
||||||
|
{
|
||||||
|
levelId = config.levelId,
|
||||||
|
levelName = config.levelName
|
||||||
|
};
|
||||||
|
|
||||||
|
if (config.arrows == null || config.arrows.Count == 0)
|
||||||
|
{
|
||||||
|
result.isSolvable = true;
|
||||||
|
result.message = "关卡无箭头";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 构建网格占用
|
||||||
|
var gridOccupation = BuildGridOccupation(config);
|
||||||
|
|
||||||
|
// 2. 构建依赖图
|
||||||
|
var blockedBy = BuildDependencyGraph(config, gridOccupation);
|
||||||
|
|
||||||
|
// 3. 拓扑排序检测
|
||||||
|
var (isSolvable, unsolvableArrows) = DetectDeadlock(config, blockedBy);
|
||||||
|
|
||||||
|
result.isSolvable = isSolvable;
|
||||||
|
result.blockedBy = blockedBy;
|
||||||
|
|
||||||
|
if (isSolvable)
|
||||||
|
{
|
||||||
|
result.message = "✅ 可解";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 找出环路中的具体箭头
|
||||||
|
var cycleArrows = ExtractCycleArrowIds(config, blockedBy, unsolvableArrows);
|
||||||
|
result.unsolvableArrowIds = cycleArrows.OrderBy(x => x).ToList();
|
||||||
|
result.message = $"❌ 死局,无法消除的箭头: [{string.Join(", ", result.unsolvableArrowIds)}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量检测关卡目录下所有JSON文件
|
||||||
|
/// </summary>
|
||||||
|
public static void ValidateAllLevels(string folderPath)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(folderPath))
|
||||||
|
{
|
||||||
|
Debug.LogError($"目录不存在: {folderPath}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] jsonFiles = Directory.GetFiles(folderPath, "*.json");
|
||||||
|
int totalCount = jsonFiles.Length;
|
||||||
|
int solvableCount = 0;
|
||||||
|
int unsolvableCount = 0;
|
||||||
|
var unsolvableResults = new List<ValidationResult>();
|
||||||
|
|
||||||
|
foreach (string filePath in jsonFiles)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string json = File.ReadAllText(filePath);
|
||||||
|
LevelConfig config = JsonUtility.FromJson<LevelConfig>(json);
|
||||||
|
|
||||||
|
var result = ValidateLevel(config);
|
||||||
|
|
||||||
|
if (result.isSolvable)
|
||||||
|
solvableCount++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsolvableCount++;
|
||||||
|
unsolvableResults.Add(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log($"[{filePath}] {result.message}");
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"解析文件失败: {filePath}, 错误: {e.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log("========== 检测汇总 ==========");
|
||||||
|
Debug.Log($"总关卡数: {totalCount}");
|
||||||
|
Debug.Log($"可解关卡: {solvableCount}");
|
||||||
|
Debug.Log($"死局关卡: {unsolvableCount}");
|
||||||
|
|
||||||
|
if (unsolvableResults.Count > 0)
|
||||||
|
{
|
||||||
|
Debug.Log("========== 死局关卡详情 ==========");
|
||||||
|
foreach (var result in unsolvableResults)
|
||||||
|
{
|
||||||
|
Debug.Log($"关卡 {result.levelId} ({result.levelName}): {result.message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 编辑器菜单 ==========
|
||||||
|
|
||||||
|
[MenuItem("Tools/箭头游戏/检测单个关卡(选择JSON文件)")]
|
||||||
|
public static void ValidateSelectedLevel()
|
||||||
|
{
|
||||||
|
string path = EditorUtility.OpenFilePanel("选择关卡JSON", Application.streamingAssetsPath, "json");
|
||||||
|
if (string.IsNullOrEmpty(path)) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string json = File.ReadAllText(path);
|
||||||
|
LevelConfig config = JsonUtility.FromJson<LevelConfig>(json);
|
||||||
|
|
||||||
|
var result = ValidateLevel(config);
|
||||||
|
|
||||||
|
Debug.Log($"========== 关卡 {result.levelId} ({result.levelName}) 检测结果 ==========");
|
||||||
|
Debug.Log(result.message);
|
||||||
|
|
||||||
|
if (!result.isSolvable)
|
||||||
|
{
|
||||||
|
Debug.Log($"环路箭头: [{string.Join(", ", result.unsolvableArrowIds)}]");
|
||||||
|
|
||||||
|
// 打印依赖详情
|
||||||
|
Debug.Log("========== 依赖关系 ==========");
|
||||||
|
foreach (int id in result.unsolvableArrowIds)
|
||||||
|
{
|
||||||
|
if (result.blockedBy.TryGetValue(id, out var blockers))
|
||||||
|
{
|
||||||
|
Debug.Log($"箭头 {id} 被阻挡于: [{string.Join(", ", blockers)}]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorUtility.DisplayDialog("检测完成", result.message, "确定");
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"检测失败: {e.Message}");
|
||||||
|
EditorUtility.DisplayDialog("错误", $"检测失败: {e.Message}", "确定");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("Tools/箭头游戏/批量检测所有关卡")]
|
||||||
|
public static void ValidateAllLevelsMenu()
|
||||||
|
{
|
||||||
|
string folderPath = EditorUtility.OpenFolderPanel("选择关卡目录", Application.streamingAssetsPath, "");
|
||||||
|
if (string.IsNullOrEmpty(folderPath)) return;
|
||||||
|
|
||||||
|
ValidateAllLevels(folderPath);
|
||||||
|
EditorUtility.DisplayDialog("批量检测完成", "请查看Console输出结果", "确定");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 数据结构 ==========
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检测结果
|
||||||
|
/// </summary>
|
||||||
|
public class ValidationResult
|
||||||
|
{
|
||||||
|
public int levelId;
|
||||||
|
public string levelName;
|
||||||
|
public bool isSolvable;
|
||||||
|
public string message;
|
||||||
|
public List<int> unsolvableArrowIds = new List<int>();
|
||||||
|
public Dictionary<int, HashSet<int>> blockedBy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: da19b18902544191a3062014594d3b22
|
||||||
|
timeCreated: 1784305307
|
||||||
@@ -4,6 +4,12 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.unity3d.player"
|
package="com.unity3d.player"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<!-- 强制移除webview aar自带的媒体权限,解决Play未声明报错 -->
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" tools:node="remove"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" tools:node="remove"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" tools:node="remove"/>
|
||||||
|
|
||||||
<application>
|
<application>
|
||||||
<activity android:name="com.unity3d.player.UnityPlayerActivity"
|
<activity android:name="com.unity3d.player.UnityPlayerActivity"
|
||||||
android:theme="@style/UnityThemeSelector">
|
android:theme="@style/UnityThemeSelector">
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><resources><string name="com.crashlytics.android.build_id" translatable="false">a3b8638f-c8ff-4e13-89ae-85cb2b148835</string></resources>
|
<?xml version="1.0" encoding="utf-8"?><resources><string name="com.crashlytics.android.build_id" translatable="false">d4a07f28-7baa-4f99-aa00-e8f80b7c45a1</string></resources>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
"failed_save": "Failed to save information., please try again!",
|
"failed_save": "Failed to save information., please try again!",
|
||||||
"un_lock": "To be unlocked",
|
"un_lock": "To be unlocked",
|
||||||
"exchange_succ": "Claim({0})",
|
"exchange_succ": "Claim({0})",
|
||||||
"exchange_success": "Claim X{0}",
|
"redeem_success": "Claim X{0}",
|
||||||
"free_revive": "Free Revive",
|
"free_revive": "Free Revive",
|
||||||
"revive": "Revive",
|
"revive": "Revive",
|
||||||
"need_lv_text":"Level {0}",
|
"need_lv_text":"Level {0}",
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
"failed_save": "情報の保存に失敗しました。再度お試しください!",
|
"failed_save": "情報の保存に失敗しました。再度お試しください!",
|
||||||
"un_lock": "解放待ち",
|
"un_lock": "解放待ち",
|
||||||
"exchange_succ": "受け取る({0})",
|
"exchange_succ": "受け取る({0})",
|
||||||
"exchange_success": "X{0}を受け取る",
|
"redeem_success": "X{0}を受け取る",
|
||||||
"free_revive": "無料復活",
|
"free_revive": "無料復活",
|
||||||
"revive": "復活",
|
"revive": "復活",
|
||||||
"need_lv_text": "レベル{0}",
|
"need_lv_text": "レベル{0}",
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
"failed_save": "정보 저장에 실패했습니다. 다시 시도해 주세요!",
|
"failed_save": "정보 저장에 실패했습니다. 다시 시도해 주세요!",
|
||||||
"un_lock": "잠금 해제 예정",
|
"un_lock": "잠금 해제 예정",
|
||||||
"exchange_succ": "수령({0})",
|
"exchange_succ": "수령({0})",
|
||||||
"exchange_success": "X{0} 수령",
|
"redeem_success": "X{0} 수령",
|
||||||
"free_revive": "무료 부활",
|
"free_revive": "무료 부활",
|
||||||
"revive": "부활",
|
"revive": "부활",
|
||||||
"need_lv_text": "레벨 {0}",
|
"need_lv_text": "레벨 {0}",
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
"failed_save": "Не удалось сохранить данные, попробуйте снова!",
|
"failed_save": "Не удалось сохранить данные, попробуйте снова!",
|
||||||
"un_lock": "Будет разблокировано",
|
"un_lock": "Будет разблокировано",
|
||||||
"exchange_succ": "Забрать({0})",
|
"exchange_succ": "Забрать({0})",
|
||||||
"exchange_success": "Забрать X{0}",
|
"redeem_success": "Забрать X{0}",
|
||||||
"free_revive": "Бесплатное воскрешение",
|
"free_revive": "Бесплатное воскрешение",
|
||||||
"revive": "Воскреснуть",
|
"revive": "Воскреснуть",
|
||||||
"need_lv_text": "Уровень {0}",
|
"need_lv_text": "Уровень {0}",
|
||||||
@@ -125,7 +125,7 @@
|
|||||||
"failed_save": "जानकारी सहेजने में विफल, कृपया पुनः प्रयास करें!",
|
"failed_save": "जानकारी सहेजने में विफल, कृपया पुनः प्रयास करें!",
|
||||||
"un_lock": "जल्द अनलॉक होगा",
|
"un_lock": "जल्द अनलॉक होगा",
|
||||||
"exchange_succ": "दावा करें({0})",
|
"exchange_succ": "दावा करें({0})",
|
||||||
"exchange_success": "X{0} दावा करें",
|
"redeem_success": "X{0} दावा करें",
|
||||||
"free_revive": "मुफ्त पुनर्जीवन",
|
"free_revive": "मुफ्त पुनर्जीवन",
|
||||||
"revive": "पुनर्जीवित करें",
|
"revive": "पुनर्जीवित करें",
|
||||||
"need_lv_text": "स्तर {0}",
|
"need_lv_text": "स्तर {0}",
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
"exchange_success": "विनिमय सफल"
|
"exchange_success": "विनिमय सफल"
|
||||||
},
|
},
|
||||||
"pt": {
|
"pt": {
|
||||||
"copy_succeed": "Cópia realizada com sucesso",
|
"copy_succeed": " Cópia realizada com sucesso",
|
||||||
"not_ads": "Os anúncios ainda não estão prontos!",
|
"not_ads": "Os anúncios ainda não estão prontos!",
|
||||||
"try_send": "Enviando e-mail…",
|
"try_send": "Enviando e-mail…",
|
||||||
"no_network": "Sua conexão com a internet está instável!",
|
"no_network": "Sua conexão com a internet está instável!",
|
||||||
@@ -153,7 +153,7 @@
|
|||||||
"failed_save": "Falha ao salvar as informações, tente novamente!",
|
"failed_save": "Falha ao salvar as informações, tente novamente!",
|
||||||
"un_lock": "A ser desbloqueado",
|
"un_lock": "A ser desbloqueado",
|
||||||
"exchange_succ": "Resgatar({0})",
|
"exchange_succ": "Resgatar({0})",
|
||||||
"exchange_success": "Resgatar X{0}",
|
"redeem_success": "Resgatar X{0}",
|
||||||
"free_revive": "Reviver grátis",
|
"free_revive": "Reviver grátis",
|
||||||
"revive": "Reviver",
|
"revive": "Reviver",
|
||||||
"need_lv_text": "Nível {0}",
|
"need_lv_text": "Nível {0}",
|
||||||
@@ -181,7 +181,7 @@
|
|||||||
"failed_save": "Speichern fehlgeschlagen, bitte erneut versuchen!",
|
"failed_save": "Speichern fehlgeschlagen, bitte erneut versuchen!",
|
||||||
"un_lock": "Wird freigeschaltet",
|
"un_lock": "Wird freigeschaltet",
|
||||||
"exchange_succ": "Einlösen({0})",
|
"exchange_succ": "Einlösen({0})",
|
||||||
"exchange_success": "X{0} einlösen",
|
"redeem_success": "X{0} einlösen",
|
||||||
"free_revive": "Kostenlose Wiederbelebung",
|
"free_revive": "Kostenlose Wiederbelebung",
|
||||||
"revive": "Wiederbeleben",
|
"revive": "Wiederbeleben",
|
||||||
"need_lv_text": "Level {0}",
|
"need_lv_text": "Level {0}",
|
||||||
@@ -209,7 +209,7 @@
|
|||||||
"failed_save": "Échec de l'enregistrement, veuillez réessayer !",
|
"failed_save": "Échec de l'enregistrement, veuillez réessayer !",
|
||||||
"un_lock": "À débloquer",
|
"un_lock": "À débloquer",
|
||||||
"exchange_succ": "Réclamer({0})",
|
"exchange_succ": "Réclamer({0})",
|
||||||
"exchange_success": "Réclamer X{0}",
|
"redeem_success": "Réclamer X{0}",
|
||||||
"free_revive": "Réanimation gratuite",
|
"free_revive": "Réanimation gratuite",
|
||||||
"revive": "Réanimer",
|
"revive": "Réanimer",
|
||||||
"need_lv_text": "Niveau {0}",
|
"need_lv_text": "Niveau {0}",
|
||||||
@@ -237,7 +237,7 @@
|
|||||||
"failed_save": "Error al guardar la información, inténtalo de nuevo!",
|
"failed_save": "Error al guardar la información, inténtalo de nuevo!",
|
||||||
"un_lock": "Pendiente de desbloquear",
|
"un_lock": "Pendiente de desbloquear",
|
||||||
"exchange_succ": "Reclamar({0})",
|
"exchange_succ": "Reclamar({0})",
|
||||||
"exchange_success": "Reclamar X{0}",
|
"redeem_success": "Reclamar X{0}",
|
||||||
"free_revive": "Revivir gratis",
|
"free_revive": "Revivir gratis",
|
||||||
"revive": "Revivir",
|
"revive": "Revivir",
|
||||||
"need_lv_text": "Nivel {0}",
|
"need_lv_text": "Nivel {0}",
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ namespace ChillConnect
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
ui.btn_mult.GetChild("title").text = Language.GetContentParams("exchange_success", AwardRate);
|
ui.btn_mult.GetChild("title").text = Language.GetContentParams(" redeem_success", AwardRate);
|
||||||
|
|
||||||
if (SuccessDatas.IsH5Reward)
|
if (SuccessDatas.IsH5Reward)
|
||||||
ui.com_ch.visible = false;
|
ui.com_ch.visible = false;
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ PlayerSettings:
|
|||||||
loadStoreDebugModeEnabled: 0
|
loadStoreDebugModeEnabled: 0
|
||||||
visionOSBundleVersion: 1.0
|
visionOSBundleVersion: 1.0
|
||||||
tvOSBundleVersion: 1.0
|
tvOSBundleVersion: 1.0
|
||||||
bundleVersion: 1.0.0
|
bundleVersion: 1.0.1
|
||||||
preloadedAssets: []
|
preloadedAssets: []
|
||||||
metroInputSource: 0
|
metroInputSource: 0
|
||||||
wsaTransparentSwapchain: 0
|
wsaTransparentSwapchain: 0
|
||||||
@@ -171,7 +171,7 @@ PlayerSettings:
|
|||||||
iPhone: 2
|
iPhone: 2
|
||||||
tvOS: 0
|
tvOS: 0
|
||||||
overrideDefaultApplicationIdentifier: 1
|
overrideDefaultApplicationIdentifier: 1
|
||||||
AndroidBundleVersionCode: 1
|
AndroidBundleVersionCode: 2
|
||||||
AndroidMinSdkVersion: 24
|
AndroidMinSdkVersion: 24
|
||||||
AndroidTargetSdkVersion: 36
|
AndroidTargetSdkVersion: 36
|
||||||
AndroidPreferredInstallLocation: 1
|
AndroidPreferredInstallLocation: 1
|
||||||
@@ -849,7 +849,7 @@ PlayerSettings:
|
|||||||
webGLMemoryGeometricGrowthCap: 96
|
webGLMemoryGeometricGrowthCap: 96
|
||||||
webGLPowerPreference: 2
|
webGLPowerPreference: 2
|
||||||
scriptingDefineSymbols:
|
scriptingDefineSymbols:
|
||||||
Android: UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI;USE_ADDRESSABLES;GAME_RELEASE
|
Android: UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI;USE_ADDRESSABLES;GAME_RELEASE1
|
||||||
EmbeddedLinux: UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI
|
EmbeddedLinux: UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI
|
||||||
LinuxHeadlessSimulation: UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI
|
LinuxHeadlessSimulation: UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI
|
||||||
Nintendo Switch: UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI
|
Nintendo Switch: UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI
|
||||||
|
|||||||
Reference in New Issue
Block a user