Files
FutureMen/Assets/Scripts/Manager/GameManager.cs

1458 lines
49 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;
using DragonLi.Core;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.Mathematics;
using Unity.XR.PXR;
using UnityEngine;
using XPlugin.Data.JsonLiteDB;
using static XPlugin.Data.JsonLiteDB.JsonLiteDB;
using Random = UnityEngine.Random;
public enum GameKey
{
DinosaurPark2=0,//重返侏罗纪
SpongeBob=1,//深海冒险
XMen=2,//银河守护者
KOF=3,//幻影交锋
Valheim=4,//小小幻宠
FutureMen=5,//未来战警
AliceBall=6,//爱丽丝的舞会
Zombie=7,//僵尸来了
DefendNJ=8,//保卫金陵
Loong=9, //巨龙猎人
MRCS=10,//火力对决
SXDMystery=11,//三星堆之谜
}
/// <summary>
/// 游戏场地
/// </summary>
public enum GamePlace
{
// Test = -1,
Company1Floor = 0,
Company1FloorShiwai = -999,
LiaoningAnShan = 1,
Liaoning_AnShan_Lishan_Dayuecheng=-1,
HangZhouLongHuTianJie = 2,
Nanjing_Yuhua_Wanxiang = 3,
Nanjing_Xianlin_WanDaMao = 4,
Yangzhou_Hanjiang_Tansuozhongxin = 5,
Yangzhou_Hanjiang_TansuoZhongxin_wai = -5,
Zhejiang_Jinhua_KeJiGuan = 6,
Guangzhou_Panyv_Zhanting = 7,
Anhui_Wuhu_Guanwei = 8,
Shandong_Jining_Shangchang = 9,
Shandong_Jining_Shangchang_nei = -9,
ShanDong_Langfang_QingzhouTaihuacheng = 10,
Hubei_Xiangyang_Kejiguan = 11,
Zhejiang_Shaoxing_Shengzhou_WuyueGuangchang=12,
Hunan_Jishou_Qianzhou_Tianhong=13,
Jilin_Tonghua_Liuhe=14,
Shandong_Jinan_Huaiyin_ShengfutongShangmao = 15,
Shandong_Jinan_Huaiyin_ShengfutongShangmao_wai = -15,
Henan_Xinzheng_Shuanghudadao_Longhujinyicheng = 16,
Nanjing_Qixia_Yaohuamen_Jindiguangchang = 17,
Nanjing_Qixia_Yaohuamen_Jindiguangchang_nei = -17,
Anshan_Suzhou_Yueshan_Guchengshangyejie = 18,
Anhui_Suzhou_Yueshan_Guchengshangyejie_2=-18,
Gansu_Longnan_Shicheng_Dongsheng = 19,
Shandong_Heze_Yuncheng_Gefuli = 20,
Wulanhaote_Ouya_Shangchang = 21,
Wulanhaote_Wanda_Shangchang = -21,
Yunnan_Mile_Jinchen_Shidaiguangchang = 22,
Xinjiang_Yili_Yining_Wanrong = 23,
Hunan_Hengyang_Zhuhui_Dongzhoudao = 24,
Hunan_Hengyang_Zhuhui_Dongzhoudao_nei = -24,
Yunnan_Lincang_Linxiang_Hengji = 25,
Yunnan_Lincang_Linxiang_Hengji_Dixia = -25,
Guangxi_Guilin_Gongcheng_Shijixincheng = 26,
Guangdong_Shenzhen_Guangming_Wanda = 27,
Gansu_Jinchang_Jinchuan_Shijiguangchang = 28,
Gansu_Jinchang_Jinchuan_Shijiguangchang_Shiwai=-28,
Jiangsu_Xvzhou_Fengxian_Wuyueguangchang =29,
Hebei_Tangshan_Qianan_Tianyuangu = 30,
Guangdong_Guangzhou_Yanghaiyan = 31,
Guangdong_Guangzhou_Yanghaiyan_Lihu=-31,
Zhejiang_Hangzhou_Linping_Yintaicheng = 32,
Zhejiang_Hangzhou_Linping_Yintaicheng_Shinei= -32,
Henan_Xinxiang_Wandaguangchang =33,
Henan_Xinxiang_Wandaguangchang_Shinei=-33,
Yangzhou_Hanjiang_TansuoZhongxin_Waidai =34,
Nanjing_Pukou_Longhutianjie=35,
Jiangsu_Xvzhou_Guolou_Oulebao=36,
Jiangsu_Xvzhou_Guolou_Oulebao_2=-36,
Jiangsu_Xvzhou_Suning_Guangchang =37,
Jiangsu_Xvzhou_Suning_Guangchang_1=-37,
Shanxi_Baoji_Meixian_TianlongShangcheng = 38,
Hunan_Changde_Lixian_WandaGuangchang=39,
Jilin_Changchun_Beihu_WyueGuangchang=41,
Chongqing_Yuzhong_Hongyadong_Xiakexing=42,
Chongqing_Yuzhong_Hongyadong_Xiakexing_shiwan=-42,
Chengdu_Shuangliu_ShengfeiXuexiao =43,
Hebei_Hengshui_Xinji_WandaGuangchang = 44,
Hebei_Hengshui_Taocheng_WandaGuangchang=-44,
Ningxia_Yinchuan_Jinfeng_XinhualianGuangchang = 45,
Hunan_Zhuzhou_Wanda_Shennongcheng_Chaowanshe=46,
Anhui_Suzhou_Yueshan_Guchengshangyejie_Shinei=47,
Zhejiang_Wenzhou_Cangnan_Yintaicheng = 48,
Shandong_Jining_Shangchang_3=49,
Anhui_Manshan_XingyueGuangchang = 50,
Shandong_Weifang_Linqu_WandaGuangchang = 51,
Guangdong_Foushan_Haiyangguang = 52,
Jilin_Changchun_Chaoyang_OuyaMaichang=53,
Shandong_Weifang_Linqu_WandaGuangchang_Shinei=54,
Liaoning_Panjin_Shuangtaizi_Shuangtaicheng = 55,
Liaoning_Dalian_Pulandian_WandaGuangchang = 56,
}
public class GameManager : MonoBehaviour
{
public static GameManager Ins { get; private set; }
/// <summary>
/// 是否时间到了
/// </summary>
public bool isTimeEnd = true;
// json数据库
private JsonLiteDB DB;
// Enemy子弹数据
public Dictionary<int, BulletData> EnemyBulletDataDic = new Dictionary<int, BulletData>();
// Player子弹数据
public Dictionary<int, BulletData> PlayerBulletDataDic = new Dictionary<int, BulletData>();
public Dictionary<int, PropData> PropDataDic = new Dictionary<int, PropData>();
public Dictionary<int, BossPosData> BossPosDataDic = new Dictionary<int, BossPosData>();
public List<Enemy> curEnemyList = new List<Enemy>();
public Dictionary<int, EnemyData> EnemyDataDic = new Dictionary<int, EnemyData>();
[Header("道具")]
public GameObject EnergyPumpPre;
public GameObject gameStartPointPre;
public GameObject enemyDoorPre;
public GameObject point ;
[Header("敌人")]
public GameObject[] enemyPre;
public GameObject callEffectPre;//召唤特效
[Header("玩家")]
public GameObject playerPre;
public GameObject player;
public int gameTime=60*10;
public float curGameTime;
/// <summary>
/// 血包
/// </summary>
public GameObject BloodBagPre;
/// <summary>
/// 武器道具
/// </summary>
public GameObject weaponItemPre;
/// <summary>
/// 攻击BUFF
/// </summary>
public GameObject AtkBuffPre;
public GameObject deffBuffPre;
public bool GameStart = false;
public bool isGameEnd = false;
public int EnergyPumpTag = 0;
public float EnergyPumpFillAmount = 0;
public float curTime;
public float buffAtk = 0f;
public float buffDef = 0f;
public LoginInfo loginInfo = new LoginInfo();
public Enemy curBoss;
public int curLevel = 0;
//添加
[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>();
private void Awake()
{
}
public void Start()
{
Ins = this;
CreatePlayer();
LoginPanel.Show();
// 新增:初始化指引系统
InitializeGuideArrow();
if (gameStartPointPre != null)
{
point = Instantiate(gameStartPointPre);
point.SetActive(false); // 初始隐藏
}
#if !UNITY_EDITOR
PXR_Enterprise.InitEnterpriseService();
PXR_Enterprise.BindEnterpriseService();
TrueGearEffectManager.Ins.StartRequestTrueGear();
#endif
CoroutineTaskManager.Instance.WaitSecondTodo(ShowPlayerUI, 1.5f);
}
void Update()
{
// 更新指引箭头位置
UpdateGuideArrowPosition();
if (isGamePlay)
{
curGameTime+=Time.deltaTime;
}
}
public int GetNowTime()
{
return Mathf.RoundToInt(curGameTime);
}
/// <summary>
/// 登录
/// </summary>
public void Request(Action<HTTPRequest, HTTPResponse> cb = null)
{
string url = "http://www.pineappletech.cn/startcount";
HTTPRequest request = new HTTPRequest(new Uri(url), HTTPMethods.Post, (req, response) =>
{
if (response != null)
{
Debug.Log("收到数据 ->" + response.DataAsText);
}
cb?.Invoke(req, response);
});
loginInfo.deviceSn = GetPicoSn();
loginInfo.startAt = ConvertTimestampToDateTime(GetTimestamp()) + "";
loginInfo.shop = 0;
#if !UNITY_EDITOR && UNITY_ANDROID && PICO
loginInfo.shop = (int)GameInit.Ins.gamePlace;
if(GameInit.Ins.gamePlace== GamePlace.Company1FloorShiwai)
loginInfo.shop = 0;
if(GameInit.Ins.gamePlace== GamePlace.Liaoning_AnShan_Lishan_Dayuecheng)
loginInfo.shop = 1;
if(GameInit.Ins.gamePlace== GamePlace.Yangzhou_Hanjiang_TansuoZhongxin_wai)
loginInfo.shop = 5;
if(GameInit.Ins.gamePlace== GamePlace.Shandong_Jining_Shangchang_nei)
loginInfo.shop = 9;
if(GameInit.Ins.gamePlace== GamePlace.Shandong_Jinan_Huaiyin_ShengfutongShangmao_wai)
loginInfo.shop = 15;
if(GameInit.Ins.gamePlace== GamePlace.Nanjing_Qixia_Yaohuamen_Jindiguangchang_nei)
loginInfo.shop = 17;
if(GameInit.Ins.gamePlace== GamePlace.Anhui_Suzhou_Yueshan_Guchengshangyejie_2)
loginInfo.shop = 18;
if(GameInit.Ins.gamePlace== GamePlace.Wulanhaote_Wanda_Shangchang)
loginInfo.shop = 21;
if(GameInit.Ins.gamePlace== GamePlace.Hunan_Hengyang_Zhuhui_Dongzhoudao_nei)
loginInfo.shop = 24;
if(GameInit.Ins.gamePlace== GamePlace.Yunnan_Lincang_Linxiang_Hengji_Dixia)
loginInfo.shop = 25;
if(GameInit.Ins.gamePlace== GamePlace. Gansu_Jinchang_Jinchuan_Shijiguangchang_Shiwai)
loginInfo.shop = 28;
if(GameInit.Ins.gamePlace== GamePlace. Guangdong_Guangzhou_Yanghaiyan_Lihu)
loginInfo.shop = 31;
if(GameInit.Ins.gamePlace== GamePlace.Zhejiang_Hangzhou_Linping_Yintaicheng_Shinei)
loginInfo.shop = 32;
if(GameInit.Ins.gamePlace== GamePlace.Henan_Xinxiang_Wandaguangchang_Shinei)
loginInfo.shop = 33;
if(GameInit.Ins.gamePlace== GamePlace.Jiangsu_Xvzhou_Guolou_Oulebao_2)
loginInfo.shop = 36;
if(GameInit.Ins.gamePlace== GamePlace.Jiangsu_Xvzhou_Suning_Guangchang_1)
loginInfo.shop = 37;
if(GameInit.Ins.gamePlace== GamePlace.Chongqing_Yuzhong_Hongyadong_Xiakexing_shiwan)
loginInfo.shop = 42;
if(GameInit.Ins.gamePlace== GamePlace.Hebei_Hengshui_Taocheng_WandaGuangchang)
loginInfo.shop = 44;
#endif
//loginInfo.shop = 0;
loginInfo.gameId = 5;
string authJson = JsonUtility.ToJson(loginInfo);
Debug.Log("发送数据 -> " + authJson);
request.RawData = System.Text.Encoding.UTF8.GetBytes(authJson);
request.AddHeader("Content-Type", "application/json");
request.Send();
}
/// <summary>
/// 更新配置表
/// </summary>
public void InitData()
{
string text = "";
string text0 = Resources.Load<TextAsset>(string.Format("zh/{0}Data", GameInit.Ins.gamePlace)).text;
GetReaderJson(text0);
}
public static string ConvertTimestampToDateTime(long timestamp)
{
// Unix时间戳是从1970年1月1日00:00:00开始的秒数或毫秒数
// 这里以秒为单位如果时间戳是毫秒则除以1000
DateTime dateTime = DateTimeOffset.FromUnixTimeSeconds(timestamp).DateTime;
return dateTime.ToString("yyyy-MM-dd HH:mm:ss");
}
public void GetReaderJson(string text)
{
DB = new JsonLiteDB();
DB.Load(text);
// 读取Info表数据
TableReader infoReader = DB["EnemyData"].GetReader();
EnemyDataDic.Clear();
while (infoReader.Read())
{
EnemyData info = new EnemyData(infoReader);
EnemyDataDic.Add(info.Id, info);
}
// 敌人子弹数据
TableReader EnemyBulletReader = DB["EnemyBulletData"].GetReader();
EnemyBulletDataDic.Clear();
while (EnemyBulletReader.Read())
{
BulletData data = new BulletData(EnemyBulletReader);
EnemyBulletDataDic.Add(data.ID, data);
}
// 玩家子弹数据
TableReader PlayerBulletReader = DB["PlayerBulletData"].GetReader();
PlayerBulletDataDic.Clear();
while (PlayerBulletReader.Read())
{
BulletData data = new BulletData(PlayerBulletReader);
PlayerBulletDataDic.Add(data.ID, data);
}
// 道具表
TableReader PropReader = DB["PropData"].GetReader();
PropDataDic.Clear();
while (PropReader.Read())
{
PropData data = new PropData(PropReader);
PropDataDic.Add(data.PropId, data);
}
// Boss位置
TableReader BossPosReader = DB["BossPosData"].GetReader();
BossPosDataDic.Clear();
while (BossPosReader.Read())
{
BossPosData data = new BossPosData(BossPosReader);
BossPosDataDic.Add(data.ID, data);
}
}
/// <summary>
/// Get sn
/// </summary>
public string GetPicoSn()
{
string res = "UnityEditor";
#if !UNITY_EDITOR && UNITY_ANDROID && PICO
res = PXR_Enterprise.StateGetDeviceInfo(SystemInfoEnum.EQUIPMENT_SN);
#endif
return res;
}
public long GetTimestamp()
{
return (long)DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
}
public bool isGamePlay;
//AI介绍是否完成
private bool isAIIntroductionComplete = false;
// 游戏开始
public void GamePlay()
{
//TODO:添加一个玩家进入游戏AI进行游戏介绍介绍完后AI自动回到玩家左侧
//修改处创建AI角色
CreateAICharacter();
CleanupGuideArrow();
//isGamePlay = true;
//CreateBoss();
//PlayerUIMessage(0);
//CoroutineTaskManager.Instance.WaitSecondTodo(() =>
// AudioManager.Ins?.SoundPlay("bgm2", true), 10f);
//CoroutineTaskManager.Instance.WaitSecondTodo(() =>
// AudioManager.Ins?.SoundPlay("2.39BGM", true), 30f);
}
//修改处添加AI介绍完成后的游戏开始方法
public void StartGameAfterIntroduction()
{
isAIIntroductionComplete = true;
isGamePlay = true;
Debug.Log("AI介绍完成开始游戏正常流程");
//创建Boss
CreateBoss();
PlayerUIMessage(0);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
AudioManager.Ins?.SoundPlay("bgm2", true), 10f);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
AudioManager.Ins?.SoundPlay("2.39BGM", true), 30f);
}
//修改处添加创建AI角色的方法
private void CreateAICharacter()
{
//检查是否已经存在AI角色
if (aiCharacter != null)
{
Debug.Log("AI角色已经存在不再创建新的");
return;
}
if (aiCharacterPre != null)
{
Debug.Log("创建AI角色");
//在玩家前方创建AI角色
Vector3 spawnPosition = player.transform.position + player.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分配!");
}
}
private IEnumerator DelayedStartIntroduction(AIController aiController)
{
yield return new WaitForSeconds(0.1f); // 短暂延迟
aiController.StartIntroduction();
}
public void ShowPlayerUI()
{
OverlayUI.Ins.Cover("UI/PlayerUI", false);
}
public void ShowEndGameUI(bool isWin)
{
CurEnemyDie();
GameEndPanel.Show(isWin);
}
public GameObject CreateEnemy(int id, Vector3 pos, Vector3 eulerAngles, bool isBoss)
{
GameObject go = Instantiate(enemyPre[id], pos, Quaternion.identity);
go.transform.localEulerAngles = eulerAngles;
Enemy enemy = go.GetComponent<Enemy>();
enemy.Init();
if (isBoss)
{
curBoss = enemy;
}
else
{
curEnemyList.Add(enemy);
}
return go;
}
public GameObject CreateCallEnemyEffect(Vector3 pos)
{
GameObject go = Instantiate(callEffectPre, pos, quaternion.identity);
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
Destroy(go);
}, 3f);
return go;
}
void Destroy()
{
#if !UNITY_EDITOR
PXR_Enterprise.UnBindEnterpriseService();
#endif
}
public void CreateEnergyPump(Vector3 pos)
{
isGamePlay = false;
GameObject EnergyPump = Instantiate(EnergyPumpPre);
//EnergyPump.transform.position = pos;
EnergyPump.transform.position = new Vector3(2, 0, 2);
if (GameInit.Ins.gamePlace == GamePlace.Nanjing_Xianlin_WanDaMao)
{
EnergyPump.transform.position = new Vector3(-1.2f, 0, 1.5f);
}
if (GameInit.Ins.gamePlace == GamePlace.Nanjing_Yuhua_Wanxiang)
{
EnergyPump.transform.position = new Vector3(-3, 0, 2);
}
if (GameInit.Ins.gamePlace == GamePlace.Yangzhou_Hanjiang_Tansuozhongxin)
{
EnergyPump.transform.position = new Vector3(-1.2f, 0, 0f);
}
if (GameInit.Ins.gamePlace == GamePlace.Yangzhou_Hanjiang_TansuoZhongxin_wai)
{
EnergyPump.transform.position = new Vector3(0, 0, 2f);
}
if (GameInit.Ins.gamePlace == GamePlace.Zhejiang_Jinhua_KeJiGuan)
{
EnergyPump.transform.position = new Vector3(0, 0, 2f);
}
if (GameInit.Ins.gamePlace == GamePlace.Jilin_Tonghua_Liuhe)
{
EnergyPump.transform.position = new Vector3(0, 0, 2f);
}
if (GameInit.Ins.gamePlace == GamePlace.Guangzhou_Panyv_Zhanting)
{
EnergyPump.transform.position = new Vector3(0, 0, 2f);
}
if (GameInit.Ins.gamePlace == GamePlace.Zhejiang_Shaoxing_Shengzhou_WuyueGuangchang)
{
EnergyPump.transform.position = new Vector3(-0.23f, 0, 1.1f);
}
if (GameInit.Ins.gamePlace == GamePlace.ShanDong_Langfang_QingzhouTaihuacheng)
{
EnergyPump.transform.position = pos;
}
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Jishou_Qianzhou_Tianhong)
{
EnergyPump.transform.position = new Vector3(5f, 0, 1f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Jinan_Huaiyin_ShengfutongShangmao)
{
EnergyPump.transform.position = new Vector3(0.62f, 0, 1f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Heze_Yuncheng_Gefuli)
{
EnergyPump.transform.position = new Vector3(-10.9f, 0, 1.6f);
}
if (GameInit.Ins.gamePlace == GamePlace.Henan_Xinzheng_Shuanghudadao_Longhujinyicheng)
{
EnergyPump.transform.position = new Vector3(-2.08f, 0, -0.75f);
}
if (GameInit.Ins.gamePlace == GamePlace.Wulanhaote_Ouya_Shangchang)
{
EnergyPump.transform.position = new Vector3(-0.92f, 0, 9.5f);
}
if (GameInit.Ins.gamePlace == GamePlace.Wulanhaote_Wanda_Shangchang)
{
EnergyPump.transform.position = new Vector3(-8.47f, 0, 1.59f);
}
if (GameInit.Ins.gamePlace == GamePlace.Yunnan_Mile_Jinchen_Shidaiguangchang)
{
EnergyPump.transform.position = new Vector3(1.55f, 0, 1.7f);
}
if (GameInit.Ins.gamePlace == GamePlace.Xinjiang_Yili_Yining_Wanrong)
{
EnergyPump.transform.position = new Vector3(1.55f, 0, 1.24f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Hengyang_Zhuhui_Dongzhoudao)
{
EnergyPump.transform.position = new Vector3(-0.5f, 0, 3.5f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Hengyang_Zhuhui_Dongzhoudao_nei
|| GameInit.Ins.gamePlace == GamePlace.Jiangsu_Xvzhou_Fengxian_Wuyueguangchang
|| GameInit.Ins.gamePlace == GamePlace.Jiangsu_Xvzhou_Guolou_Oulebao_2
|| GameInit.Ins.gamePlace == GamePlace.Chongqing_Yuzhong_Hongyadong_Xiakexing_shiwan
)
{
EnergyPump.transform.position = new Vector3(-0.39f, 0, 3.83f);
}
if (GameInit.Ins.gamePlace == GamePlace.Yunnan_Lincang_Linxiang_Hengji)
{
EnergyPump.transform.position = new Vector3(1.8f, 0, 2.4f);
}
if (GameInit.Ins.gamePlace == GamePlace.Yunnan_Lincang_Linxiang_Hengji_Dixia)
{
EnergyPump.transform.position = new Vector3(0.03f, 0, 6.48f);
}
if (GameInit.Ins.gamePlace == GamePlace.Guangxi_Guilin_Gongcheng_Shijixincheng)
{
EnergyPump.transform.position = new Vector3(-5.41f, 0, 10.96f);
}
if (GameInit.Ins.gamePlace == GamePlace.Guangdong_Shenzhen_Guangming_Wanda)
{
EnergyPump.transform.position = new Vector3(-0.62f, 0, 1.07f);
}
if (GameInit.Ins.gamePlace == GamePlace.Liaoning_AnShan_Lishan_Dayuecheng)
{
EnergyPump.transform.position = new Vector3(-3.23f, 0, 5.47f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hebei_Tangshan_Qianan_Tianyuangu)
{
EnergyPump.transform.position = new Vector3(2f, 0, 2f);
}
if (GameInit.Ins.gamePlace == GamePlace.Zhejiang_Hangzhou_Linping_Yintaicheng)
{
EnergyPump.transform.position = new Vector3(1.12f, 0, 1.74f);
}
if (GameInit.Ins.gamePlace == GamePlace.Guangdong_Guangzhou_Yanghaiyan)
{
EnergyPump.transform.position = new Vector3(1.63f, 0, 1.3f);
}
if (GameInit.Ins.gamePlace == GamePlace.Gansu_Jinchang_Jinchuan_Shijiguangchang)
{
EnergyPump.transform.position = new Vector3(3f, 0, 7.32f);
}
if (GameInit.Ins.gamePlace == GamePlace.Gansu_Jinchang_Jinchuan_Shijiguangchang_Shiwai)
{
EnergyPump.transform.position = new Vector3(0.18f, 0, 0.59f);
}
if (GameInit.Ins.gamePlace == GamePlace.Henan_Xinxiang_Wandaguangchang)
{
EnergyPump.transform.position = new Vector3(3.29f, 0, -11.05f);
}
if (GameInit.Ins.gamePlace == GamePlace.Henan_Xinxiang_Wandaguangchang_Shinei)
{
EnergyPump.transform.position = new Vector3(-0.09f, 0, 2.775f);
}
if (GameInit.Ins.gamePlace == GamePlace.Zhejiang_Hangzhou_Linping_Yintaicheng_Shinei)
{
EnergyPump.transform.position = new Vector3(2f, 0, 6.23f);
}
if (GameInit.Ins.gamePlace == GamePlace.Nanjing_Pukou_Longhutianjie)
{
EnergyPump.transform.position = new Vector3(-0.37f, 0, 2.94f);
}
if (GameInit.Ins.gamePlace == GamePlace.Jiangsu_Xvzhou_Guolou_Oulebao || GameInit.Ins.gamePlace == GamePlace.Jiangsu_Xvzhou_Suning_Guangchang_1)
{
EnergyPump.transform.position = new Vector3(0f, 0, 2f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Changde_Lixian_WandaGuangchang)
{
EnergyPump.transform.position = new Vector3(-1.13f, 0, 2.65f);
}
if (GameInit.Ins.gamePlace == GamePlace.Chongqing_Yuzhong_Hongyadong_Xiakexing)
{
EnergyPump.transform.position = new Vector3(2f, 0, 28.22f);
}
if (GameInit.Ins.gamePlace == GamePlace.Chengdu_Shuangliu_ShengfeiXuexiao)
{
EnergyPump.transform.position = new Vector3(-1.33f, 0, 17.38f);
}
if (GameInit.Ins.gamePlace == GamePlace.Anhui_Suzhou_Yueshan_Guchengshangyejie_2)
{
EnergyPump.transform.position = new Vector3(2f, 0, 2f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hebei_Hengshui_Xinji_WandaGuangchang)
{
EnergyPump.transform.position = new Vector3(0.18f, 0, 5.09f);
}
if (GameInit.Ins.gamePlace == GamePlace.Ningxia_Yinchuan_Jinfeng_XinhualianGuangchang)
{
EnergyPump.transform.position = new Vector3(10.35f, 0, 4.33f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Zhuzhou_Wanda_Shennongcheng_Chaowanshe)
{
EnergyPump.transform.position = new Vector3(-0.09f, 0, 1.37f);
}
if (GameInit.Ins.gamePlace == GamePlace.Company1FloorShiwai)
{
EnergyPump.transform.position = new Vector3(-0.75f, 0, 22.38f);
}
if (GameInit.Ins.gamePlace == GamePlace.Anhui_Suzhou_Yueshan_Guchengshangyejie_Shinei)
{
EnergyPump.transform.position = new Vector3(-0.2f, 0, 3.23f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hebei_Hengshui_Taocheng_WandaGuangchang)
{
EnergyPump.transform.position = new Vector3(-5.47f, 0, 7.12f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Jining_Shangchang_3)
{
EnergyPump.transform.position = new Vector3(0.23f, 0, 4.29f);
}
if (GameInit.Ins.gamePlace == GamePlace.Anhui_Manshan_XingyueGuangchang)
{
EnergyPump.transform.position = new Vector3(0.08f, 0, 6.77f);
}
if (GameInit.Ins.gamePlace == GamePlace.Zhejiang_Wenzhou_Cangnan_Yintaicheng)
{
EnergyPump.transform.position = new Vector3(-0.12f, 0, 4.64f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Weifang_Linqu_WandaGuangchang)
{
EnergyPump.transform.position = new Vector3(-7.19f, 0, -5.37f);
}
if (GameInit.Ins.gamePlace == GamePlace.Jilin_Changchun_Chaoyang_OuyaMaichang)
{
EnergyPump.transform.position = new Vector3(-1.13f, 0, 2.01f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Weifang_Linqu_WandaGuangchang_Shinei)
{
EnergyPump.transform.position = new Vector3(2f, 0, 4.79f);
}
if (GameInit.Ins.gamePlace == GamePlace.Liaoning_Dalian_Pulandian_WandaGuangchang)
{
EnergyPump.transform.position = new Vector3(-0.74f, 0, 4.91f);
}
EnergyPumpTag++;
EnergyPump.GetComponent<EnergyPump>().Init(EnergyPumpTag);
}
public void PlayerUIMessage(int index)
{
EventDispatcher.TriggerEvent("PromptMessage", index);
}
public void CreateGameStartPoint()
{
GameStart = true;
isGamePlay = false;
point.SetActive(true );
if (GameInit.Ins.gamePlace == GamePlace.LiaoningAnShan)
{
point.transform.position = new Vector3(-2, 0, 2);
}
if (GameInit.Ins.gamePlace == GamePlace.ShanDong_Langfang_QingzhouTaihuacheng)
{
point.transform.position = new Vector3(7.46f, 0, 1.65f);
}
if (GameInit.Ins.gamePlace == GamePlace.Ningxia_Yinchuan_Jinfeng_XinhualianGuangchang)
{
point.transform.position = new Vector3(4.15f, 0, 2.3f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Weifang_Linqu_WandaGuangchang)
{
point.transform.position = new Vector3(-4.97f, 0, -4f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hebei_Hengshui_Taocheng_WandaGuangchang)
{
point.transform.position = new Vector3(-7.51f, 0, -2.78f);
}
else
{
point.transform.position = new Vector3(0.27f, 0, 2.84f);
}
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
StartGuide();
}, 0.5f);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
if (isGamePlay)
return;
Destroy(point.gameObject);
GamePlay();
}, 5f);
}
public GameObject CreateEnemyDoor(Vector3 pos, Vector3 angle, Vector3 scale)
{
GameObject crack = Instantiate(enemyDoorPre);
crack.transform.position = new Vector3(pos.x, pos.y, pos.z);
crack.transform.localEulerAngles = angle;
crack.transform.localScale = scale;
return crack;
}
/// <summary>
/// 创建攻击BUFF
/// </summary>
/// <param name="pos"></param>
public void CreateAtkBuff(Vector3 pos)
{
GameObject atkBuff = Instantiate(AtkBuffPre);
atkBuff.transform.position = new Vector3(pos.x, 0, pos.z);
// 山东廊坊青州泰华城场地的特殊逻辑:道具自动飞向(0,0,0)点
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Zhuzhou_Wanda_Shennongcheng_Chaowanshe)
{
StartCoroutine(FlyToCenterPoint(atkBuff, new Vector3(0.1f, 1, 1.68f), 2.0f));
}
}
/// <summary>
/// 创建防御BUFF
/// </summary>
/// <param name="pos"></param>
public void CreateDeeBuff(Vector3 pos)
{
GameObject deeBuff = Instantiate(deffBuffPre);
deeBuff.transform.position = new Vector3(pos.x, 0, pos.z);
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Zhuzhou_Wanda_Shennongcheng_Chaowanshe)
{
StartCoroutine(FlyToCenterPoint(deeBuff, new Vector3(0.1f, 1, 1.68f), 2.0f));
}
}
/// <summary>
/// 创建血包
/// </summary>
public void CreateBloodBag(Vector3 pos)
{
GameObject bloodBag = Instantiate(BloodBagPre);
bloodBag.transform.position = new Vector3(pos.x, 0, pos.z);
// 山东廊坊青州泰华城场地的特殊逻辑:道具自动飞向(0,0,0)点
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Zhuzhou_Wanda_Shennongcheng_Chaowanshe)
{
StartCoroutine(FlyToCenterPoint(bloodBag, new Vector3(0.1f, 1, 1.68f), 2.0f));
}
}
/// <summary>
/// 创建武器道具
/// </summary>
public void CreatePlayerWeapon(PlayerWeaponType type, Vector3 pos)
{
GameObject prop = Instantiate(weaponItemPre);
prop.GetComponent<WeaponProp>().Init(type);
prop.transform.position = new Vector3(pos.x, 1f, pos.z);
// 山东廊坊青州泰华城场地的特殊逻辑:道具自动飞向(0,0,0)点
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Zhuzhou_Wanda_Shennongcheng_Chaowanshe)
{
StartCoroutine(FlyToCenterPoint(prop, new Vector3(0.1f,1,1.68f), 2.0f));
}
}
/// <summary>
/// 道具飞向中心点(0,0,0)的协程
/// </summary>
/// <param name="prop">道具对象</param>
/// <param name="targetPosition">目标位置</param>
/// <param name="duration">飞行时间</param>
/// <returns></returns>
private IEnumerator FlyToCenterPoint(GameObject prop, Vector3 targetPosition, float duration)
{
if(prop == null) yield break;
// 获取道具的碰撞器组件,暂时禁用碰撞器避免飞行过程中被拾取
Collider propCollider = prop.GetComponent<Collider>();
if (propCollider != null)
{
propCollider.enabled = false;
}
Vector3 startPosition = prop.transform.position;
float elapsedTime = 0f;
// 添加一个向上的弧度,让飞行路径更自然
Vector3 controlPoint = (startPosition + targetPosition) * 0.5f + Vector3.up * 2f;
// 飞行过程中只更新位置,不改变旋转
while (elapsedTime < duration && prop != null)
{
elapsedTime += Time.deltaTime;
float t = elapsedTime / duration;
// 使用二次贝塞尔曲线计算位置
Vector3 position = CalculateBezierPoint(startPosition, controlPoint, targetPosition, t);
// 只更新位置不改变旋转让WeaponProp脚本的旋转动画自然运行
prop.transform.position = position;
yield return null;
}
// 飞行完成后重新启用碰撞器
if (prop != null && propCollider != null)
{
propCollider.enabled = true;
// 确保最终位置准确
prop.transform.position = targetPosition;
}
}
/// <summary>
/// 计算二次贝塞尔曲线上的点
/// </summary>
/// <param name="p0">起点</param>
/// <param name="p1">控制点</param>
/// <param name="p2">终点</param>
/// <param name="t">插值参数(0-1)</param>
/// <returns>曲线上的点</returns>
private Vector3 CalculateBezierPoint(Vector3 p0, Vector3 p1, Vector3 p2, float t)
{
float u = 1 - t;
float tt = t * t;
float uu = u * u;
Vector3 p = uu * p0; // (1-t)^2 * P0
p += 2 * u * t * p1; // 2(1-t)t * P1
p += tt * p2; // t^2 * P2
return p;
}
public bool isFirstGetWeapon;
public void EnemyDisGetWeapon(Vector3 pos)
{
bool isGet = Random.Range(0, 100) > 70;
if (!isGet) return;
int index = Random.Range(0, 100);
int id = 2;
if (index <= 10)
id = Random.Range(8, 10);
if (index is > 10 and <= 50)
id = Random.Range(5, 8);
if (index is > 50)
id = Random.Range(2, 5);
// 对于山东廊坊青州泰华城场地,掉落的位置改为(0,0,0)附近
Vector3 dropPosition = pos;
if (GameInit.Ins.gamePlace == GamePlace.Henan_Xinxiang_Wandaguangchang_Shinei)
{
// 在(0,0,0)点周围随机位置掉落
dropPosition = new Vector3(
Random.Range(1.5f, 2.5f),
1f,
Random.Range(1.5f, 2.5f)
);
}
CreatePlayerWeapon((PlayerWeaponType)id, dropPosition);
}
public void CurEnemyDie()
{
foreach (var enemy in curEnemyList)
{
if (enemy != null)
enemy.Dead();
}
curEnemyList.Clear();
}
public int GetCurEnemyListCount()
{
int count = 0;
foreach (var enemy in curEnemyList)
{
if (enemy != null)
count++;
}
return count;
}
public void CreatePlayer()
{
player = Instantiate(playerPre);
}
public bool IsAllBossPetDie()
{
foreach (var enemy in curEnemyList)
{
if (enemy != null && enemy.health > 0)
return false;
}
return true;
}
public void CurLevelWin(Vector3 pos)
{
curLevel++;
CurEnemyDie();
CreateEnergyPump(pos);
}
public void CreateBoss()
{
BossPosData data = BossPosDataDic[curLevel];
GameObject door = null;
if (curLevel != 0)
door = CreateEnemyDoor(data.DoorPos, data.DoorAng, Vector3.one * data.DoorScale);
switch (curLevel)
{
case 0:
CreateEnemy(0, data.BossPos, Vector3.zero, true);
break;
case 1:
//舰载机
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
door.GetComponent<EnemyDoor>().desTime = 6;
door.GetComponent<EnemyDoor>().InitData();
}, 1f);
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
CreateEnemy(2, data.BossPos, data.BossAng, true);
}, 3f);
break;
case 2:
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
door.GetComponent<EnemyDoor>().desTime = 10;
door.GetComponent<EnemyDoor>().InitData();
}, 1f);
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
CreateEnemy(3, data.BossPos, data.BossAng, true);
}, 3f);
break;
case 3:
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
door.GetComponent<EnemyDoor>().desTime = 10;
door.GetComponent<EnemyDoor>().InitData();
}, 1f);
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
CreateEnemy(5, data.BossPos, data.BossAng, true);
}, 3f);
break;
case 4:
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
door.GetComponent<EnemyDoor>().desTime = 6;
door.GetComponent<EnemyDoor>().InitData();
}, 1f);
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
CreateEnemy(7, data.BossPos, data.BossAng, true);
}, 1f);
break;
}
}
public void WinEndGame()
{
isGameEnd = true;
ShowEndGameUI(true);
GameInit.Ins.PlayAudio("1.17", GameInit.Ins.self.transform, true);
AudioManager.Ins?.SoundPlay("bgm4", true);
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
Debug.Log("游戏结束5秒后退出");
Application.Quit();
}, 60f);
////修改处销毁AI角色
if (aiCharacter != null)
{
//取消注册事件
AIController aiController = aiCharacter.GetComponent<AIController>();
if (aiController != null)
{
aiController.OnIntroductionComplete -= StartGameAfterIntroduction;
}
Destroy(aiCharacter);
}
}
public void LoseEndGame()
{
ShowEndGameUI(false);
if (curBoss != null)
{
Destroy(curBoss.gameObject);
}
GameInit.Ins.self.IsAlive = false;
GameInit.Ins.self.End();
isGameEnd = true;
CurEnemyDie();
AudioManager.Ins?.SoundPlay("bgm4", true);
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
Debug.Log("游戏结束5秒后退出");
Application.Quit();
}, 60f);
//修改处销毁AI角色
if (aiCharacter != null)
{
//取消注册事件
AIController aiController = aiCharacter.GetComponent<AIController>();
if (aiController != null)
{
aiController.OnIntroductionComplete -= StartGameAfterIntroduction;
}
Destroy(aiCharacter);
}
}
#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 (GameInit.Ins.self != null)
{
lastPlayerPosition = GameInit.Ins.self.transform.position;
}
}
/// <summary>
/// 更新指引箭头位置(实时跟随玩家移动)
/// </summary>
// 修改 UpdateGuideArrowPosition 方法
private void UpdateGuideArrowPosition()
{
if (!isGuideArrowActive || point == null || GameInit.Ins.self == null)
return;
// 获取玩家当前位置
Vector3 currentPlayerPosition = GameInit.Ins.self.transform.position;
// 检查冷却时间
if (Time.time - lastPathUpdateTime < updatePathCooldown)
return;
// 检查玩家是否移动了足够远的距离
float distanceMoved = Vector3.Distance(currentPlayerPosition, lastPlayerPosition);
if (distanceMoved > updatePathThreshold)
{
// 获取门的位置
Vector3 doorPosition = point.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 && point != null && GameInit.Ins.self != null)
{
guideArrowComponent.ShowPath();
isGuideArrowActive = true;
// 初始化路径
Vector3 playerPosition = GameInit.Ins.self.transform.position;
Vector3 doorPosition = point.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 (point != null && GameInit.Ins.self != null)
{
ShowGuideArrow();
// 初始化路径
Vector3 playerPosition = GameInit.Ins.self.transform.position;
Vector3 doorPosition = point.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
}