Files
AliceBall/Assets/_Alice/Scripts/Base/GameManager.cs

761 lines
22 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines;
using Common;
using DarkTonic.MasterAudio;
using DragonLi.Core;
using LitJson;
using NaughtyAttributes;
using Pathfinding;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.PlayerLoop;
using UnityEngine.UIElements;
using XPlugin.Data.JsonLiteDB;
using static XPlugin.Data.JsonLiteDB.JsonLiteDB;
/// <summary>
/// 游戏状态
/// </summary>
public enum GameState
{
None = 0,
Playing = 1,
/// <summary>
/// 胜利
/// </summary>
Victory = 2,
/// <summary>
/// 失败
/// </summary>
Failur = 3,
Settle
}
public class GameManager : MonoBehaviour
{
public static GameManager Ins { get; private set; }
public TaskManager taskManager;
public GameState gameState;
public float vistEnd = 60 * 10;
public GameObject wuHui;
//预制体
public GameObject playerPre;
public GameObject enemyPre;
public GameObject gemKeyPre;
public GameObject eggBulletPre;
public GameObject eggBulletExPre;
public GameObject gameStartDoor;
public RightHand playerRightHand;
public Enemy enemy;
public bool isStartGame = false;
//添加
[Header("AI角色")]
public GameObject aiCharacterPre;//AI角色预制体
private GameObject aiCharacter;//AI角色实例
// 新增:指引系统
[Header("指引系统")]
public GameObject GuideArrowPre; // 指引箭头预制体
private GameObject guideArrowInstance; // 指引箭头实例
private GuideArrowPath guideArrowComponent; // 指引箭头组件
private bool isGuideArrowActive = false;
private Vector3 lastPlayerPosition; // 记录玩家上一次的位置
private float updatePathThreshold = 0.5f; // 更新路径的阈值(玩家移动超过这个距离才更新路径)
private float updatePathCooldown = 0.3f; // 更新路径的冷却时间
private float lastPathUpdateTime = 0f;
private Vector3[] lastPathPoints; // 上一次的路径点
private bool isPathSmoothed = false;
private List<Vector3> smoothedPath = new List<Vector3>();
void Awake()
{
Ins = this;
}
private void Start()
{
isStartGame = false;
wuHui.SetActive(false);
// 新增:初始化指引系统
InitializeGuideArrow();
}
public void GameStart()
{
CreateAICharacter();
CleanupGuideArrow();
//isStartGame = true;
//HUDPanel.Show();
//taskManager.bg.SetActive(true);
//CreateEnemy(GameLocal.Ins.enemyPos.position, new Vector3(0,180,0));
//宝石任务
//enemy.SetState(1);
//taskManager.curTaskId = 1;
//拔萝卜任务
// enemy.SetState(2);
// taskManager.curTaskId = 2;
//换装任务
//taskManager.curTaskId = 3;
//taskManager.StartTask();
//打鸡蛋任务
//enemy.SetState(3);
//taskManager.curTaskId = 4;
//taskManager.StartTask();
}
//修改处添加创建AI角色的方法
private void CreateAICharacter()
{
//检查是否已经存在AI角色
if (aiCharacter != null)
{
Debug.Log("AI角色已经存在不再创建新的");
return;
}
if (aiCharacterPre != null)
{
Debug.Log("创建AI角色");
//在玩家前方创建AI角色
Vector3 spawnPosition = playerPre.transform.position + playerPre.transform.forward * 3f;
aiCharacter = Instantiate(aiCharacterPre, spawnPosition, Quaternion.identity);
//获取AIController并启动开场白
AIController aiController = aiCharacter.GetComponent<AIController>();
if (aiController != null)
{
//注册AI介绍完成回调
aiController.OnIntroductionComplete += StartGameAfterIntroduction;
//添加延迟,确保所有组件已经完成初始化
StartCoroutine(DelayedStartIntroduction(aiController));
}
else
{
Debug.LogError("AI预制体中的AIController组件丢失");
}
}
else
{
Debug.LogError("AI预制体没有在GameManager分配!");
}
}
public void StartGameAfterIntroduction()
{
isStartGame = true;
Debug.Log("AI介绍完成开始游戏正常流程");
HUDPanel.Show();
taskManager.bg.SetActive(true);
CreateEnemy(GameLocal.Ins.enemyPos.position, new Vector3(0, 180, 0));
}
private IEnumerator DelayedStartIntroduction(AIController aiController)
{
yield return new WaitForSeconds(0.1f); // 短暂延迟
aiController.StartIntroduction();
}
public void LoginGame()
{
CreatePlayer();
//PlaySound2DRPC("1.25");
PlayBGM(0);
CreateGameStartDoor(GameLocal.Ins.startDoorPos.position);
}
public void PlayBGM(int id)
{
foreach (var item in GameLocal.Ins.BGM)
{
item.SetActive(false);
}
GameLocal.Ins.BGM[id].SetActive(true);
}
public void GameOver(GameState state)
{
}
/// <summary>
/// 更新配置表
/// </summary>
public void UpdateConf()
{
// string text = Resources.Load<TextAsset>("Data").text;
// if (text != null)
// {
// ParseGameJson(text);
// }
}
public void ParseGameJson(string text)
{
// DB = new JsonLiteDB();
// DB.Load(text);
//
// TableReader infoReader = DB["EnemysInfo"].GetReader();
// while (infoReader.Read())
// {
// EnemyInfo info = new EnemyInfo(infoReader);
//
// }
Debug.Log("游戏数值更新 -> complete");
}
public void StopBgm()
{
}
public void PlaySound2DRPC(string sound)
{
MasterAudio.PlaySound(sound);
}
public void PlaySound3DRPC(string sound,Transform soundTran,bool isStop=false)
{
if(isStop)
MasterAudio.StopAllSoundsOfTransform(soundTran);
MasterAudio.PlaySound3DAtTransform(sound, soundTran);
}
public void CreateGameStartDoor(Vector3 pos)
{
var door= Instantiate(gameStartDoor, pos, Quaternion.identity);
// 延迟开始指引,确保玩家和门都已初始化
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
StartGuide();
}, 0.5f);
if (GameLocal.Ins.place == Place.Jiangsu_Xvzhou_Suning_Guangchang
||GameLocal.Ins.place == Place.Hunan_Changde_Lixian_WandaGuangchang
||GameLocal.Ins.place == Place.Hunan_Zhuzhou_Wanda_Shennongcheng_Chaowanshe
)
{
door.transform.eulerAngles = new Vector3(0, 90, 0);
}
if ( GameLocal.Ins.place == Place.Hunan_Zhuzhou_Wanda_Shennongcheng_Chaowanshe
)
{
door.transform.eulerAngles = new Vector3(0, -90, 0);
}
else
{
door.transform.eulerAngles = new Vector3(0, 180, 0);
}
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
if (!isStartGame)
{
if (door.gameObject==null)
return;
door.gameObject.GetComponent<Collider>().enabled = false;
door.gameObject.SetActive(false);
Destroy(door.gameObject);
if (taskManager.curTaskId != 4)
{
GameStart();
}
else
{
StartDance();
}
}
},5);
}
public void CreatePlayer()
{
Instantiate(playerPre);
}
public void CreateEnemy(Vector3 pos,Vector3 eulerAngles)
{
var curEnemy=Instantiate(enemyPre,pos,Quaternion.identity);
curEnemy.transform.eulerAngles = eulerAngles;
curEnemy.GetComponent<Enemy>().Init();
enemy = curEnemy.GetComponent<Enemy>();
}
public GameObject CreateGemKey(Vector3 pos,Vector3 eulerAngles,Transform box)
{
var key= Instantiate(gemKeyPre, pos,Quaternion.identity,box);
key.transform.localEulerAngles = eulerAngles;
key.transform.localPosition = pos;
return key;
}
public void CreateEggBullet(Vector3 pos)
{
var egg= Instantiate(eggBulletPre, pos,Quaternion.identity);
egg.GetComponent<EggBullet>().Init();
}
public void CreateEggEx(Vector3 pos)
{
var eggEx= Instantiate(eggBulletExPre, pos,Quaternion.identity);
PlaySound2DRPC("1.23");
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
Destroy(eggEx);
},5f);
}
public void PlayerHit()
{
if(enemy.isDie)
return;
//玩家UI模糊
HUDPanel.Ins.ShowEgg();
Debug.Log("击中玩家");
PlaySound2DRPC("1.50");
}
public void EnemyHit(Vector3 pos)
{
if(enemy.isDie)
return;
enemy.Hit();
PlaySound3DRPC("1.49",enemy.transform,true);
CreateEggEx(pos);
}
public void EnemyTimeHit()
{
enemy.isTimeHit = true;
}
public void StartGameEnd()
{
//任务结束
PlaySound2DRPC("1.24");
playerRightHand.ChangeHand();
taskManager.OverTask();
isStartGame = false;
CreateGameStartDoor(GameLocal.Ins.self.transform.position.ReflectVectorXOZ()+new Vector3(0,0,2));
}
public void StartDance()
{
//开启舞会
Debug.LogError("开启舞会场景");
PlayBGM(1);
wuHui.SetActive(true);
taskManager.bg.SetActive(false);
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
WinPanel.Show();
},10f);
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
wuHui.SetActive(false);
Application.Quit();
}, 90f);
}
private void Update()
{
//if (Input.GetKeyDown(KeyCode.Q))
//{
// CreateEnemy(new Vector3(0, 1, 5), new Vector3(0, 180, 0));
// enemy.SetState(3);
// taskManager.curTaskId = 4;
// taskManager.StartTask();
//}
//更新指引箭头位置
UpdateGuideArrowPosition();
}
#region
public string GetLessTimeStr()
{
string res = "";
if (gameState == GameState.Playing)
{
res = FormatTime((int)(vistEnd - DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds));
}
return res;
}
public int GetLessTimeSeconds()
{
return (int)(vistEnd - DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds);
}
// 时分秒
public string FormatTime(int totalSeconds)
{
int hours = totalSeconds / 3600;
// string hh = hours < 10 ? "0" + hours : hours.ToString();
int minutes = (totalSeconds - hours * 3600) / 60;
string mm = minutes < 10f ? "0" + minutes : minutes.ToString();
int seconds = totalSeconds - hours * 3600 - minutes * 60;
string ss = seconds < 10 ? "0" + seconds : seconds.ToString();
return string.Format("{0}:{1}", mm, ss);
}
#endregion
#region
/// <summary>
/// 初始化指引箭头
/// </summary>
private void InitializeGuideArrow()
{
// 检查预制体是否存在
if (GuideArrowPre == null)
{
Debug.LogError("GuideArrowPre 预制体未分配!");
return;
}
// 实例化指引箭头预制体
guideArrowInstance = Instantiate(GuideArrowPre);
guideArrowInstance.name = "GuideArrow";
// 获取指引箭头组件
guideArrowComponent = guideArrowInstance.GetComponent<GuideArrowPath>();
if (guideArrowComponent == null)
{
Debug.LogError("GuideArrowPre 预制体上没有找到 GuideArrowPath 组件!");
Destroy(guideArrowInstance);
guideArrowInstance = null;
return;
}
// 设置指引箭头的层级和高度
guideArrowComponent.obstacleMask = LayerMask.GetMask("Default"); // 根据实际障碍物层级设置
guideArrowComponent.pathHeight = 0.5f; // 设置路径显示高度
// 初始隐藏指引
guideArrowComponent.ClosePath();
// 可选:设置父物体,保持场景整洁
guideArrowInstance.transform.SetParent(this.transform);
// 初始化玩家位置
if (GameLocal.Ins.self != null)
{
lastPlayerPosition = GameLocal.Ins.self.transform.position;
}
}
/// <summary>
/// 更新指引箭头位置(实时跟随玩家移动)
/// </summary>
// 修改 UpdateGuideArrowPosition 方法
private void UpdateGuideArrowPosition()
{
if (!isGuideArrowActive || GameLocal.Ins.startDoorPos == null || GameLocal.Ins.self == null)
return;
// 获取玩家当前位置
Vector3 currentPlayerPosition = GameLocal.Ins.self.transform.position;
// 检查冷却时间
if (Time.time - lastPathUpdateTime < updatePathCooldown)
return;
// 检查玩家是否移动了足够远的距离
float distanceMoved = Vector3.Distance(currentPlayerPosition, lastPlayerPosition);
if (distanceMoved > updatePathThreshold)
{
// 获取门的位置
Vector3 doorPosition = GameLocal.Ins.startDoorPos.transform.position;
// 使用曲线检测和路径平滑
UpdatePathWithCurveDetection(currentPlayerPosition, doorPosition);
// 更新记录的位置和时间
lastPlayerPosition = currentPlayerPosition;
lastPathUpdateTime = Time.time;
}
}
// 新增:使用曲线检测和路径平滑的方法
private void UpdatePathWithCurveDetection(Vector3 start, Vector3 end)
{
if (guideArrowComponent == null)
return;
// 1. 检测是否为直接可见路径
if (IsDirectPathClear(start, end))
{
// 直接路径,使用简单的贝塞尔曲线
smoothedPath = GenerateBezierCurve(start, end, 0.2f);
guideArrowComponent.SetPath(smoothedPath); // 这里使用 List<Vector3> 参数
isPathSmoothed = true;
return;
}
// 2. 间接路径,使用优化的绕路算法
List<Vector3> newPath = CalculateObstacleAvoidancePath(start, end);
if (newPath != null && newPath.Count > 1)
{
// 应用路径平滑
smoothedPath = SmoothPath(newPath);
guideArrowComponent.SetPath(smoothedPath); // 这里使用 List<Vector3> 参数
isPathSmoothed = true;
lastPathPoints = smoothedPath.ToArray();
}
}
// 新增:检查直接路径是否畅通
private bool IsDirectPathClear(Vector3 start, Vector3 end)
{
Vector3 direction = (end - start).normalized;
float distance = Vector3.Distance(start, end);
// 使用射线检测,同时检查多个点
int checkPoints = Mathf.CeilToInt(distance / 0.5f);
for (int i = 0; i <= checkPoints; i++)
{
float t = (float)i / checkPoints;
Vector3 checkPoint = Vector3.Lerp(start, end, t);
// 检查周围小范围的碰撞
if (Physics.CheckSphere(checkPoint, 0.3f, guideArrowComponent.obstacleMask))
{
return false;
}
}
return true;
}
// 新增:生成贝塞尔曲线路径
private List<Vector3> GenerateBezierCurve(Vector3 start, Vector3 end, float curveHeight)
{
List<Vector3> curvePoints = new List<Vector3>();
int segments = 20; // 曲线分段数
// 计算控制点(在中间稍微抬起形成曲线)
Vector3 controlPoint = (start + end) * 0.5f + Vector3.up * curveHeight;
for (int i = 0; i <= segments; i++)
{
float t = (float)i / segments;
// 二次贝塞尔曲线公式
Vector3 point = (1 - t) * (1 - t) * start +
2 * (1 - t) * t * controlPoint +
t * t * end;
curvePoints.Add(point);
}
return curvePoints;
}
// 新增:优化后的绕障碍物路径计算
private List<Vector3> CalculateObstacleAvoidancePath(Vector3 start, Vector3 end)
{
List<Vector3> path = new List<Vector3>();
path.Add(start);
// 尝试寻找最佳绕行点
Vector3 bypassPoint = FindOptimalBypassPoint(start, end);
if (bypassPoint != start)
{
// 如果有绕行点,构建曲线路径
List<Vector3> curve1 = GenerateBezierCurve(start, bypassPoint, 0.3f);
List<Vector3> curve2 = GenerateBezierCurve(bypassPoint, end, 0.3f);
path.AddRange(curve1.Skip(1));
path.AddRange(curve2.Skip(1));
}
else
{
// 没有找到绕行点,使用简单的曲线
path = GenerateBezierCurve(start, end, 0.2f);
}
return path;
}
// 新增:寻找最优绕行点
private Vector3 FindOptimalBypassPoint(Vector3 from, Vector3 to)
{
Vector3 direction = (to - from).normalized;
float distance = Vector3.Distance(from, to);
// 定义多个探测方向
Vector3[] probeDirections = new Vector3[]
{
Vector3.Cross(direction, Vector3.up).normalized, // 右侧
-Vector3.Cross(direction, Vector3.up).normalized, // 左侧
(Vector3.Cross(direction, Vector3.up).normalized + Vector3.up * 0.3f).normalized, // 右上
(-Vector3.Cross(direction, Vector3.up).normalized + Vector3.up * 0.3f).normalized // 左上
};
float[] probeDistances = new float[] { 2f, 3f, 4f, 5f };
Vector3 bestBypassPoint = from;
float bestScore = float.MaxValue;
foreach (Vector3 probeDir in probeDirections)
{
foreach (float probeDist in probeDistances)
{
Vector3 probePoint = from + probeDir * probeDist;
// 检查探测点是否可行
if (!Physics.CheckSphere(probePoint, 0.5f, guideArrowComponent.obstacleMask))
{
// 计算路径分数(距离 + 转向角度)
float pathLength = Vector3.Distance(from, probePoint) +
Vector3.Distance(probePoint, to);
float angleCost = Vector3.Angle(probePoint - from, to - probePoint) * 0.1f;
float score = pathLength + angleCost;
if (score < bestScore)
{
bestScore = score;
bestBypassPoint = probePoint;
}
}
}
}
return bestBypassPoint;
}
// 新增:路径平滑算法
private List<Vector3> SmoothPath(List<Vector3> rawPath)
{
if (rawPath.Count < 3)
return rawPath;
List<Vector3> smoothed = new List<Vector3>();
smoothed.Add(rawPath[0]);
// 使用简单的平均平滑
for (int i = 1; i < rawPath.Count - 1; i++)
{
Vector3 smoothedPoint = (rawPath[i - 1] + rawPath[i] + rawPath[i + 1]) / 3f;
smoothed.Add(smoothedPoint);
}
smoothed.Add(rawPath[rawPath.Count - 1]);
return smoothed;
}
/// <summary>
/// 显示指引箭头
/// </summary>
public void ShowGuideArrow()
{
if (guideArrowComponent != null && GameLocal.Ins.startDoorPos != null && GameLocal.Ins.self != null)
{
guideArrowComponent.ShowPath();
isGuideArrowActive = true;
// 初始化路径
Vector3 playerPosition = GameLocal.Ins.self.transform.position;
Vector3 doorPosition = GameLocal.Ins.startDoorPos.transform.position;
UpdatePathWithCurveDetection(playerPosition, doorPosition);
// 记录初始位置
lastPlayerPosition = playerPosition;
}
}
/// <summary>
/// 隐藏指引箭头
/// </summary>
public void HideGuideArrow()
{
if (guideArrowComponent != null)
{
guideArrowComponent.ClosePath();
isGuideArrowActive = false;
}
}
/// <summary>
/// 开始指引(在创建门后调用)
/// </summary>
public void StartGuide()
{
if (GameLocal.Ins.startDoorPos != null && GameLocal.Ins.self != null)
{
ShowGuideArrow();
// 初始化路径
Vector3 playerPosition = GameLocal.Ins.self.transform.position;
Vector3 doorPosition = GameLocal.Ins.startDoorPos.transform.position;
// 使用新的路径计算方法
UpdatePathWithCurveDetection(playerPosition, doorPosition);
// 记录初始位置
lastPlayerPosition = playerPosition;
}
}
/// <summary>
/// 停止指引(在游戏开始或删除门时调用)
/// </summary>
public void StopGuide()
{
HideGuideArrow();
}
/// <summary>
/// 清理指引箭头实例
/// </summary>
public void CleanupGuideArrow()
{
if (guideArrowInstance != null)
{
Destroy(guideArrowInstance);
guideArrowInstance = null;
guideArrowComponent = null;
isGuideArrowActive = false;
}
}
#endregion
}