2534 lines
82 KiB
C#
2534 lines
82 KiB
C#
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
|
||
}
|