Files
DinosaurPark/Assets/_DinosaurAge/Scripts/GameInit.cs

769 lines
25 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.Generic;
using System.Linq;
using BehaviorDesigner.Runtime;
using DarkTonic.MasterAudio;
using DragonLi.Core;
using Mirror;
using Unity.XR.PXR;
using UnityEngine;
using UnityEngine.UIElements;
public enum GameState
{
None,
Playing,
/// <summary>
/// 游戏计时结束
/// </summary>
GameTimerOver,
/// <summary>
/// 游戏流程结束
/// </summary>
GameOver,
}
namespace DinosaurAge
{
public class DinosaurEat
{
public int dinosaurId;
public int playerId;
}
public class GameInit : NetworkBehaviour
{
public static GameInit Ins { get; private set; }
public List<Dinosaur> Dinosaurs = new List<Dinosaur>();
public Dictionary<int, RightHand> RightHands = new Dictionary<int, RightHand>();
public Dictionary<int, LeftHand> LeftHand = new Dictionary<int, LeftHand>();
private List<DinosaurEat> dinosaurEats = new List<DinosaurEat>();
// 游玩结束时间
[NonSerialized]
[SyncVar]
public long vistEnd = 0;
// 总游玩时长
private int vistAllTime = (int)(60 * 10f);
public GameObject Door;
public GameObject DoorPre;
public GameObject glovePre;
public GameObject[] GameObjPres;
/// <summary>
/// 机器人实例
/// </summary>
public AiRobotGuide AiRobotGuide;
[SyncVar]
public GameState gameState = GameState.None;
private int maoziIndex = 0;
void Start()
{
Ins = this;
AuthorPanel.Show();
#if !UNITY_EDITOR && UNITY_ANDROID && PICO
PXR_MixedReality.EnableVideoSeeThrough(true);
#elif !UNITY_EDITOR && UNITY_ANDROID && VIVE
Interop.WVR_ShowPassthroughUnderlay(true);
#endif
}
private float eatEndDinosaurTime = 6f;
private float eatCurDinosaurTime = 0;
private int lestEatDinosaurId = -1;
private float triggerIdleTime = 0.5f;
private float curTriggerIdleTime = 0;
private void Update()
{
if (isClient && isServer)
{
if (gameState == GameState.Playing)
{
List<int> selects = new List<int>();
List<RightHand> rightHands = RightHands.Values.ToList();
for (int i = 0; i < rightHands.Count; i++)
{
int select = rightHands[i].targetId;
if (select != -1)
{
selects.Add(select);
}
}
DinosaurSelect(selects);
eatCurDinosaurTime -= Time.deltaTime;
if (eatCurDinosaurTime < 0)
{
eatCurDinosaurTime = 0;
lestEatDinosaurId = -1;
}
curTriggerIdleTime += Time.deltaTime;
if (gameState == GameState.Playing)
{
EatDinosaur();
if (curTriggerIdleTime > triggerIdleTime)
{
EndEatDinosaur();
curTriggerIdleTime = 0;
}
}
}
}
if (Input.GetKeyDown(KeyCode.Q))
{
MasterAudio.StopAllSoundsOfTransform(GameManager.Ins.MRCamera.transform);
MasterAudio.StopAllSoundsOfTransform(AiRobotGuide.transform);
MasterAudio.StopAllSoundsOfTransform(transform);
foreach (var roomPlayer in MRNetworkManager.Ins.roomSlots)
{
Player player = roomPlayer.GetComponent<Player>();
if (player != null)
{
player.isHaveGlove = false;
}
}
SetTourGuideState(AIRobotGuideState.Exit);
}
}
[ClientRpc]
public void StartRain()
{
Debug.Log("开始倒计时下雨");
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
GameManager.Ins.Rain.SetActive(true);
}, 60*2, this);
}
[ClientRpc]
public void StopRain()
{
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
GameManager.Ins.Rain.SetActive(false);
}, 8*60, this);
}
[ClientRpc]
public void CloseAllFlyDinosaurs()
{
for (int i = 0; i < Dinosaurs.Count; i++)
{
Dinosaurs[i].gameObject.SetActive(false);
}
}
public void StartServer()
{
if (isServer)
{
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
GameInit.Ins.CreateObj();
}, 3.0f, this);
}
}
[Server]
public void HapticImpulse(int playerIndex, int fishCollisonId)
{
foreach (var item in Dinosaurs)
{
Dinosaur dinosaur = item.GetComponent<Dinosaur>();
}
}
#region
/// <summary>
/// 喂食恐龙
/// </summary>
[Server]
public void IdleDinosaur(Dinosaur dinosaur,int playerId)
{
LeftHand[playerId].ShowFood(dinosaur.Type);
RightHands[playerId].targetId = dinosaur.Id;
}
/// <summary>
/// 介绍恐龙
/// </summary>
/// <param name="id"></param>
/// <param name="rightId"></param>
[Server]
public void IntroductionDinosaur(int id)
{
foreach (var item in Dinosaurs)
{
if(!item.isPlay)
continue;
if (item.Id == id)
{
Debug.Log("切换到介绍恐龙模式");
SetTourGuideState(AIRobotGuideState.IntroductionDinosaur);
item.ShowDescPanel();
}
}
}
/// <summary>
/// 结束抚摸
/// </summary>
[Server]
public void EndIdleDinosaur(int rightId)
{
foreach (var dinosaur in Dinosaurs)
{
if (dinosaur.isPlay&& RightHands[rightId].targetId==dinosaur.Id)
{
dinosaur.ChangeState(DinosaurStateType.Walk);
RightHands[rightId].targetId = -1;
RightHands[rightId].isIntroductionDinosaur = false;
}
}
RightHands[rightId].targetId = -1;
LeftHand[rightId].HideFoods();
}
[Server]
public void EatDinosaur(int dinosaursId,int playerId)
{
foreach (var item in Dinosaurs)
{
if (item.Id == dinosaursId)
{
item.ChangeState(DinosaurStateType.Eat,playerId);
return;
}
}
}
[Server]
public void EndEatDinosaur(int id,int playerId)
{
foreach (var item in Dinosaurs)
{
if (item.Id == id)
{
item.ChangeState(DinosaurStateType.Idle,playerId);
return;
}
}
}
public bool IsPlayDinosaur()
{
bool isPlay = false;
foreach (var dinosaur in Dinosaurs)
{
if (dinosaur!=null&&dinosaur.isPlay)
{
isPlay = true;
}
}
return isPlay;
}
[Server]
public void EatDinosaur()
{
Dinosaur dinosaur = null;
foreach (var item in MRNetworkManager.Ins.roomSlots)
{
var player= item.GetComponent<Player>();
if(!player.isHaveGlove||player.dinosaurId != -1)
continue;
dinosaur=GetEatDinosaur(false,player);
if(dinosaur==null||dinosaur.state==DinosaurStateType.Idle||lestEatDinosaurId==dinosaur.Id)
continue;
// 触发介绍
IntroductionDinosaur(dinosaur.Id);
// 添加判断玩家是否在恐龙面前的检测
if (IsPlayerFacingDinosaur(player, dinosaur))
{
PlayFishAudio(dinosaur, player);
IdleDinosaur(dinosaur, RightHands[player.index].ownerIndex);
dinosaur.ChangeState(DinosaurStateType.Idle, item.index);
player.dinosaurId = dinosaur.Id;
AiRobotGuide.behaviorTree.SetVariable("Target", (SharedGameObject)dinosaur.gameObject);
// 触发介绍
IntroductionDinosaur(dinosaur.Id);
}
}
}
[Server]
public void EndEatDinosaur()
{
foreach (var item in MRNetworkManager.Ins.roomSlots)
{
var player= item.GetComponent<Player>();
if(!player.isHaveGlove||player.dinosaurId==-1)
continue;
var dinosaur = GetEatDinosaur(true,player);
int foodType = 0;
foreach (var itemDinosaur in Dinosaurs)
{
if (itemDinosaur.Id == player.dinosaurId)
foodType = itemDinosaur.typeId;
}
if (dinosaur!=null||LeftHand[player.index].foods[foodType].isEnd)
{
EndIdleDinosaur(player.index);
SetTourGuideState(AIRobotGuideState.Follow);
eatCurDinosaurTime = eatEndDinosaurTime;
lestEatDinosaurId = player.dinosaurId;
player.dinosaurId = -1;
}
}
}
/// <summary>
/// 判断玩家是否在恐龙面前
/// </summary>
/// <param name="player">玩家对象</param>
/// <param name="dinosaur">恐龙对象</param>
/// <param name="maxAngle">最大角度阈值默认30度</param>
/// <param name="maxDistance">最大距离阈值</param>
/// <returns>true表示玩家在恐龙面前</returns>
[Server]
public bool IsPlayerFacingDinosaur(Player player, Dinosaur dinosaur, float maxAngle = 90f, float maxDistance = 2f)
{
// 计算玩家到恐龙的方向向量
Vector3 directionToDinosaur = dinosaur.transform.position - player.transform.position;
float distance = directionToDinosaur.magnitude;
// 检查距离是否在阈值内
if (distance > maxDistance)
return false;
// 归一化方向向量
directionToDinosaur.Normalize();
// 获取玩家的前向向量
Vector3 playerForward = player.transform.forward;
// 使用点积计算角度(更高效的方式)
float dotProduct = Vector3.Dot(playerForward, directionToDinosaur);
// 将点积转换为角度
float angle = Mathf.Acos(dotProduct) * Mathf.Rad2Deg;
// 检查角度是否在阈值内
return angle <= maxAngle;
}
[Server]
public Dinosaur GetEatDinosaur(bool isEndEat,Player player)
{
if (!isEndEat)
{
foreach (var item in Dinosaurs)
{
if(item.isPlay)
continue;
float distSqr = (player.transform.position - item.transform.position).sqrMagnitude;
float eatRadiusSqr = item.playerDis * item.playerDis;
if (distSqr <= eatRadiusSqr )
{
return item;
}
}
}
else
{
foreach (var item in Dinosaurs)
{
if(!item.isPlay|| player.dinosaurId!=item.Id)
continue;
float distSqr = (player.transform.position - item.transform.position).sqrMagnitude;
float eatRadiusSqr = item.playerDis * item.playerDis;
if (distSqr > eatRadiusSqr )
{
return item;
}
}
}
return null;
}
#endregion
[Server]
public void CreateDoor()
{
Debug.Log("创建门");
GameObject door = Instantiate(DoorPre,GameManager.Ins.museumScene.transform);
Door = door;
isGoDinosaur = false;
NetworkServer.Spawn(door);
}
[Server]
public void DelDoor()
{
Door.GetComponent<Collider>().enabled = false;
NetworkServer.Destroy(Door);
}
#region
/// <summary>
/// 改变机器人状态
/// </summary>
public void SetTourGuideState(AIRobotGuideState state)
{
if (AiRobotGuide != null)
{
if(AiRobotGuide.state== AIRobotGuideState.Exit)
return;
AiRobotGuide.state = state;
}
}
#endregion
#region
[Server]
public void DinosaurSelect(List<int> dinosaurIds)
{
if (dinosaurIds.Count == 0)
{
for (int i = 0; i < Dinosaurs.Count; i++)
{
Dinosaurs[i].HideOutline();
}
}
else
{
for (int i = 0; i < Dinosaurs.Count; i++)
{
bool show = false;
for (int j = 0; j < dinosaurIds.Count; j++)
{
if (Dinosaurs[i].Id == dinosaurIds[j])
{
show = true;
}
}
if (show)
{
Dinosaurs[i].ShowOutline();
}
else
{
Dinosaurs[i].HideOutline();
}
}
}
}
#endregion
/// <summary>
/// 游戏开始
/// </summary>
[Server]
public void GameStart()
{
if (gameState == GameState.Playing)
{
return;
}
// 设置游戏状态
gameState = GameState.Playing;
// 设置所有玩家状态
AllPlayerStateChange(PlayerState.WaitStart);
// 2.进入恐龙场景
ToDinosaurScene();
// 3.设置游玩时间
vistEnd = (long)(DateTime.Now.Subtract(new DateTime(1970, 1, 1))).TotalSeconds + vistAllTime;
RpcShowDuringPanel();
// 4.设置结束计时
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
MasterAudio.StopAllSoundsOfTransform(GameManager.Ins.MRCamera.transform);
MasterAudio.StopAllSoundsOfTransform(AiRobotGuide.transform);
MasterAudio.StopAllSoundsOfTransform(transform);
foreach (var roomPlayer in MRNetworkManager.Ins.roomSlots)
{
Player player = roomPlayer.GetComponent<Player>();
if(player!=null)
{
player.isHaveGlove = false;
}
}
SetTourGuideState(AIRobotGuideState.Exit);
}, vistAllTime);
CreateDinosaurs();
SetTourGuideState(AIRobotGuideState.SendGlove);
// 设置游戏状态
gameState = GameState.Playing;
// Debug.Log("等待1分钟通知计费");
// MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
// {
// RequestNotifyStartRpc();
// }, 60);
StartRain();
StopRain();
}
[ClientRpc]
public void ToDinosaurScene()
{
GameManager.Ins.dinosaurScene.SetActive(true);
GameManager.Ins.museumScene.SetActive(false);
GameManager.Ins.goObj.SetActive(false);
GameManager.Ins.bgm.clip = GameManager.Ins.dinosaurClip;
GameManager.Ins.bgm.Play();
lestEatDinosaurId = -1;
eatCurDinosaurTime = eatEndDinosaurTime;
DelDoor();
}
public bool isGoDinosaur;
[Server]
public void GoDinosaurScene()
{
if(isGoDinosaur)
return;
isGoDinosaur = true;
OpenGo();
AiRobotGuide.Stop();
SetTourGuideState(AIRobotGuideState.Follow);
AiRobotGuide.PlaySoundRpc("时空穿梭");
}
private float goTime = 42;
[ClientRpc]
public void OpenGo()
{
Debug.Log("开始游戏");
GameManager.Ins.museumScene.SetActive(false);
GameManager.Ins.goObj.SetActive(true);
GameManager.Ins.goObj.transform.position = GameManager.Ins.MRCamera.transform.position += new Vector3(0,1,20);
if(GameManager.Ins.place== Place.Yangzhou_Hanjiang_TansuoZhongxin)
GameManager.Ins.goObj.transform.position = GameManager.Ins.MRCamera.transform.position += new Vector3(0,1,-30);
GameManager.Ins.dinosaurSpawner.Play();
GameManager.Ins.bgm.clip = GameManager.Ins.goClip;
GameManager.Ins.bgm.Play();
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
GameManager.Ins.dinosaurSpawner.Stop();
GameStart();
}, goTime);
}
[Server]
public void CreateObj()
{
// 5.创建游戏物体
foreach (GameObjInfo info in GameManager.Ins.GameObjInfos)
{
GameObject obj = Instantiate(GameObjPres[(int)info.ID]);
NetworkServer.Spawn(obj);
if (info.ID == GameObjType.AIRobotGuide)
{
AiRobotGuide = obj.GetComponent<AiRobotGuide>();
}
obj.transform.position = GameManager.Ins.aiPos.position;
}
if(gameState==GameState.Playing)
AiRobotGuide.SendGlove();
}
public string GetLessTimeStr()
{
string res = "00:00";
int lessTime = (int)(vistEnd - DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds);
if (lessTime <= 0)
{
lessTime = 0;
}
res = FormatTime(lessTime);
return res;
}
// 时分秒
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);
}
[ClientRpc]
public void RpcShowDuringPanel()
{
DuringPanel.Show();
}
//创建手套
[Server]
public void CreateGlove()
{
foreach (var item in MRNetworkManager.Ins.roomSlots)
{
Player player = item.GetComponent<Player>();
player.isHaveGlove = true;
// GameObject gloveObj = Instantiate(glovePre,AiRobotGuide.glovePos);
// gloveObj.transform.position=Vector3.zero;
// NetworkServer.Spawn(gloveObj);
// var glove = gloveObj.GetComponent<Glve>();
// glove.Init(player.index);
// Debug.Log("创建手套:"+player.index);
}
}
// 创建恐龙
[Server]
public void CreateDinosaurs()
{
float allTime = 0;
for (int i = 0; i <GameManager.Ins.DinosaurDescInfos.Count; i++)
{
DinosaurDescInfo info = GameManager.Ins.DinosaurDescInfos[i];
if(info.Id==3)
continue;
float createTime = UnityEngine.Random.Range(0, 0.2f);
allTime += createTime;
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
GameObject pre = Resources.Load<GameObject>("Dinosaurs/" + GameManager.Ins.DinosaurDescInfos[info.Id].Name);
if (pre != null)
{
GameObject dinosaur = Instantiate(pre);
NetworkServer.Spawn(dinosaur);
Dinosaur script = dinosaur.GetComponent<Dinosaur>();
pre.transform.localScale=new Vector3(info.scale,info.scale,info.scale);
script.Init(info.Id,info.speed,info.scale,info.type,info.eatDis);
Dinosaurs.Add(script);
}
}, allTime, this);
}
}
[ClientRpc]
public void PlayFishAudio(Dinosaur dinosaur,Player player)
{
if (player.index == GameManager.Ins.self.index)
{
dinosaur.PlayAudio();
MasterAudio.StopAllSoundsOfTransform(GameManager.Ins.MRCamera.transform);
MasterAudio.PlaySound3DAtTransform(dinosaur.Introduction,GameManager.Ins.MRCamera.transform);
}
}
// 游戏结束
[Server]
public void CheckGameEnd()
{
GameEndClient();
}
[Server]
public void GameEndClient()
{
Debug.Log("游戏结束");
gameState = GameState.GameOver;
// 消融所有恐龙
for (int i = 0; i < Dinosaurs.Count; i++)
{
NetworkServer.Destroy(Dinosaurs[i].gameObject);
}
Dinosaurs.Clear();
//左手恢复
foreach (var item in LeftHand)
{
item.Value.HideFoods();
}
AiRobotGuide.state = AIRobotGuideState.Follow;
ResetMuseum();
//返回博物馆
// 关闭飞翔的恐龙
//CloseAllFlyDinosaurs();
//RequestNotifyEnd();
// // 发送行为报告
// HTTPRequest request = new HTTPRequest(new Uri("http://192.168.1.100:5000/data"), HTTPMethods.Post, (req, response) =>
// {
// string text = response.DataAsText;
// Debug.Log("response data is" + text);
// });
// request.RawData = Encoding.UTF8.GetBytes(JsonUtility.ToJson(DataReportManager.Ins.StopRecord()));
// request.SetHeader("Content-Type", "application/json");
// request.Send();
}
[ClientRpc]
public void ResetMuseum()
{
GameManager.Ins.ResetMuseum();
}
#region
[Server]
public void AllPlayerStateChange(PlayerState state)
{
for (int i = 0; i < MRNetworkManager.Ins.roomSlots.Count; i++)
{
Player player = MRNetworkManager.Ins.roomSlots[i].GetComponent<Player>();
if (player.state != PlayerState.WatchVideo)
{
player.state = state;
}
}
}
[Command(requiresAuthority = false)]
public void PlayerStateChangeCmd(int playerIndex, PlayerState state)
{
PlayerStateChange(playerIndex, state);
}
[Server]
public void PlayerStateChange(int playerIndex, PlayerState state)
{
Player player = MRNetworkManager.Ins.roomSlots[playerIndex].GetComponent<Player>();
player.state = state;
}
#endregion
}
}