Files
XMen/Assets/Scripts/GameManager.cs
2026-01-14 18:17:11 +08:00

2534 lines
82 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 System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using BestHTTP;
using BestHTTP.JSON;
using DragonLi.Core;
using DragonLi.Frame;
using JetBrains.Annotations;
using MechanicalAge;
using Mirror;
using Unity.Mathematics;
using Unity.VisualScripting;
using Unity.XR.PXR;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR.Interaction.Toolkit;
using XPlugin.Data.Json;
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
{
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,
Anhui_Wuhu_Guanwei = 8,
Shandong_Jining_Wanhuicheng_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,
Anhui_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_shenzheng_Guangming_Shijiguangchang=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,
}
public class GameManager : NetworkBehaviour
{
public static GameManager Ins { get; private set; }
private string Version = "2.1.9";
//private string Author = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiJhMGE4OTE0ZjRjODE0NTNiYWZmMTdiODFmYjBjNmU5YSIsInVzZXIiOiJkZXZpY2UtMDAxIiwic3ViIjoiZGV2aWNlLTAwMSJ9.krKxq1NQYUTlqAMcb0FwHlsI17TLos08OjqUIi_5zmK8sh-LA6hL2awyXZpblrE-LYuWh0g8qA8DjRcjP74hOQ";
private string Author = "";
public string HttpServerUrl = "";
[SyncVar]
public List<Transform> players;
//[NonSerialized]
[SyncVar]
public List<Transform> enemyList = new List<Transform>();
/// <summary>
/// 护盾
/// </summary>
private Dictionary<int, Shield> Shields = new Dictionary<int, Shield>();
private int ShieldId = 0;
[SyncVar]
public int AllEnemyAmount;
/// <summary>
/// 在倒计时之内
/// </summary>
[SyncVar]
public bool isWithinTime = true;
[SyncVar]
// 游玩结束时间
public long vistEnd = 0;
//总共游玩时间
// 总游玩时长
public int vistAllTime;
public float curGameTime = 0;
// json数据库
private JsonLiteDB DB;
// 怪物详情
public Dictionary<int, EnemyInfo> EnemyDescInfos = new Dictionary<int, EnemyInfo>();
// 武器详情
public Dictionary<int, WeaponData> WeaponDescInfos = new Dictionary<int, WeaponData>();
// 道具表
public Dictionary<int, PropInfo> PropDescInfos = new Dictionary<int, PropInfo>();
// 关卡难度
public Dictionary<int, DifficultyInfo> DifficultyescInfos = new Dictionary<int, DifficultyInfo>();
// 称号表
public Dictionary<int, TitleInfo> TitleDescInfos = new Dictionary<int, TitleInfo>();
// 子弹详情
public Dictionary<int, BulletInfo> BulletDescInfos = new Dictionary<int, BulletInfo>();
//剧情
public Dictionary<int, StoryInfo> StoryDescInfos = new Dictionary<int, StoryInfo>();
public Dictionary<int, TitleConditionInfo> titleConditionDescInfos = new Dictionary<int, TitleConditionInfo>();
public Dictionary<int, StoryInfo1> GameStoryInfos = new Dictionary<int, StoryInfo1>();
//临时对象
public Dictionary<int, TempInfo> tempDescInfos = new Dictionary<int, TempInfo>();
// 保存传送门
public List<GameObject> cracksList = new List<GameObject>();
[Header("预制体")]
public GameObject wallPre;
public GameObject doorPre;
public GameObject EnergyPumpPre;
public GameObject gameStartPointPre;
[Header("怪物预制体")]
public GameObject RobotGuardianPre;
public GameObject CrackPre;
public GameObject QYPre;
public GameObject EskyPre;
public GameObject TurretPre;
public GameObject SpiderPre;
public GameObject EliteSpiderPre;
public GameObject RobotMechPre;
public GameObject EskyClonePre;
public GameObject SpiderClonePre;
public GameObject ShadowPre;
public GameObject ShadowCastPre;
public GameObject BossPre;
public GameObject MachineHeartPre;
public GameObject HudPre;
public GameObject radarPoint;
//闪电特效
public GameObject LightningPre;
/// <summary>
/// 护盾
/// </summary>
public GameObject ShieldPre;
/// <summary>
/// 血包
/// </summary>
public GameObject BloodBagPre;
/// <summary>
/// 武器道具
/// </summary>
public GameObject WeaponPropPre;
/// <summary>
/// 攻击BUFF
/// </summary>
public GameObject AtkBuffPre;
public GameObject deffBuffPre;
[Header("特效")]
public GameObject RockfallPre;
public GameObject BOSS_lightPre;
//激光蓄力
public AudioClip xuliEffect;
//激光射线
public AudioClip LayEffect;
//切换枪支
public AudioClip SwitchGunEffect;
public Collider StartPoint;
public GameObject Landmarks;
[SyncVar]
public bool GameStart = false;
public bool isDoorDie;
//怪物index
[NonSerialized]
[SyncVar]
public int EnemyAmount = 0;
[SyncVar]
public int SummonAmount = 0;
[NonSerialized]
[SyncVar]
public float PumpsMaxAmount = 5;
public ScriptableObject scriptMachineGraph;
private Shadow NowShadow;
[SyncVar]
public bool isGameEnd = false;
[SyncVar]
public int EnergyPumpTag = 0;
[SyncVar]
public float EnergyPumpFillAmount = 0;
public float buffAtk = 0f;
public float buffDef = 0f;
public AuthInfo authInfo = new AuthInfo();
[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>();
//关闭手柄射线
[ClientRpc]
public void CloseLay()
{
GameInit.Ins.MRLeftControl.GetComponent<XRRayInteractor>().enabled = false;
GameInit.Ins.MRRightControl.GetComponent<XRRayInteractor>().enabled = false;
}
private void Awake()
{
AllEnemyAmount = -1;
vistAllTime = (int)(60 * 15f);
}
public void Start()
{
Ins = this;
Landmarks = GameInit.Ins.Landmarks;
isDoorDie = false;
vistEnd = (long)(DateTime.Now.Subtract(new DateTime(1970, 1, 1))).TotalSeconds + vistAllTime;
if (isClient)
{
// 鉴权
AuthorPanel.Show();
}
// 新增:初始化指引系统
InitializeGuideArrow();
#if !UNITY_EDITOR
// PXR_Enterprise.InitEnterpriseService();
// PXR_Enterprise.BindEnterpriseService();
#endif
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
CustomEvent.Trigger(GameInit.Ins.Event.gameObject, "GameManager", transform);
if (isClient)
{
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
// 创建头盔
CustomEvent.Trigger(GameInit.Ins.Event.gameObject, "StartGame");
GenerateHUD();
}, 0.5f);
}
}, 1.0f);
}
public void Update()
{
// 更新指引箭头位置
UpdateGuideArrowPosition();
if (GameStart)
{
curGameTime+= Time.deltaTime;
}
// if (isServer && enemyList.Count > 0)
// {
// List<Vector3> vectors = new List<Vector3>();
// for (int i = 0; i < enemyList.Count; i++)
// {
// if (enemyList[i] != null)
// {
// vectors.Add(enemyList[i].position);
// }
// }
// EnemysPosRpc(vectors);
// }
}
/// <summary>
/// 鉴权
/// </summary>
public void RequestAuth(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);
});
//request.AddHeader("Authorization", Author);
authInfo.deviceSn = GetSn();
authInfo.startAt = ConvertTimestampToDateTime(GetTimestamp()) + "";
//authInfo.paid = 2;
//authInfo.uuid = GetSn() + GetTimestamp();
authInfo.shop = 0;
#if !UNITY_EDITOR && UNITY_ANDROID && PICO
authInfo.shop = (int)GameInit.Ins.gamePlace;
if(GameInit.Ins.gamePlace== GamePlace.Liaoning_AnShan_Lishan_Dayuecheng)
authInfo.shop = 1;
if(GameInit.Ins.gamePlace== GamePlace.Yangzhou_Hanjiang_TansuoZhongxin_wai)
authInfo.shop = 5;
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Jining_Wanhuicheng_nei)
authInfo.shop = 9;
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Jinan_Huaiyin_ShengfutongShangmao_wai)
authInfo.shop = 15;
if (GameInit.Ins.gamePlace == GamePlace.Nanjing_Qixia_Yaohuamen_Jindiguangchang_nei)
authInfo.shop = 17;
if (GameInit.Ins.gamePlace == GamePlace.Anhui_Suzhou_Yueshan_Guchengshangyejie_2)
authInfo.shop = 18;
if (GameInit.Ins.gamePlace == GamePlace.Wulanhaote_Wanda_Shangchang)
authInfo.shop = 21;
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Hengyang_Zhuhui_Dongzhoudao_nei)
authInfo.shop = 24;
if (GameInit.Ins.gamePlace == GamePlace.Yunnan_Lincang_Linxiang_Hengji_Dixia)
authInfo.shop = 25;
if (GameInit.Ins.gamePlace == GamePlace.Gansu_Jinchang_Jinchuan_Shijiguangchang_Shiwai)
authInfo.shop = 28;
if (GameInit.Ins.gamePlace == GamePlace.Guangdong_Guangzhou_Yanghaiyan_Lihu)
authInfo.shop = 31;
if (GameInit.Ins.gamePlace == GamePlace.Zhejiang_Hangzhou_Linping_Yintaicheng_Shinei)
authInfo.shop = 32;
if (GameInit.Ins.gamePlace == GamePlace.Henan_Xinxiang_Wandaguangchang_Shinei)
authInfo.shop = 33;
if (GameInit.Ins.gamePlace == GamePlace.Jiangsu_Xvzhou_Guolou_Oulebao_2)
authInfo.shop = 36;
if (GameInit.Ins.gamePlace == GamePlace.Jiangsu_Xvzhou_Suning_Guangchang_1)
authInfo.shop = 37;
if (GameInit.Ins.gamePlace == GamePlace.Chongqing_Yuzhong_Hongyadong_Xiakexing_shiwan)
authInfo.shop = 42;
if (GameInit.Ins.gamePlace == GamePlace. Hebei_Hengshui_Taocheng_WandaGuangchang )
authInfo.shop = 44;
if (GameInit.Ins.gamePlace == GamePlace.Company1FloorShiwai)
authInfo.shop = 0;
#endif
//authInfo.shop = 0;
authInfo.gameId = (int)GameInit.Ins.gameId;
string authJson = JsonUtility.ToJson(authInfo);
Debug.Log("发送数据 -> " + authJson);
request.RawData = System.Text.Encoding.UTF8.GetBytes(authJson);
request.AddHeader("Content-Type", "application/json");
request.Send();
}
[ClientRpc]
public void GameEnd()
{
// 取消注册事件
if (aiCharacter != null)
{
AIController aiController = aiCharacter.GetComponent<AIController>();
if (aiController != null)
{
aiController.OnIntroductionComplete -= StartGameAfterIntrodiction;
}
NetworkServer.Destroy(aiCharacter);
}
Debug.Log("游戏结束60秒后退出");
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
Debug.Log("正在退出游戏...");
Application.Quit();
}, 60f);
//RequestNotifyEnd();
}
public int GetNowTime()
{
return Mathf.FloorToInt(curGameTime);
}
/// <summary>
/// 通知服务器已开始游戏
/// </summary>
// public void RequestNotifyStart(Action cb = null)
// {
// string url = HttpServerUrl + "/api/record";
// HTTPRequest request = new HTTPRequest(new Uri(url), HTTPMethods.Put, (req, response) =>
// {
// if (response != null)
// {
// Debug.Log("收到数据 ->" + response.DataAsText);
// cb?.Invoke();
// }
// });
// request.AddHeader("Authorization", Author);
// authInfo.paid = 1;
// string authJson = JsonUtility.ToJson(authInfo);
// Debug.Log("发送数据 -> " + authJson);
// request.RawData = System.Text.Encoding.UTF8.GetBytes(authJson);
// request.AddHeader("Content-Type", "application/json");
// request.Send();
// }
/// <summary>
/// 通知服务器游戏结束
/// </summary>
public void RequestNotifyEnd(Action<HTTPRequest, HTTPResponse> cb = null)
{
// string url = HttpServerUrl + "/api/record";
// HTTPRequest request = new HTTPRequest(new Uri(url), HTTPMethods.Put, (req, response) =>
// {
// if (response != null)
// {
// Debug.Log("收到数据 ->" + response.DataAsText);
// cb?.Invoke(req, response);
// }
// });
// request.AddHeader("Authorization", Author);
// authInfo.endAt = ConvertTimestampToDateTime(GetTimestamp()) + "";
// authInfo.dur = (int)(((long)(DateTime.Now.Subtract(new DateTime(1970, 1, 1))).TotalSeconds) - (vistEnd - vistAllTime));
// Debug.Log("dur---:" + authInfo.dur);
// string authJson = JsonUtility.ToJson(authInfo);
// Debug.Log("发送数据 -> " + authJson);
// request.RawData = System.Text.Encoding.UTF8.GetBytes(authJson);
// request.AddHeader("Content-Type", "application/json");
// request.Send();
}
/// <summary>
/// 游戏开始
/// </summary>
/// <summary>
/// 请求配置
/// </summary>
public void RequestConf(Action<HTTPRequest, HTTPResponse> cb = null)
{
string url = HttpServerUrl + "/api/config/info?deviceSn={0}&gameType=1&version={1}";
url = string.Format(url, GetSn(), Version);
Debug.Log("发送数据 -> " + url);
HTTPRequest request = new HTTPRequest(new Uri(url), HTTPMethods.Get, (req, response) =>
{
cb?.Invoke(req, response);
});
request.AddHeader("Authorization", Author);
request.Send();
}
/// <summary>
/// 更新配置表
/// </summary>
public void UpdateConf()
{
string text = "";
string text0 = Resources.Load<TextAsset>(string.Format("zh/{0}Data", GameInit.Ins.gamePlace)).text;
ParseGameJson(text0);
// switch (gamePlace)
// {
// case GamePlace.HongYueCheng:
// RequestConf((req, response) =>
// {
// if (response != null)
// {
// Debug.Log("收到数据 -> " + response.DataAsText);
// JObject jObj = JObject.OptParse(response.DataAsText);
// text = jObj["data"]["data"].AsString();
// int status = jObj["status"].AsInt();
// if (status >= 200 && status < 300 && text != "")
// {
// ParseGameJson(text);
// }
// else
// {
// string text0 = Resources.Load<TextAsset>("MechanicalAgeDataHongYuecheng").text;
// ParseGameJson(text0);
// }
// }
// else
// {
//
// string text0 = Resources.Load<TextAsset>("MechanicalAgeDataHongYuecheng").text;
// ParseGameJson(text0);
// }
// });
// break;
// case GamePlace.BeiJing:
// text = Resources.Load<TextAsset>("MechanicalAgeDataBeiJing").text;
// ParseGameJson(text);
// break;
// case GamePlace.YuHua:
// text = Resources.Load<TextAsset>("MechanicalAgeDataYuHua").text;
// ParseGameJson(text);
// break;
// case GamePlace.ZhengHong:
// text = Resources.Load<TextAsset>("MechanicalAgeDataZhengHong").text;
// ParseGameJson(text);
// break;
// case GamePlace.SuZhouAoti:
// text = Resources.Load<TextAsset>("MechanicalAgeDataAoti").text;
// ParseGameJson(text);
// break;
// case GamePlace.JNWD_F2:
// text = Resources.Load<TextAsset>("JNWD").text;
// ParseGameJson(text);
// break;
// case GamePlace.JNWD_F1:
// text = Resources.Load<TextAsset>("JNWD_F1").text;
// ParseGameJson(text);
// break;
//
// }
}
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");
}
/// <summary>
/// 解析游戏使用的json
/// </summary>
public void ParseGameJson(string text)
{
DB = new JsonLiteDB();
DB.Load(text);
// 读取Info表数据
TableReader infoReader = DB["EnemyInfo"].GetReader();
Dictionary<int, EnemyInfo> EnemyDescInfosC = new Dictionary<int, EnemyInfo>();
while (infoReader.Read())
{
EnemyInfo info = new EnemyInfo(infoReader);
EnemyDescInfosC.Add(info.Id, info);
}
EnemyDescInfos = EnemyDescInfosC;
// 读取武器表数据
TableReader weaponReader = DB["WeaponInfo"].GetReader();
Dictionary<int, WeaponData> WeaponDescInfosC = new Dictionary<int, WeaponData>();
while (weaponReader.Read())
{
WeaponData info = new WeaponData(weaponReader);
WeaponDescInfosC.Add(info.Id, info);
}
WeaponDescInfos = WeaponDescInfosC;
// 解析子弹详情表
TableReader BulletReader = DB["BulletInfo"].GetReader();
Dictionary<int, BulletInfo> BulletDescInfosC = new Dictionary<int, BulletInfo>();
while (BulletReader.Read())
{
BulletInfo info = new BulletInfo(BulletReader);
BulletDescInfosC.Add(info.ID, info);
}
BulletDescInfos = BulletDescInfosC;
// 道具表
TableReader PropReader = DB["PropInfo"].GetReader();
Dictionary<int, PropInfo> PropDescInfosC = new Dictionary<int, PropInfo>();
while (PropReader.Read())
{
PropInfo info = new PropInfo(PropReader);
PropDescInfosC.Add(info.PropId, info);
}
PropDescInfos = PropDescInfosC;
// 关卡难度表
TableReader DifficultyReader = DB["DifficultyInfo"].GetReader();
Dictionary<int, DifficultyInfo> DifficultyescInfosC = new Dictionary<int, DifficultyInfo>();
while (DifficultyReader.Read())
{
DifficultyInfo info = new DifficultyInfo(DifficultyReader);
DifficultyescInfosC.Add(info.Id, info);
}
DifficultyescInfos = DifficultyescInfosC;
// 称号列表
TableReader TitleDescInfosReader = DB["TitleInfo"].GetReader();
Dictionary<int, TitleInfo> TitleDescInfosC = new Dictionary<int, TitleInfo>();
while (TitleDescInfosReader.Read())
{
TitleInfo info = new TitleInfo(TitleDescInfosReader);
TitleDescInfosC.Add(info.Id, info);
}
TitleDescInfos = TitleDescInfosC;
TableReader storyReader = DB["Story"].GetReader();
while (storyReader.Read())
{
StoryInfo info = new StoryInfo(storyReader);
StoryDescInfos.Add(info.Id, info);
}
TableReader titleConditionInfo = DB["TitleConditionInfo"].GetReader();
while (titleConditionInfo.Read())
{
TitleConditionInfo info = new TitleConditionInfo(titleConditionInfo);
titleConditionDescInfos.Add(info.Id, info);
}
TableReader tempReader = DB["TempInfo"].GetReader();
while (tempReader.Read())
{
TempInfo info = new TempInfo(tempReader);
tempDescInfos.Add(info.Id, info);
}
}
/// <summary>
/// 获取sn号
/// </summary>
public string GetSn()
{
string res = "UnityEditor";
// string res = "PA8E10MGH7210380D";
#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;
}
[ClientRpc]
public void EnemysPosRpc(List<Vector3> vectors)
{
EventDispatcher.TriggerEvent("EnemyList", vectors);
}
[ClientRpc]
public void ShowWinUI(float time)
{
if (GameInit.Ins.Win)
GameInit.Ins.Win.SetActive(true);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
GameInit.Ins.Win.SetActive(false);
}, time);
}
public void PlaySwitchGunSound()
{
GameInit.Ins.bgm.PlayOneShot(SwitchGunEffect);
}
[ClientRpc]
public void ShowJxsdLogo()
{
GameInit.Ins.JxsdLogo.SetActive(true);
}
[ClientRpc]
public void PlayOneShotAudioTrriger(string name)
{
EventDispatcher.TriggerEvent("PlayOnShotAudio", "Audio/" + name);
//
//CustomEvent.Trigger(GameInit.Ins.Event.gameObject, "PlayOnShotAudio");
}
public void PlayAudioTrriger(string name)
{
EventDispatcher.TriggerEvent("PlayAudio", "Audio/Background" + name);
}
//---------------播放音乐-------------------
[ClientRpc]
public void PlayXuliSound()
{
GameInit.Ins.bgm.PlayOneShot(xuliEffect);
}
[ClientRpc]
public void StopSound()
{
GameInit.Ins.bgm.Stop();
}
[Header("AI角色")]
public GameObject aiCharacterPre;//AI角色预制体
public GameObject aiCharacter;//AI角色实例
// 游戏开始
[Server]
public void GameOK()
{
CleanupGuideArrow();
//修改处创建AI角色不立即开始游戏
CreateAICharacter();
//GameStart = true;
//关闭射线
CloseLay();
StartPointClose();
}
//修改处:添加字段
[SyncVar(hook = nameof(OnAIIntroductionComoleteChanged))]
public bool isAIIntroductionComplete = false;//AI介绍是否完成
//修改处添加hook方法
private void OnAIIntroductionComoleteChanged(bool oldValue, bool newValue)
{
isAIIntroductionComplete = newValue;
Debug.Log($"AI介绍完成状态变化{oldValue}->{newValue}");
}
//添加AI 介绍完成后的游戏开始方法
[Server]
public void StartGameAfterIntrodiction()
{
isAIIntroductionComplete = true;
GameStart = true;
Debug.Log("AI介绍完成开始游戏正常流程");
Debug.LogError("倒计时时间:"+vistAllTime);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
GameEnd();
isGameEnd = true;
StoryManager.Ins.ShowResultPlane();
ClearAllEnemy();
if(_energyPump != null)
NetworkServer.Destroy(_energyPump.gameObject);
}, vistAllTime);
//通知所有客户端已经完成
RpcSetAIIntroductionComplete(true);
}
[ClientRpc]
public void RpcSetAIIntroductionComplete(bool complete)
{
isAIIntroductionComplete = complete;
}
//添加创建AI角色的方法
[Server]
private void CreateAICharacter()
{
//检查是否已经存在AI角色
if (aiCharacter != null)
{
Debug.LogError("AI角色已经存在不再创建新的");
return;
}
if (aiCharacterPre != null)
{
Debug.Log("创建AI角色");
//获取第一个玩家
Transform firstPlayer = GetPlayer(0);
if (firstPlayer == null)
{
Debug.LogError("找不到玩家无法创建AI角色");
return;
}
//在玩家前方创建AI角色
Vector3 spawnPoisiton = firstPlayer.position + firstPlayer.forward * 3f;
spawnPoisiton.y = 0f; // 固定Y坐标为0
aiCharacter = Instantiate(aiCharacterPre, spawnPoisiton, Quaternion.identity);
NetworkServer.Spawn(aiCharacter);
//获取AIController并启动开场白
AIController aiController = aiCharacter.GetComponent<AIController>();
if (aiCharacter != null)
{
//注册AI介绍完成回调
aiController.OnIntroductionComplete += StartGameAfterIntrodiction;
//添加延迟,确保所有组件已经完成初始化
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 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);
}
public GameObject GenerateHUD()
{
OverlayUIManager.Ins.Cover("UI/HUD", false);
//return Instantiate(HudPre, new Vector3(2000, 0, 0), quaternion.identity);
return null;
}
[ClientRpc]
public void ShowLandmark(int index1, int index2)
{
return;
GameObject landmark1 = Landmarks.transform.GetChild(index1).gameObject;
GameObject landmark2 = Landmarks.transform.GetChild(index2).gameObject;
if (index2 == 0)
{
landmark1.SetActive(true);
}
else
{
landmark1.SetActive(false);
landmark2.SetActive(true);
}
}
[ClientRpc]
public void StartPointClose()
{
if (StartPoint)
{
StartPoint.gameObject.SetActive(false);
}
}
public void CreateItemDrop(int enemyIndex, Vector3 pos)
{
if(isGameEnd)
return;
int storyId = StoryManager.Ins.currentStoryIndex - 1;
StoryInfo storyInfo = StoryDescInfos[storyId];
//当前怪物的序号 索引从开始需要加1
int currentIndex = (enemyIndex + 1);
if (currentIndex % storyInfo.ItemRule == 0)
{
if (storyInfo.ALLEnemyAmount[StoryManager.Ins.gameDifficulty] > 1)
{
int counter = Mathf.FloorToInt(currentIndex / storyInfo.ItemRule);
int itemIndex = (counter - 1) % storyInfo.ItemDrop.Length; // 使用取余操作符确保循环索引
Debug.Log($"当前怪物index:{enemyIndex}当前物品index:{itemIndex}当前物品ID:{storyInfo.ItemDrop[itemIndex]}");
if (storyInfo.BulletAmount.ContainsKey(storyInfo.ItemDrop[itemIndex]))
{
int amount = storyInfo.BulletAmount[storyInfo.ItemDrop[itemIndex]];
Debug.Log("amount" + amount);
CreateItemProp(storyInfo.ItemDrop[itemIndex], pos, amount);
}
else
{
CreateItemProp(storyInfo.ItemDrop[itemIndex], pos);
}
}
else
{
for (int i = 0; i < storyInfo.ItemDrop.Length; i++)
{
int key = storyInfo.ItemDrop[i];
if (storyInfo.BulletAmount.ContainsKey(key))
{
int amount = storyInfo.BulletAmount[key];
CreateItemProp(storyInfo.ItemDrop[i], pos + new Vector3(i + 0.5f, 0, 0), amount);
// Debug.Log("当前子弹数量为:" + amount);
}
else
{
CreateItemProp(storyInfo.ItemDrop[i], pos + new Vector3(i + 0.5f, 0, 0));
}
}
}
}
}
// // 解锁所有人的超级武器
// [Server]
// public void UnLockAllSuperGunServer()
// {
// Debug.Log("解锁所有人的超级武器");
// UnLockSuperGun();
// }
// [Server]
// public void DestoryALLWeapon()
// {
// SwitchNULL();
// }
// [ClientRpc]
// public void SwitchNULL()
// {
// GameInit.Ins.self.SwitchNULL();
// }
// [ClientRpc]
// public void UnLockSuperGun()
// {
// GameInit.Ins.self.UnLockSuperGun();
// }
// 给所有客户端播放音乐
[ClientRpc]
public void PlayeBGM2AllClient()
{
CustomEvent.Trigger(GameInit.Ins.Event.gameObject, "PlayBGM2");
}
[ClientRpc]
public void PlayerBGM()
{
CustomEvent.Trigger(GameInit.Ins.Event.gameObject, "PlayBGM2");
}
public void WaitDestoryObject(GameObject obj, float time)
{
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
NetworkServer.Destroy(obj);
}, time);
}
void Destroy()
{
#if !UNITY_EDITOR
//PXR_Enterprise.UnBindEnterpriseService();
#endif
}
[Server]
public void InitEnemyAmount()
{
EnemyAmount = 0;
enemyList.Clear();
}
[Server]
public void ClearAllEnemy()
{
for (int i = 0; i < enemyList.Count; i++)
{
if (enemyList[i] != null)
{
enemyList[i].GetComponent<IDamagable>().ApplyDamage(100000000000, true, null);
}
}
EnemyAmount = 0;
enemyList.Clear();
}
public Transform RandomFloundEnemy(XAgent.BodyPoint point)
{
List<Transform> notNullElements = enemyList.Where(element => element != null).ToList();
Transform res = null;
if (notNullElements.Count > 0)
{
Transform enemy = notNullElements[Random.Range(0, notNullElements.Count)];
if (enemy != null)
{
res = enemy.GetComponent<XAgent>().FindBody(point);
}
}
return res;
}
public List<Transform> GetRangeEnemys(Vector3 Pos, float radius)
{
Collider[] colliders;
colliders = new Collider[15];
int colliderCount = Physics.OverlapSphereNonAlloc(Pos, radius, colliders);
List<Transform> enemys = new List<Transform>();
for (int i = 0; i < colliderCount; i++)
{
if (colliders[i].CompareTag("Enemy"))
{
enemys.Add(colliders[i].transform);
}
}
return enemys;
}
public List<Transform> GetRangePlayers(Vector3 Pos, float radius)
{
Collider[] colliders;
colliders = new Collider[15];
int colliderCount = Physics.OverlapSphereNonAlloc(Pos, radius, colliders);
List<Transform> players = new List<Transform>();
for (int i = 0; i < colliderCount; i++)
{
if (colliders[i].CompareTag("Player"))
{
players.Add(colliders[i].transform);
}
}
return players;
}
public Transform[] FoundNearestEnemy(int amount, Transform self)
{
if (enemyList.Count <= 0) return null;
var sortedEnemies = enemyList.OrderBy(e => Vector3.Distance(self.position, e.position));
if (enemyList.Count >= amount)
{
return sortedEnemies.Take(amount).ToArray();
}
else
{
return sortedEnemies.Take(enemyList.Count).ToArray();
}
}
private EnergyPump _energyPump;
//创建能量泵
[Server]
public void GenerateEnergyPump(Vector3 pos)
{
if(isGameEnd)
return;
GameObject EnergyPump = Instantiate(EnergyPumpPre);
NetworkServer.Spawn(EnergyPump);
//EnergyPump.transform.position = pos;
EnergyPump.transform.position = pos;
if (GameInit.Ins.gamePlace == GamePlace.Company1Floor)
{
EnergyPump.transform.position = new Vector3(-3f, 0, 5f);
}
if (GameInit.Ins.gamePlace == GamePlace.Zhejiang_Jinhua_KeJiGuan)
{
EnergyPump.transform.position = new Vector3(-3f, 0, 5f);
}
if (GameInit.Ins.gamePlace == GamePlace.Anhui_Wuhu_Guanwei)
{
EnergyPump.transform.position = new Vector3(-1.6f, 0, 1.6f);
}
if (GameInit.Ins.gamePlace == GamePlace.Zhejiang_Shaoxing_Shengzhou_WuyueGuangchang)
{
EnergyPump.transform.position = new Vector3(-3f, 0, 5f);
}
if (GameInit.Ins.gamePlace == GamePlace.Nanjing_Xianlin_WanDaMao)
{
EnergyPump.transform.position = new Vector3(-1.2f, 0, 1.5f);
}
if (GameInit.Ins.gamePlace == GamePlace.Yangzhou_Hanjiang_Tansuozhongxin)
{
EnergyPump.transform.position = new Vector3(1, 0, -2.61f);
}
if (GameInit.Ins.gamePlace == GamePlace.Yangzhou_Hanjiang_TansuoZhongxin_wai)
{
EnergyPump.transform.position = new Vector3(0, 0, 2f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Jining_Wanhuicheng_nei)
{
EnergyPump.transform.position = new Vector3(0, 0, 2f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Langfang_QingzhouTaihuacheng)
{
EnergyPump.transform.position = new Vector3(7.36f, 0, 7.58f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hubei_Xiangyang_Kejiguan)
{
EnergyPump.transform.position = new Vector3(0, 0, 5f);
}
if (GameInit.Ins.gamePlace == GamePlace.Jilin_Tonghua_Liuhe)
{
EnergyPump.transform.position = new Vector3(1.87f, 0, 2.17f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Jishou_Qianzhou_Tianhong)
{
EnergyPump.transform.position = new Vector3(4.82f, 0, -0.63f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Jinan_Huaiyin_ShengfutongShangmao)
{
EnergyPump.transform.position = new Vector3(-0.84f, 0, -0.11f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Jinan_Huaiyin_ShengfutongShangmao_wai)
{
EnergyPump.transform.position = new Vector3(-0.84f, 0, 1.2f);
}
if (GameInit.Ins.gamePlace == GamePlace.Henan_Xinzheng_Shuanghudadao_Longhujinyicheng)
{
EnergyPump.transform.position = new Vector3(-1.6f, 0, 4.35f);
}
if (GameInit.Ins.gamePlace == GamePlace.Nanjing_Qixia_Yaohuamen_Jindiguangchang)
{
EnergyPump.transform.position = new Vector3(1.35f, 0, 1.45f);
}
if (GameInit.Ins.gamePlace == GamePlace.Nanjing_Qixia_Yaohuamen_Jindiguangchang_nei)
{
EnergyPump.transform.position = new Vector3(-0.62f, 0, 1.87f);
}
if (GameInit.Ins.gamePlace == GamePlace.Anhui_Suzhou_Yueshan_Guchengshangyejie)
{
EnergyPump.transform.position = new Vector3(0f, 0, 3f);
}
if (GameInit.Ins.gamePlace == GamePlace.Gansu_Longnan_Shicheng_Dongsheng)
{
EnergyPump.transform.position = new Vector3(0f, 0, 7f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Heze_Yuncheng_Gefuli)
{
EnergyPump.transform.position = new Vector3(4.4f, 0, -0.61f);
}
if (GameInit.Ins.gamePlace == GamePlace.Wulanhaote_Ouya_Shangchang)
{
EnergyPump.transform.position = new Vector3(3.88f, 0, 7.38f);
}
if (GameInit.Ins.gamePlace == GamePlace.Wulanhaote_Wanda_Shangchang)
{
EnergyPump.transform.position = new Vector3(-10.8f, 0, 2.11f);
}
if (GameInit.Ins.gamePlace == GamePlace.Yunnan_Mile_Jinchen_Shidaiguangchang)
{
EnergyPump.transform.position = new Vector3(-1.45f, 0, 1.62f);
}
if (GameInit.Ins.gamePlace == GamePlace.Xinjiang_Yili_Yining_Wanrong)
{
EnergyPump.transform.position = new Vector3(0.59f, 0, 1.55f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Hengyang_Zhuhui_Dongzhoudao)
{
EnergyPump.transform.position = new Vector3(1.35f, 0, 1.45f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Hengyang_Zhuhui_Dongzhoudao_nei)
{
EnergyPump.transform.position = new Vector3(-0.58f, 0, 3.02f);
}
if (GameInit.Ins.gamePlace == GamePlace.Yunnan_Lincang_Linxiang_Hengji)
{
EnergyPump.transform.position = new Vector3(1.11f, 0, 2.64f);
}
if (GameInit.Ins.gamePlace == GamePlace.Yunnan_Lincang_Linxiang_Hengji_Dixia)
{
EnergyPump.transform.position = new Vector3(-0.34f, 0,9.82f);
}
if (GameInit.Ins.gamePlace == GamePlace.Guangxi_Guilin_Gongcheng_Shijixincheng)
{
EnergyPump.transform.position = new Vector3(-2.05f, 0, 9.72f);
}
if (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.71f, 0, 4.05f);
}
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.21f, 0,-0.07f);
}
if (GameInit.Ins.gamePlace == GamePlace.Guangdong_Guangzhou_Yanghaiyan)
{
EnergyPump.transform.position = new Vector3(1.72f, 0,-0.1f);
}
if (GameInit.Ins.gamePlace == GamePlace.Gansu_Jinchang_Jinchuan_Shijiguangchang)
{
EnergyPump.transform.position = new Vector3(0.05f, 0,6.65f);
}
if (GameInit.Ins.gamePlace == GamePlace.Henan_Xinxiang_Wandaguangchang)
{
EnergyPump.transform.position = new Vector3(4.05f, 0,-12.68f);
}
if (GameInit.Ins.gamePlace == GamePlace.Henan_Xinxiang_Wandaguangchang_Shinei)
{
EnergyPump.transform.position = new Vector3(-0.17f, 0,1.45f);
}
if (GameInit.Ins.gamePlace == GamePlace.Zhejiang_Hangzhou_Linping_Yintaicheng_Shinei)
{
EnergyPump.transform.position = new Vector3(0.61f, 0,3.72f);
}
if (GameInit.Ins.gamePlace == GamePlace.Gansu_Jinchang_Jinchuan_Shijiguangchang_Shiwai)
{
EnergyPump.transform.position = new Vector3(-2.58f, 0,0.31f);
}
if (GameInit.Ins.gamePlace == GamePlace.Guangdong_Guangzhou_Yanghaiyan_Lihu)
{
EnergyPump.transform.position = new Vector3(0.44f, 0,0.74f);
}
if (GameInit.Ins.gamePlace == GamePlace.Nanjing_Pukou_Longhutianjie)
{
EnergyPump.transform.position = new Vector3(0.36f, 0,3.39f);
}
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,2.88f);
}
if (GameInit.Ins.gamePlace == GamePlace.Jiangsu_Xvzhou_Suning_Guangchang)
{
EnergyPump.transform.position = new Vector3(1.35f, 0,1.45f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shanxi_Baoji_Meixian_TianlongShangcheng)
{
EnergyPump.transform.position = new Vector3(1.35f, 0,3.41f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Changde_Lixian_WandaGuangchang)
{
EnergyPump.transform.position = new Vector3(-0.4f, 0,2.64f);
}
if (GameInit.Ins.gamePlace == GamePlace.Jilin_Changchun_Beihu_WyueGuangchang)
{
EnergyPump.transform.position = new Vector3(0.66f, 0,3f);
}
if (GameInit.Ins.gamePlace == GamePlace.Chongqing_Yuzhong_Hongyadong_Xiakexing)
{
EnergyPump.transform.position = new Vector3(1.35f, 0,29.034f);
}
if (GameInit.Ins.gamePlace == GamePlace.Chengdu_Shuangliu_ShengfeiXuexiao)
{
EnergyPump.transform.position = new Vector3(-0.78f, 0,16.79f);
}
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.06f, 0,5.52f);
}
if (GameInit.Ins.gamePlace == GamePlace.Ningxia_Yinchuan_Jinfeng_XinhualianGuangchang)
{
EnergyPump.transform.position = new Vector3(10.88f, 0,4.59f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Zhuzhou_Wanda_Shennongcheng_Chaowanshe)
{
EnergyPump.transform.position = new Vector3(0.13f, 0,1.45f);
}
if (GameInit.Ins.gamePlace == GamePlace.Company1FloorShiwai)
{
EnergyPump.transform.position = new Vector3(-3.4f, 0,21.61f);
}
if (GameInit.Ins.gamePlace == GamePlace.Anhui_Suzhou_Yueshan_Guchengshangyejie_Shinei)
{
EnergyPump.transform.position = new Vector3(-0.08f, 0,4.63f);
}
if (GameInit.Ins.gamePlace == GamePlace.Hebei_Hengshui_Taocheng_WandaGuangchang)
{
EnergyPump.transform.position = new Vector3(-7.19f, 0,-2.28f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Weifang_Linqu_WandaGuangchang)
{
EnergyPump.transform.position = new Vector3(-7.19f, 0,-5.37f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Jining_Shangchang_3)
{
EnergyPump.transform.position = new Vector3(1.35f, 0,5.25f);
}
if (GameInit.Ins.gamePlace == GamePlace.Anhui_Manshan_XingyueGuangchang)
{
EnergyPump.transform.position = new Vector3(0.17f, 0,6.53f);
}
if (GameInit.Ins.gamePlace == GamePlace.Zhejiang_Wenzhou_Cangnan_Yintaicheng)
{
EnergyPump.transform.position = new Vector3(-0.1f, 0,4.57f);
}
if (GameInit.Ins.gamePlace == GamePlace.Jilin_Changchun_Chaoyang_OuyaMaichang)
{
EnergyPump.transform.position = new Vector3(0.9f, 0,2.24f);
}
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Weifang_Linqu_WandaGuangchang_Shinei)
{
EnergyPump.transform.position = new Vector3(2.14f, 0,5.34f);
}
EnergyPumpTag++;
EnergyPump.GetComponent<EnergyPump>().Init(EnergyPumpTag);
_energyPump=EnergyPump.GetComponent<EnergyPump>();
}
//创建闪电
[Server]
public void GenerateLightning(Vector3 transform, Vector3 angle, float time)
{
GameObject Lightning = Instantiate(LightningPre);
NetworkServer.Spawn(Lightning);
Lightning.transform.position = transform;
Lightning.transform.eulerAngles = angle;
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
NetworkServer.Destroy(Lightning);
}, time);
}
[ClientRpc]
public void ShowTex()
{
GameInit.Ins.Tex.SetActive(true);
}
[ClientRpc]
public void OpenCoillder(GameObject obj)
{
obj.GetComponent<CapsuleCollider>().enabled = true;
}
[Server]
public void DestoryEnergyPump(GameObject obj)
{
NetworkServer.Destroy(obj);
}
[Server]
public void GenerateWall(int index, Vector3 position, Vector3 angle)
{
//EnergyPump1
GameObject wall = Instantiate(wallPre);
//NetworkServer.Spawn(wall);
wall.tag = "Story" + index.ToString();
wall.transform.position = position;
wall.transform.eulerAngles = angle;
}
//创建雷达点
[Server]
public void GenerateRadarPoint()
{
GameObject point = Instantiate(doorPre);
NetworkServer.Spawn(point);
point.transform.position = new Vector3(transform.transform.position.x, transform.transform.position.y, transform.transform.position.z);
point.transform.localEulerAngles = new Vector3(0, 0, 0);
}
//创建大门
[Server]
public GameObject GenerateDoor()
{
GameObject door = Instantiate(doorPre);
Vector3 pos = tempDescInfos[1].Positions[0];
Vector3 scale = tempDescInfos[1].Scales[0];
NetworkServer.Spawn(door);
door.transform.position = new Vector3(pos.x, pos.y, pos.z);
door.transform.localScale = scale;
door.transform.localEulerAngles = tempDescInfos[1].Angles[0];
door.GetComponentInChildren<Animator>().SetBool("IsOpen", true);
return door;
}
// 创建巡逻兵
[Server]
public void GenerateRobotGuardian(Transform pos)
{
Debug.Log("创建巡逻兵");
GameObject RobotGuardian = Instantiate(RobotGuardianPre);
NetworkServer.Spawn(RobotGuardian);
RobotGuardian.transform.position = new Vector3(pos.transform.position.x, pos.transform.position.y, pos.transform.position.z);
RobotGuardian.GetComponent<RobotGuardian>().OnSpawn();
}
[Server]
public GameObject GenerateEnemy(EnemyType Type, Vector3 pos, Vector3 angle, Vector3 scale, string pathId = "0")
{
if (isGameEnd)
return null;
GameObject enemy = null;
switch (Type)
{
case EnemyType.RobotGuardian:
enemy = CreateRobotGuardian(pos, angle, scale, pathId);
break;
case EnemyType.QY:
enemy = CreateQY(pos, angle, scale, pathId);
break;
case EnemyType.Esky:
enemy = CreateEsky(pos, angle, scale, pathId);
break;
case EnemyType.Spider:
enemy = CreateSpider(pos, angle, scale, pathId);
break;
case EnemyType.EliteSpider:
enemy = CreateEliteSpiderPre(pos, angle, scale);
break;
case EnemyType.RobotMech:
enemy = CreateRobotMesh(pos, angle, scale);
break;
case EnemyType.Shadow:
enemy = CreateShadow(pos, angle, scale);
break;
case EnemyType.ShadowCast:
enemy = CreateShadowCast(pos, angle, scale);
break;
case EnemyType.Boss:
enemy = CreateBoos(pos, angle, scale, pathId);
break;
}
XAgent xagent = enemy.GetComponent<XAgent>();
xagent.index = EnemyAmount;
enemyList.Add(xagent.transform);
EnemyAmount++;
return enemy;
}
[Server]
public GameObject CreateQY(Vector3 pos, Vector3 angle, Vector3 scale, string pathId)
{
GameObject QY = Instantiate(QYPre);
NetworkServer.Spawn(QY);
QY.transform.position = pos;
QY.transform.localEulerAngles = angle;
QY.transform.localScale = scale;
QY qyScript = QY.GetComponent<QY>();
qyScript.OnSpawn();
qyScript.SetPathId(pathId);
return QY;
}
// 创建起义兵
[Server]
public GameObject CreateRobotGuardian(Vector3 pos, Vector3 angle, Vector3 scale, string pathId)
{
GameObject robotGuardian = Instantiate(RobotGuardianPre);
NetworkServer.Spawn(robotGuardian);
robotGuardian.transform.position = pos;
robotGuardian.transform.localEulerAngles = angle;
robotGuardian.transform.localScale = scale;
RobotGuardian robotScript = robotGuardian.GetComponent<RobotGuardian>();
robotScript.OnSpawn();
robotScript.SetPathId(pathId);
return robotGuardian;
}
[ClientRpc]
public void HudMessage(int index)
{
EventDispatcher.TriggerEvent("PromptMessage", index);
}
[ClientRpc]
public void Message(string text, string clipName)
{
EventDispatcher.TriggerEvent("Message", text, clipName);
}
[ClientRpc]
public void ShowTeachUI(int index)
{
EventDispatcher.TriggerEvent("ShowTeachUI", index);
}
[Server]
public GameObject CreateEliteSpiderPre(Vector3 pos, Vector3 angle, Vector3 scale)
{
GameObject eliteSpider = Instantiate(EliteSpiderPre);
NetworkServer.Spawn(eliteSpider);
eliteSpider.transform.position = pos;
eliteSpider.transform.localEulerAngles = angle;
eliteSpider.transform.localScale = scale;
eliteSpider.GetComponent<EliteSpider>().OnSpawn();
return eliteSpider;
}
[Server]
public GameObject CreateRobotMesh(Vector3 pos, Vector3 angle, Vector3 scale)
{
GameObject robotMesh = Instantiate(RobotMechPre);
NetworkServer.Spawn(robotMesh);
robotMesh.transform.position = pos;
robotMesh.transform.localEulerAngles = angle;
robotMesh.transform.localScale = scale;
robotMesh.GetComponent<RobotMech>().OnSpawn();
return robotMesh;
}
/// <summary>
/// 创建幻影者
/// </summary>
/// <param name="pos"></param>
/// <param name="angle"></param>
/// <returns></returns>
[Server]
public GameObject CreateShadow(Vector3 pos, Vector3 angle, Vector3 scale)
{
GameObject Shadow = Instantiate(ShadowPre);
NetworkServer.Spawn(Shadow);
Shadow.transform.position = pos;
Shadow.transform.localEulerAngles = angle;
Shadow.transform.localScale = scale;
Shadow shadow = Shadow.GetComponent<Shadow>();
NowShadow = shadow;
shadow.OnSpawn();
return Shadow;
}
/// <summary>
/// 创建幻影者分身
/// </summary>
/// <param name="pos"></param>
/// <param name="angle"></param>
/// <returns></returns>
public GameObject CreateShadowCast(Vector3 pos, Vector3 angle, Vector3 scale)
{
GameObject Shadow = Instantiate(ShadowCastPre);
NetworkServer.Spawn(Shadow);
Shadow.transform.position = pos;
Shadow.transform.localEulerAngles = angle;
Shadow.transform.localScale = scale;
ShadowCast shadow = Shadow.GetComponent<ShadowCast>();
shadow.Init(NowShadow.OriginHealth, NowShadow.Health);
return Shadow;
}
[Server]
public GameObject CreateBoos(Vector3 pos, Vector3 angle, Vector3 scale, string pathId)
{
GameObject boss = Instantiate(BossPre);
NetworkServer.Spawn(boss);
boss.transform.position = pos;
boss.transform.localEulerAngles = angle;
boss.transform.localScale = scale;
Boss bossScript = boss.GetComponent<Boss>();
bossScript.OnSpawn();
bossScript.SetPathId(pathId);
return boss;
}
[Command(requiresAuthority = false)]
public void CreateGameStartPoint()
{
Vector3 pos = tempDescInfos[0].Positions[0];
StartGuide();
GameObject point = Instantiate(gameStartPointPre);
NetworkServer.Spawn(point);
if (GameInit.Ins.gamePlace == GamePlace.Shandong_Langfang_QingzhouTaihuacheng)
{
point.transform.position = new Vector3(7.3f, 0, 2.3f);
}
if (GameInit.Ins.gamePlace == GamePlace.Wulanhaote_Ouya_Shangchang)
{
point.transform.position = new Vector3(4.5f, 0, -1f);
}
if (GameInit.Ins.gamePlace == GamePlace.Company1FloorShiwai)
{
point.transform.position = new Vector3(0.48f, 0, 20.17f);
}
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);
}
if (GameInit.Ins.gamePlace == GamePlace.Ningxia_Yinchuan_Jinfeng_XinhualianGuangchang)
{
point.transform.position = new Vector3(6.05f, 0, 1.93f);
}
else
{
point.transform.position = pos;
}
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
if(isDoorDie)
return;
isDoorDie = true;
NetworkServer.Destroy(point.gameObject);
StoryManager.Ins.CreateStoryItem();
Debug.Log("触碰光柱");
GameOK();
//修改处:获取 AI 控制器并注册事件
if (aiCharacter != null)
{
var aiController = aiCharacter.GetComponent<AIController>();
if (aiController != null)
{
aiController.OnIntroductionComplete += StartGameAfterAIIntroduction;
}
}
}, 8f);
// point.transform.position = new Vector3(5.55f, 0, 2.19f);//beijing
}
public void StartGameAfterAIIntroduction()
{
var aiController = aiCharacter.GetComponent<AIController>();
Debug.Log("AI介绍完成开始游戏讲解");
//修改添加设置AI介绍完成标志
RpcSetAIIntroductionComplete(true);
//修改触发教学音频和UI
HudMessage(0);
//启动游戏讲解协程
StartCoroutine(StoryManager.Ins.MyCoroutine());
// 延迟播放背景音乐
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
AudioManager.Ins?.SoundPlay("bgm2", true);
}, 10f);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
AudioManager.Ins?.SoundPlay("bgm3", true);
}, 30f);
// 取消事件注册,避免重复调用
if (aiController != null)
{
aiController.OnIntroductionComplete -= StartGameAfterAIIntroduction;
}
}
[Server]
// 创建苍蝇
public GameObject CreateEsky(Vector3 pos, Vector3 angle, Vector3 scale, string pathId)
{
GameObject Esky = Instantiate(EskyPre);
NetworkServer.Spawn(Esky);
Esky.transform.position = pos;
Esky.transform.localEulerAngles = angle;
Esky.transform.localScale = scale;
Esky eskyScript = Esky.GetComponent<Esky>();
eskyScript.OnSpawn();
eskyScript.SetPathId(pathId);
return Esky;
}
[Server]
public GameObject CreateEskyClone(Vector3 pos, Vector3 angle)
{
GameObject EskyClone = Instantiate(EskyClonePre);
NetworkServer.Spawn(EskyClone);
EskyClone.transform.position = pos;
EskyClone.transform.localEulerAngles = angle;
EskyClone eskyScript = EskyClone.GetComponent<EskyClone>();
eskyScript.OnSpawn();
return EskyClone;
}
[Server]
//创建炮台
public GameObject GenerateTurret(Vector3 pos, Vector3 scale, Vector3 angle)
{
GameObject turret = Instantiate(TurretPre);
NetworkServer.Spawn(turret);
turret.transform.position = pos;
turret.transform.localScale = scale;
turret.transform.localEulerAngles = angle;
return turret;
}
public void CreateProp(PropType propType, Vector3 pos)
{
switch (propType)
{
case PropType.BloodBag:
CreateBloodBag(pos);
break;
case PropType.EnergyMask:
CreateShield(pos);
break;
case PropType.AtkBuff:
CreateAtkBuff(pos);
break;
case PropType.DefenseBuff:
CreateDeeBuff(pos);
break;
case PropType.EnergyPump:
GenerateEnergyPump(pos);
break;
}
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)
);
}
}
[Server]
public void CreateItemProp(int index, Vector3 pos, int amount = 1)
{
if(isGameEnd)
return;
if (index < 500)
{
//武器
CreateWeaponProp((WeaponType)(index), pos, amount);
}
else if (index > 500 && index < 1000)
{
//道具
CreateProp((PropType)(index), pos);
}
}
//创建蜘蛛
[Server]
public GameObject CreateSpider(Vector3 pos, Vector3 angle, Vector3 scale, string pathId = "")
{
GameObject Spider = Instantiate(SpiderPre);
NetworkServer.Spawn(Spider);
Spider.transform.position = pos;
Spider.transform.localEulerAngles = angle;
Spider.transform.localScale = scale;
Spider.GetComponent<Spider>().OnSpawn();
Spider.GetComponent<Spider>().SetPathId(pathId);
return Spider;
}
[Server]
public GameObject CreateSpiderClone(Vector3 pos, Vector3 angle)
{
GameObject SpiderClone = Instantiate(SpiderClonePre);
NetworkServer.Spawn(SpiderClone);
SpiderClone.transform.position = pos;
SpiderClone.transform.localEulerAngles = angle;
SpiderClone.GetComponent<SpiderClone>().OnSpawn();
return SpiderClone;
}
//创建落石特效
[Server]
public GameObject GenerateRockfall(Vector3 pos, Vector3 angle)
{
GameObject Rockfall = Instantiate(RockfallPre);
Rockfall.transform.position = pos;
Rockfall.transform.localEulerAngles = angle;
NetworkServer.Spawn(Rockfall);
return Rockfall;
}
[Server]
public GameObject CreateCrack(Vector3 pos, Vector3 angle)
{
GameObject Crack = Instantiate(CrackPre);
NetworkServer.Spawn(Crack);
Crack.transform.position = new Vector3(pos.x, pos.y, pos.z);
Crack.transform.localEulerAngles = angle;
return Crack;
}
[Server]
public void CreatePortal(Vector3 pos, float angleY, int amount, float interval, bool isActive, EnemyType type)
{
GameObject portal = Instantiate(CrackPre);
NetworkServer.Spawn(portal);
portal.transform.position = pos;
portal.transform.localEulerAngles = new Vector3(0, angleY, 0);
portal.GetComponent<Portal>().Init(amount, interval, isActive, type);
}
// 创建传送门
[Server]
public GameObject SpwanCrack(Transform pos)
{
GameObject Crack = Instantiate(CrackPre);
NetworkServer.Spawn(Crack);
Crack.transform.position = new Vector3(pos.position.x, pos.position.y, pos.position.z);
return Crack;
}
public bool EnemyDie()
{
if (AllEnemyAmount > 0)
AllEnemyAmount--;
if (AllEnemyAmount == 0)
{
EnemyAmount = 0;
return true;
}
return false;
}
// 获取第一个玩家
public Transform GetPlayer1()
{
Transform player = null;
if (MRNetworkManager.Ins.roomSlots.Count > 0)
{
player = MRNetworkManager.Ins.roomSlots[0].transform;
}
return player;
}
public Transform GetPlayer(int index)
{
NetworkRoomPlayer roomPlayer = null;
roomPlayer = MRNetworkManager.Ins.roomSlots[index];
Transform play = roomPlayer.transform;
return play;
}
public int GetRandomPlayerIndex()
{
int index = 0;
//怪物随机选取目标 只取一次
index = Random.Range(0, MRNetworkManager.Ins.roomSlots.Count);
return index;
}
/// <summary>
/// 创建护盾
/// </summary>
[Command(requiresAuthority = false)]
public void CreateShield(Vector3 pos)
{
GameObject shield = Instantiate(ShieldPre);
NetworkServer.Spawn(shield);
shield.transform.position = new Vector3(pos.x, 0, pos.z);
Shield shieldScript = shield.GetComponent<Shield>();
shieldScript.Id = ShieldId;
Shields.Add(ShieldId, shieldScript);
ShieldId++;
}
/// <summary>
/// 删除护盾
/// </summary>
public void DelShield(int id)
{
Shield shield = Shields[id];
if (shield != null)
{
Shields.Remove(id);
}
}
/// <summary>
/// 创建攻击BUFF
/// </summary>
/// <param name="pos"></param>
[Command(requiresAuthority = false)]
public void CreateAtkBuff(Vector3 pos)
{
GameObject atkBuff = Instantiate(AtkBuffPre);
NetworkServer.Spawn(atkBuff);
atkBuff.transform.position = new Vector3(pos.x, 0, pos.z);
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Zhuzhou_Wanda_Shennongcheng_Chaowanshe)
{
StartCoroutine(FlyToTargetPosition(atkBuff, new Vector3(0.1f, 0, 1.68f), 2.0f));
}
}
/// <summary>
/// 创建攻击BUFF
/// </summary>
/// <param name="pos"></param>
[Command(requiresAuthority = false)]
public void CreateDeeBuff(Vector3 pos)
{
GameObject deeBuff = Instantiate(deffBuffPre);
NetworkServer.Spawn(deeBuff);
deeBuff.transform.position = new Vector3(pos.x, 0, pos.z);
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Zhuzhou_Wanda_Shennongcheng_Chaowanshe)
{
StartCoroutine(FlyToTargetPosition(deeBuff, new Vector3(0.1f, 0, 1.68f), 2.0f));
}
}
/// <summary>
/// 创建血包
/// </summary>
[Command(requiresAuthority = false)]
public void CreateBloodBag(Vector3 pos)
{
GameObject bloodBag = Instantiate(BloodBagPre);
NetworkServer.Spawn(bloodBag);
bloodBag.transform.position = new Vector3(pos.x, 0, pos.z);
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Zhuzhou_Wanda_Shennongcheng_Chaowanshe)
{
StartCoroutine(FlyToTargetPosition(bloodBag, new Vector3(0.1f, 0, 1.68f), 2.0f));
}
}
/// <summary>
/// 创建武器道具
/// </summary>
[Command(requiresAuthority = false)]
public void CreateWeaponProp(WeaponType type, Vector3 pos, int amount)
{
GameObject prop = Instantiate(WeaponPropPre);
NetworkServer.Spawn(prop);
prop.GetComponent<WeaponProp>().Init(type, amount);
prop.transform.position = pos;
// 在掉落位置周围随机分布
Vector3 dropPosition = pos;
if (GameInit.Ins.gamePlace == GamePlace.Hunan_Zhuzhou_Wanda_Shennongcheng_Chaowanshe)
{
// 在掉落位置周围随机偏移
float randomRadius = 0.2f;
dropPosition = new Vector3(
pos.x + Random.Range(-randomRadius, randomRadius),
0.2f,
pos.z + Random.Range(-randomRadius, randomRadius)
);
prop.transform.position = dropPosition;
Vector3 targetPosition = dropPosition + new Vector3(0, 0f, 0);
StartCoroutine(FlyToTargetPosition(prop, targetPosition, 0.2f));
}
else
{
prop.transform.position = dropPosition;
}
}
/// <summary>
/// 道具飞向中心点(0,0,0)的协程
/// </summary>
/// <param name="prop">道具对象</param>
/// <param name="targetPosition">目标位置</param>
/// <param name="duration">飞行时间</param>
/// <returns></returns>
private IEnumerator FlyToTargetPosition(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 * 0.5f;
// 飞行过程中只更新位置,不改变旋转
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;
}
/// <summary>
/// 找到有玩家x在里面的护盾
/// </summary>
/// <param name="playerIndex"></param>
/// <returns></returns>
public int FindPlayerInShield(int playerIndex)
{
int res = -1;
foreach (Shield shield in Shields.Values)
{
float dis = MathExtension.GetDistanceXOZ(MRNetworkManager.Ins.roomSlots[playerIndex].transform.position, shield.transform.position);
if (dis <= 2.5f)
{
res = shield.Id;
break;
}
}
return res;
}
/// <summary>
/// 判断玩家x是否在护盾内
/// </summary>
/// <param name="playerIndex"></param>
/// <returns></returns>
public bool IsPlayerInShield(int playerIndex = 0)
{
bool res = false;
int find = FindPlayerInShield(playerIndex);
if (find != -1)
{
res = true;
}
return res;
}
/// <summary>
/// 根据位置获取能攻击的护盾
/// </summary>
/// <param name="point"></param>
/// <param name="playerIndex"></param>
/// <param name="attackArea"></param>
/// <returns></returns>
public Shield GetCanAttackShield(Vector3 point, int playerIndex, float attackArea)
{
Shield res = null;
int find = FindPlayerInShield(playerIndex);
if (find != -1)
{
float dis = MathExtension.GetDistanceXOZ(Shields[find].transform.position, point);
if (dis > 2.5f && dis < 2.5f + attackArea)
{
res = Shields[find];
}
}
return res;
}
/// <summary>
/// 判断是否能攻击护盾
/// </summary>
public bool IsCanAttackShield(Transform enemy, int playerIndex, float attackArea)
{
bool res = false;
Shield find = GetCanAttackShield(enemy.position, playerIndex, attackArea);
res = find == null ? false : true;
return res;
}
/// <summary>
/// 判断是否能攻击玩家
/// </summary>
/// <param name="playerIndex"></param>
/// <returns></returns>
public bool IsCanAttackPlayer(Transform enemy, int playerIndex, float attackArea)
{
bool res = false;
Transform player = MRNetworkManager.Ins.roomSlots[playerIndex].transform;
float dis = MathExtension.GetDistanceXOZ(player.position, enemy.transform.position);
if (dis <= attackArea)
{
res = true;
}
return res;
}
#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 || gameStartPointPre == 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 = gameStartPointPre.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 && gameStartPointPre != null && GameInit .Ins.self != null)
{
guideArrowComponent.ShowPath();
isGuideArrowActive = true;
// 初始化路径
Vector3 playerPosition = GameInit .Ins.self.transform.position;
Vector3 doorPosition = gameStartPointPre.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 (gameStartPointPre != null && GameInit .Ins.self != null)
{
ShowGuideArrow();
// 初始化路径
Vector3 playerPosition = GameInit .Ins.self.transform.position;
Vector3 doorPosition = gameStartPointPre.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
}