fix:补充ai行为流程

This commit is contained in:
bzx
2025-09-24 11:10:05 +08:00
parent d648a31930
commit d37bb0ae35
25 changed files with 742 additions and 310 deletions

View File

@@ -0,0 +1,13 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DefendEventManager : MonoBehaviour
{
public Dictionary<int,DefendEvent> defendEventDic = new Dictionary<int,DefendEvent>();
public void StartEvent(int id)
{
defendEventDic[id].StartEvent();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a2809f452877aef4d8b8ff4e955a57f9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,955 @@
using System;
using System.Collections;
using System.Collections.Generic;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines;
using Common;
using DragonLi.Core;
using Mirror;
using UnityEngine;
using UnityEngine.PlayerLoop;
using XPlugin.Data.JsonLiteDB;
using static XPlugin.Data.JsonLiteDB.JsonLiteDB;
using LitJson;
using Pathfinding;
using DarkTonic.MasterAudio;
using NaughtyAttributes;
using UnityEngine.UIElements;
using Random = UnityEngine.Random;
/// <summary>
/// 游戏状态
/// </summary>
public enum GameState
{
None = 0,
Playing = 1,
/// <summary>
/// 胜利
/// </summary>
Victory = 2,
/// <summary>
/// 失败
/// </summary>
Failur = 3,
Settle=4,
/// <summary>
/// 准备阶段
/// </summary>
Wave=5,
}
public enum GameMode
{
OnePlayer=0,
TwoPlayers=1,
}
public class GameManager : NetworkBehaviour
{
public static GameManager Ins { get; private set; }
#region
public GameObject DoorPre;
public GameObject gunPropPre;
public GameObject itemPropPre;
// 炮塔预制体集合
//public GameObject[] TowerPres;
// 怪物预制集合
public GameObject[] EnemyPres;
public GameObject[] playerAiPres;
public GameObject explosionPre;
// 怪物ui预制体
public GameObject EnemyUIPre;
#endregion
// json数据库
private JsonLiteDB DB;
// 怪物信息集合
public Dictionary<EnemyType, EnemyInfo> EnemyInfos = new Dictionary<EnemyType, EnemyInfo>();
public Dictionary<int,AiInfo> PlayerAiInfos = new Dictionary<int,AiInfo>();
// 炮塔信息集合
public Dictionary<TowerType, Dictionary<int, TowerInfo>> TowerInfos = new Dictionary<TowerType, Dictionary<int, TowerInfo>>();
// 枪械信息集合
public Dictionary<GunType, GunInfo> GunInfos = new Dictionary<GunType, GunInfo>();
// 子弹信息集合
public Dictionary<BulletType, BulletInfo> BulletInfos = new Dictionary<BulletType,BulletInfo>();
public Dictionary<int,AiInfo> AiInfos = new Dictionary<int,AiInfo>();
public Dictionary<int,RoundInfo> RoundInfos = new Dictionary<int,RoundInfo>();
// 剧情信息
public Dictionary<int, CombatUnitInfo> CombatUnitInfos = new Dictionary<int, CombatUnitInfo>();
private List<GameObject> curGunPropList = new List<GameObject>();
public Dictionary<int, Player> players = new Dictionary<int, Player>();
public GameMode gameMode = GameMode.OnePlayer;
/// <summary>
/// 敌人自增
/// </summary>
private int enemyIndex = 0;
/// <summary>
/// 所有敌人
/// </summary>
public Dictionary<int, Enemy> EnemyList = new Dictionary<int, Enemy>();
public Dictionary<int,PlayerAI> PlayerAiList = new Dictionary<int,PlayerAI>();
/// <summary>
/// 所有敌人UI
/// </summary>
public Dictionary<int, EnemyUI> EnemyUIList = new Dictionary<int, EnemyUI>();
/// <summary>
/// 所有炮塔
/// </summary>
public Dictionary<int, Tower> TowerList = new Dictionary<int, Tower>();
public Dictionary<TowerType, List<Tower>> TowerList2 = new Dictionary<TowerType, List<Tower>>();
public Dictionary<string, SettleInfo> SettleInfos = new Dictionary<string, SettleInfo>();
public List<Enemy> curEnemyList = new List<Enemy>();
[SyncVar]
public bool isStart;
/// <summary>
/// 波次自增
/// </summary>
[SyncVar]
public int roundIndex = 0;
// 游玩结束时间
[NonSerialized]
[SyncVar]
public long vistEnd = 0;
// 总游玩时长
private int vistAllTime = (int)(60*15 );
[SyncVar]
public string settleData = "";
[SyncVar]
public GameState gameState = GameState.None;
[SoundGroup] public string JointIn;
[SoundGroup] public string roundSound;
public int roundWaveTime;
public int curRoundWaveTime;
void Awake()
{
Ins = this;
}
void Start()
{
if (isClient)
{
isStart = false;
CreateDoor();
}
}
/// <summary>
/// 创建门
/// </summary>
public void CreateDoor()
{
UpdateConf();
if(!isServer)
return;
GameObject door = Instantiate(DoorPre);
door.transform.position = GameLocal.Ins.doorPos.position.ReflectVectorXOZ();
NetworkServer.Spawn(door);
}
/// <summary>
/// 创建初回合
/// </summary>
public void CreateFirstRound()
{
RpcShowHUD();
roundIndex = 0;
PlaySound2DRPC("1.0");
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
PlaySound2DRPC("1.1");
}, 10f);
CreatePlayerAi();
SetGameState(GameState.Wave);
RpcMessageRound();
}
/// <summary>
/// 创建下一回合
/// </summary>
public void CreateNextRound()
{
roundIndex++;
SetGameState(GameState.Wave);
roundWaveTime = 5;
curRoundWaveTime = 2;
RpcMessageRound();
}
[Server]
public void GameStart()
{
gameState = GameState.Playing;
gameMode=players.Count<=1 ? GameMode.OnePlayer : GameMode.TwoPlayers;
vistEnd = (long)(DateTime.Now.Subtract(new DateTime(1970, 1, 1))).TotalSeconds + vistAllTime;
isStart = true;
ChangeBgmRpc(1);
AstarPath.active.Scan();
CreateFirstRound();
// 延迟1s后给所有人发放武器
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
GivePistol();
}, 1f);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
//GameOver(GameState.Settle);
PlayEndEvent();
}, 60f * 15f);
}
[ClientRpc]
public void GivePistol()
{
Debug.Log("创建武器中...");
GameLocal.Ins.self.PickUpGun(GunType.Pistol, -999);
}
[Server]
public void SetGameState(GameState state)
{
gameState = state;
}
//1.游戏时间到
//2.所有怪物被消灭
//3.玩家被消灭
//以上都要跳出结算
[Server]
public void GameOver(GameState state)
{
RpcShow();
DamageAllEnemy();
gameState = state;
isStart = false;
// gameState = state;
foreach (string key in SettleInfos.Keys)
{
string[] titles = { "初露锋芒", "小菜一碟", "熟手", "痛并快乐着", "不死传说"
,"最强守护者", "独孤求败", "佛系玩家", "午时已到", "神枪手", "弹无虚发", "团队护盾", "我叫MT", "钢铁之躯","道具大师","行走的仓库","永不停歇" };
SetTitle(key, titles[Random.Range(0, titles.Length)]);
SetPlayerName(key);
}
string jsonStr = JsonMapper.ToJson(SettleInfos);
settleData = jsonStr;
// //结算页面
// RpcShow();
// if (blueScore >= redScore)
// {
// RpcShowWin(true);
// }
// else
// {
// RpcShowWin(false);
// }
}
[Server]
public void PlayEndEvent()
{
foreach (var item in PlayerAiList.Values)
{
item.EndEvent();
}
}
[ClientRpc]
public void RpcShowWin(bool isBlue)
{
}
[ClientRpc]
public void RpcShow()
{
SettlePanel.Show();
}
/// <summary>
/// 下一波进攻开始
/// </summary>
[Server]
public void RpcMessageRound()
{
if(!isStart)
return;
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
if(!isStart)
return;
PlaySound2DRPC("1.4");
}, curRoundWaveTime);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
if(!isStart)
return;
GetRoundEnemy();
SetGameState(GameState.Playing);
}, roundWaveTime);
}
[ClientRpc]
public void ShowHudRoundTime()
{
DragonLi.Core.EventDispatcher.TriggerEvent("NewWaveStart", roundIndex);
}
[ClientRpc]
public void ChangeBgmRpc(int i)
{
GameLocal.Ins.BGMState.StateChange(i);
}
public int curRoundEnemyCount;
/// <summary>
/// 创建敌方单位
/// </summary>
IEnumerator CreateEnemy(RoundInfo info)
{
curRoundEnemyCount = info.EnemyList.Count;
for (int i = 0; i < info.EnemyList.Count; i++)
{
GameObject enemy = Instantiate(EnemyPres[info.EnemyList[i]]);
NetworkServer.Spawn(enemy);
int posId =i/3;
int posX=i%3==0? 0: i%3==1 ? 1 : -1;
enemy.transform.position = GameLocal.Ins.enemyStartPos[posId].position;
enemy.transform.eulerAngles = new Vector3(0, 0, 0);
enemyIndex++;
Enemy enemyScript = enemy.GetComponent<Enemy>();
enemyScript.OnSpawn(enemyIndex, (EnemyType)info.EnemyList[i], 1,GameLocal.Ins.enemyStartPos[posId].position+new Vector3(posX,0,0));
EnemyList.Add(enemyIndex, enemyScript);
yield return new WaitForSeconds(0.5f);
}
}
/// <summary>
/// 创建辅助AI
/// </summary>
public void CreatePlayerAi()
{
if (gameMode == GameMode.OnePlayer)
{
for (int i = 0; i < 2; i++)
{
GameObject playerAi = Instantiate(playerAiPres[i]);
NetworkServer.Spawn(playerAi);
playerAi.transform.position = GameLocal.Ins.playerAiPos[i].position;
playerAi.transform.eulerAngles = new Vector3(0, 0, 0);
PlayerAI enemyScript = playerAi.GetComponent<PlayerAI>();
enemyScript.OnSpawn(i,(PlayerAIType)i, 1,GameLocal.Ins.playerAiEndPos[i].gameObject);
PlayerAiList.Add(i, enemyScript);
}
}
else if(gameMode == GameMode.TwoPlayers)
{
GameObject playerAi = Instantiate(playerAiPres[0]);
NetworkServer.Spawn(playerAi);
playerAi.transform.position = GameLocal.Ins.playerAiPos[0].position;
playerAi.transform.eulerAngles = new Vector3(0, 0, 0);
PlayerAI enemyScript = playerAi.GetComponent<PlayerAI>();
enemyScript.OnSpawn(0,0, 1,GameLocal.Ins.playerAiEndPos[0].gameObject);
PlayerAiList.Add(0, enemyScript);
}
}
/// <summary>
/// 创建Boss
/// </summary>
public void CreateBoss()
{
// GameObject enemy = Instantiate(EnemyPres[(int)EnemyType.ZombieBoss]);
// NetworkServer.Spawn(enemy);
// int posId = Random.Range(0, 4);
// int posX=Random.Range(-1, 1);
// int posZ=Random.Range(-1, 1);
// enemy.transform.position = GameLocal.Ins.enemyStartPos[posId].position+new Vector3(posX,0,posZ);
// enemy.transform.eulerAngles = new Vector3(0, 0, 0);
// enemyIndex++;
// Enemy enemyScript = enemy.GetComponent<Enemy>();
// enemyScript.OnSpawn(enemyIndex, EnemyType.ZombieBoss, 1);
// EnemyList.Add(enemyIndex, enemyScript);
// curRoundEnemyCount++;
}
public void CreateExplosion(Transform pos)
{
if(!isServer)
return;
var ex= Instantiate(explosionPre, pos.position, Quaternion.identity);
NetworkServer.Spawn(ex);
ex.GetComponent<Explosion>().Init(0);
}
[SyncVar]
public int gunProp1;
[SyncVar]
public int gunProp2;
[Server]
public void CreateGunProp()
{
if(!isStart)
return;
List<int> numbers = new List<int>() { 1, 2, 3, 4, 5 };
gunProp1 = numbers[Random.Range(0, numbers.Count)];
numbers.Remove(gunProp1);
gunProp2 = numbers[Random.Range(0, numbers.Count)];
var gun1= Instantiate(gunPropPre, GameLocal.Ins.gunPropPos[0]);
NetworkServer.Spawn(gun1);
gun1.GetComponent<WeaponProp>().Init((GunType)gunProp1);
curGunPropList.Add(gun1);
var gun2= Instantiate(gunPropPre, GameLocal.Ins.gunPropPos[1]);
NetworkServer.Spawn(gun2);
gun2.GetComponent<WeaponProp>().Init((GunType)gunProp2);
curGunPropList.Add(gun2);
}
public void CreateItemProp(Transform pos)
{
if(!isStart)
return;
var item= Instantiate(itemPropPre);
NetworkServer.Spawn(item);
item.transform.position=new Vector3(pos.position.x,0.5f,pos.position.z);
item.GetComponent<ItemProp>().SetItemProp(ItemPropType.Hp);
}
/// <summary>
///删除枪械
/// </summary>
public void DesGunProList()
{
if(curGunPropList.Count<=0)
return;
NetworkServer.Destroy(curGunPropList[1]);
NetworkServer.Destroy(curGunPropList[0]);
curGunPropList.Clear();
}
public List<Enemy> GetRoundEnemy()
{
List<Enemy> curEnemyList = new List<Enemy>();
if (roundIndex <= 2)
{
var combatUnitInfo= RoundInfos[0];
StartCoroutine(CreateEnemy(combatUnitInfo));
}
else
{
int curRoundIndex=Random.Range(1,RoundInfos.Count);
var roundInfo= RoundInfos[curRoundIndex];
StartCoroutine(CreateEnemy(roundInfo));
}
return curEnemyList;
}
public int[] GenerateMonsterTypes()
{
int[] weights = { 2, 6, 1, 3 };
List<int> monsterTypes = new List<int>();
int totalWeight = 0;
int targetWeight = Random.Range(24, 27); // 24-26
int targetCount = Random.Range(4, 8); // 4-7
// 随机添加怪物直到接近目标
while (monsterTypes.Count < targetCount && totalWeight < targetWeight)
{
int index = GetRandomMonsterIndex(weights);
int weight = weights[index];
// 如果剩余位置不够,跳出
if (monsterTypes.Count == targetCount)
break;
// 如果加上这个怪物不会超过目标权重,添加
if (totalWeight + weight <= targetWeight)
{
monsterTypes.Add(index);
totalWeight += weight;
}
else
{
break;
}
}
// 如果权重还没达到目标,填充最小权重怪物
while (totalWeight < targetWeight && monsterTypes.Count < targetCount)
{
int minIndex = GetMinWeightIndex(weights);
monsterTypes.Add(minIndex);
totalWeight += weights[minIndex];
}
Debug.LogError("生成的敌人数量:"+targetCount);
return monsterTypes.ToArray();
}
// 根据权重随机选择怪物
private int GetRandomMonsterIndex(int[] weights)
{
int sumWeight = 0;
foreach (var w in weights) sumWeight += w;
int randomValue = Random.Range(0, sumWeight);
int currentSum = 0;
for (int i = 0; i < weights.Length; i++)
{
currentSum += weights[i];
if (randomValue < currentSum)
return i;
}
return 0;
}
// 获取最小权重怪物的索引
private int GetMinWeightIndex(int[] weights)
{
int minIndex = 0;
for (int i = 1; i < weights.Length; i++)
{
if (weights[i] < weights[minIndex])
minIndex = i;
}
return minIndex;
}
/// <summary>
/// 删除敌方单位
/// </summary>
[Server]
public void DeleteEnemy(int id,Transform pos)
{
GameObject enemy = EnemyList[id].gameObject;
int hpItemPropIndex = 15;
int randomItemPropIndex = Random.Range(1, 101);
if(randomItemPropIndex<hpItemPropIndex)
CreateItemProp(enemy.transform);
EnemyList.Remove(id);
curRoundEnemyCount--;
NetworkServer.Destroy(enemy);
if (curRoundEnemyCount<=0)
{
//CreateGunProp();
CreateNextRound();
}
}
/// <summary>
/// 痛击场上所有敌方单位
/// </summary>
[Command(requiresAuthority = false)]
public void DamageAllEnemy()
{
foreach (Enemy enemy in EnemyList.Values)
{
enemy.ApplyDamage(999999, null, null);
}
}
/// <summary>
/// 更新配置表
/// </summary>
public void UpdateConf()
{
string text = Resources.Load<TextAsset>("Data").text;
if (text != null)
{
ParseGameJson(text);
}
}
public void ParseGameJson(string text)
{
DB = new JsonLiteDB();
DB.Load(text);
roundWaveTime = 15;
curRoundWaveTime = 12;
AiInfos.Clear();
RoundInfos.Clear();
TableReader infoReader = DB["AiInfo"].GetReader();
// EnemyInfos.Clear();
// while (infoReader.Read())
// {
// EnemyInfo info = new EnemyInfo(infoReader);
// EnemyInfos.Add((EnemyType)info.Type,info);
// }
//
// infoReader = DB["TowersInfo"].GetReader();
// while (infoReader.Read())
// {
// TowerInfo info = new TowerInfo(infoReader);
// TowerInfos.TryGetValue((TowerType)info.Type, out Dictionary<int, TowerInfo> infoList);
// if (infoList == null)
// {
// Dictionary<int, TowerInfo> list = new Dictionary<int, TowerInfo>();
// list.Add(info.Lvl, info);
// TowerInfos.Add((TowerType)info.Type, list);
// }
// else
// {
// infoList.Add(info.Lvl, info);
// }
// }
// infoReader = DB["GunsInfo"].GetReader();
// GunInfos.Clear();
// while (infoReader.Read())
// {
// GunInfo info = new GunInfo(infoReader);
// GunInfos.Add((GunType)info.Type,info);
// }
//
// infoReader = DB["BulletsInfo"].GetReader();
// BulletInfos.Clear();
// while (infoReader.Read())
// {
// BulletInfo info = new BulletInfo(infoReader);
// BulletInfos.Add((BulletType)info.Type,info);
// }
infoReader = DB["AiInfo"].GetReader();
while (infoReader.Read())
{
AiInfo info = new AiInfo(infoReader);
AiInfos.Add(info.ID,info);
}
infoReader = DB["RoundInfo"].GetReader();
while (infoReader.Read())
{
RoundInfo info = new RoundInfo(infoReader);
RoundInfos.Add(info.ID,info);
}
// infoReader = DB["StoryProgressInfo"].GetReader();
// while (infoReader.Read())
// {
// CombatUnitInfo info = new CombatUnitInfo(infoReader);
// CombatUnitInfos.Add(info.Belong,info);
// CombatUnitInfos.TryGetValue(info.Belong, out info);
// }
Debug.Log("游戏数值更新 -> complete");
}
/// <summary>
/// 获取范围内敌人
/// </summary>
public int GetRangeEnemyId(Vector3 pos, float radius)
{
int res = -1;
foreach (Enemy enemy in EnemyList.Values)
{
float dis = Vector3.Distance(enemy.transform.position, pos);
if (dis <= radius)
{
radius = dis;
res = enemy.id;
break;
}
}
return res;
}
/// <summary>
/// 获取最近的玩家
/// </summary>
/// <returns></returns>
public GameObject GetPlayer()
{
if (players == null || players.Count == 0)
return null;
GameObject nearestPlayer = null;
float minDistance = float.MaxValue;
foreach (var player in players.Values)
{
if (player == null) continue;
// 计算XZ平面距离使用你的 ReflectVectorXOZ 方法)
float dis = Vector3.Distance(
player.transform.position.ReflectVectorXOZ(),
transform.position.ReflectVectorXOZ()
);
if (dis < minDistance)
{
minDistance = dis;
nearestPlayer = player.gameObject;
}
}
return nearestPlayer;
}
/// <summary>
/// 获取最近敌人
/// </summary>
/// <returns></returns>
public GameObject GetEnemy(Transform playerAi)
{
if ( curEnemyList.Count == 0)
return null;
GameObject nearestPlayer = null;
float minDis = 999;
foreach (var enemy in curEnemyList)
{
if (enemy == null) continue;
// 计算XZ平面距离使用你的 ReflectVectorXOZ 方法)
float dis = Vector3.Distance(
enemy.transform.position.ReflectVectorXOZ(),
playerAi.position.ReflectVectorXOZ()
);
if (dis < minDis)
{
nearestPlayer = enemy.gameObject;
minDis = dis;
}
}
return nearestPlayer;
}
public void ChangePlayerAiCountdownTime()
{
foreach (var ai in PlayerAiList.Values)
{
ai.ChangeKillEnemyTime();
}
}
public Transform GetPlayerPos()
{
int rand = Random.Range(0, 100);
if (players.Count >= 2) // 双人模式
{
if (rand < 45) // 0-44
return players[0].transform; // 玩家A
else if (rand < 90) // 45-89
return players[1].transform; // 玩家B
else // 90-99
return PlayerAiList[0].transform; // 队友A
}
else // 单人模式
{
if (rand < 60) // 0-59
return players[0].transform; // 玩家
else if (rand < 80) // 60-79
return PlayerAiList[0].transform; // 队友A
else // 80-99
return PlayerAiList[1].transform; // 队友B
}
}
[Server]
public void CreateEnemyUI(Enemy enemy)
{
GameObject enemyUI = Instantiate(EnemyUIPre);
NetworkServer.Spawn(enemyUI);
EnemyUI enemyUIScript = enemyUI.GetComponent<EnemyUI>();
enemyUIScript.Init(enemy);
EnemyUIList.Add(enemy.id, enemyUIScript);
}
[Server]
public void DeleteEnemyUI(int id)
{
GameObject enemyUI = EnemyUIList[id].gameObject;
EnemyUIList.Remove(id);
NetworkServer.Destroy(enemyUI);
ChangePlayerAiCountdownTime();
}
[ClientRpc]
public void RpcShowHUD()
{
HUDPanel.Show();
}
#region
/// <summary>
/// 修复炮塔
/// </summary>
public void RepairTower()
{
}
/// <summary>
/// 进入联控
/// </summary>
[Server]
public void JoinControlTower(int playerIndex)
{
PlayJointMusic();
// 修改所有炮塔模式
foreach (Tower tower in TowerList.Values)
{
if (tower.controllerId == -1)
{
tower.controllerId = playerIndex;
tower.mode = TowerMode.Joint;
}
}
TriggerEvent("JoinControlStart", playerIndex);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
ChangeBgmRpc(1);
foreach (Tower tower in TowerList.Values)
{
if (tower.mode == TowerMode.Joint)
{
tower.controllerId = playerIndex;
tower.mode = tower.originalMode;
}
TriggerEvent("JoinControlEnd", playerIndex);
}
}, 30f);
}
#endregion
[ClientRpc]
public void TriggerEvent(string key, int param)
{
DragonLi.Core.EventDispatcher.TriggerEvent(key, param);
}
public void AddScore(string index, int damage)
{
if (SettleInfos.ContainsKey(index))
{
SettleInfos[index].Score += damage;
}
string jsonStr = JsonMapper.ToJson(SettleInfos);
settleData = jsonStr;
}
public void SetTitle(string index, string title)
{
if (SettleInfos.ContainsKey(index))
{
SettleInfos[index].Title = title;
}
Debug.Log(SettleInfos);
}
public void SetPlayerName(string index)
{
if (SettleInfos.ContainsKey(index))
{
SettleInfos[index].playerName = int.Parse(index);
}
}
[Server]
public void AddData(int playerIndex)
{
SettleInfos.Add(playerIndex.ToString(), new SettleInfo());
}
public string SerializeSettleInfos()
{
return JsonUtility.ToJson(SettleInfos);
}
public bool IsHaveEnemy()
{
return curEnemyList.Count > 0;
}
#region
public string GetLessTimeStr()
{
string res = "";
if (isStart)
{
res = FormatTime((int)(vistEnd - DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds));
}
return res;
}
public int GetLessTimeSeconds()
{
return (int)(vistEnd - DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds);
}
// 时分秒
public string FormatTime(int totalSeconds)
{
int hours = totalSeconds / 3600;
// string hh = hours < 10 ? "0" + hours : hours.ToString();
int minutes = (totalSeconds - hours * 3600) / 60;
string mm = minutes < 10f ? "0" + minutes : minutes.ToString();
int seconds = totalSeconds - hours * 3600 - minutes * 60;
string ss = seconds < 10 ? "0" + seconds : seconds.ToString();
return string.Format("{0}:{1}", mm, ss);
}
#endregion
public void PlaySound2DRPC(string sound)
{
MasterAudio.PlaySound(sound);
}
[ClientRpc]
public void PlaySound3DRPC(string sound,Transform tran,bool isStop)
{
if(isStop)
MasterAudio.StopAllSoundsOfTransform(tran);
MasterAudio.PlaySound3DAtTransform(sound, tran);
}
public void PlayJointMusic()
{
MasterAudio.PlaySound(JointIn);
GameLocal.Ins.BGMState.StateChange(2);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9deac3e9432775f428406d0fd530d351
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,253 @@
using System;
using System.Collections;
using System.Collections.Generic;
using BehaviorDesigner.Runtime.Tasks;
using TruegearSdk;
using UnityEngine;
public class TrueGearEffectManager : MonoBehaviour
{
public static TrueGearEffectManager Ins;
private void Awake()
{
Ins = this;
isAvailableIndex = 20;
GetConnectIndex = 20;
AddHitPart();
#if !UNITY_EDITOR
StartRequestTrueGear();
#endif
}
private void Start()
{
}
public void StartRequestTrueGear()
{
TruegearAndroidConnector androidConnector = new TruegearAndroidConnector();
androidConnector.InitShellJavaObject();
androidConnector.RequestPermission();
Debug.Log("开始连接");
StartCoroutine(TrueGearAndroidConnector());
}
public bool isGetConnect;
private int isAvailableIndex = 0;
private int GetConnectIndex;
IEnumerator TrueGearAndroidConnector()
{
TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance;
bool res = androidConnector.IsAvailable();
Debug.Log("蓝牙是否授权成功:"+res);
while (!res&& isAvailableIndex>0)
{
yield return new WaitForSeconds(1f);
Debug.Log("蓝牙尝试连接中....");
androidConnector.InitShellJavaObject();
androidConnector.RequestPermission();
res = androidConnector.IsAvailable();
isAvailableIndex--;
}
if (isAvailableIndex <= 0)
{
Debug.Log("蓝牙授权失败");
}
else
{
Debug.Log("蓝牙授权成功");
StartScanTrueGear();
while (!isGetConnect&& GetConnectIndex>0)
{
GetScanedDevices();
StartConnect();
yield return new WaitForSeconds(1);
Debug.Log("正在重新连接...");
GetConnectIndex--;
}
}
}
//搜索设备
public void StartScanTrueGear()
{
TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance;
bool res = androidConnector.IsAvailable();
if (res)
androidConnector.StartScan();
Debug.Log("OnStartScanClick" + res);
}
//获取设备列表
public void GetScanedDevices()
{
TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance;
bool res = androidConnector.IsAvailable();
Debug.Log("OnGetScanedDevicesClick" + res);
if (!res)
return;
List<DeviceData> res1 = androidConnector.GetScanedDevices();
string str = "";
foreach (var item in res1)
{
str += (string.Format("{0}, {1} ", item.name, item.address));
}
Debug.Log("OnGetScanedDevicesClick " + str);
}
//开始连接设备
public void StartConnect()
{
TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance;
bool res = androidConnector.IsAvailable();
Debug.Log("OnStartConnectClick" + res);
if (!res)
return;
List<DeviceData> res1 = androidConnector.GetScanedDevices();
Debug.Log(res1.ToString());
foreach (var item in res1)
{
{
androidConnector.ConnectToDevice(item.address);
Debug.Log(string.Format("Device Connect: {0}, {1}", item.name, item.address));
isGetConnect = true;
ChangeElectricalLevel();
return;
}
}
Debug.Log("No device found");
}
public void ChangeElectricalLevel()
{
TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance;
bool isZD= androidConnector.ModifyElectricalPercent(80);
Debug.LogError("是否震动:"+isZD);
}
/// <summary>
/// 断开连接
/// </summary>
public void CloseConnect()
{
TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance;
androidConnector.DisconnectFromDevice();
}
private void OnApplicationQuit()
{
//断开连接
Debug.Log("断开连接");
#if !UNITY_EDITOR
CloseConnect();
#endif
}
/// <summary>
/// 触发TrueGear震动
/// </summary>
/// <param name="effectName">效果名,可自定义</param>
/// <param name="motorIndex">作用的电机ID列表</param>
/// <param name="startTime">起始时间单位ms</param>
/// <param name="endTime">结束时间单位ms</param>
/// <param name="startIntensity">起始强度0-100</param>
/// <param name="endIntensity">结束强度0-100</param>
/// <param name="intensityMode">强度模式Const/Fade/FadeInAndOut</param>
/// <param name="actionType">震动位置</param>
public void PlayVibrationEffect(
string effectName,
List<int> motorIndex,
int startTime = 0,
int endTime = 300,
int startIntensity = 30,
int endIntensity = 30,
string intensityMode = "Const",
string actionType="Shake"
)
{
string indexStr = string.Join(",", motorIndex);
Debug.Log(indexStr);
string json = $@"
{{
""name"":""{effectName}"",
""uuid"":""{effectName}"",
""keep"":""False"",
""priority"": 0,
""tracks"":[
{{
""start_time"":{startTime},
""end_time"":{endTime},
""stop_name"":"""",
""start_intensity"":{startIntensity},
""end_intensity"":{endIntensity},
""intensity_mode"":""{intensityMode}"",
""action_type"":""{actionType}"",
""once"":""True"",
""interval"":1,
""index"":[{indexStr}]
}}
]
}}";
SendPlayEffectByContent(json);
}
public void SendPlayEffectByContent(string jsonStr)
{
TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance;
bool res = androidConnector.IsAvailable();
Debug.Log("OnTestClick" + res);
if (!res)
return;
androidConnector.SendPlayEffectByContent(jsonStr);
}
public List<string> hitParts=new List<string>();
public void AddHitPart()
{
hitParts.Add("leftUp");
hitParts.Add("leftDown");
hitParts.Add("rightUp");
hitParts.Add("rightDown");
hitParts.Add("rightAim");
}
public void OnHit(bool isUp, int index,bool isArm)
{
//ChangeElectricalLevel();
List<int> motorIDs = new List<int>();
string hitPart= hitParts[index];
switch (hitPart)
{
case "leftUp":
motorIDs.AddRange( isUp?new int[] { 0, 1, 4,5 }: new int[] { 100, 101, 104,105 }); break;
case "leftDown":
motorIDs.AddRange(isUp?new int[] { 8, 9, 12,13 }: new int[] { 108, 109, 112,113 }); break;
case "rightUp":
motorIDs.AddRange(isUp?new int[] { 2,3,6,7}: new int[] { 102, 103, 106,107 }); break;
case "rightDown":
motorIDs.AddRange(isUp?new int[] { 10,11,14,15}: new int[] { 114, 115, 118,119 }); break;
case "rightAim":
Debug.Log("xxzz");
motorIDs.AddRange(new int[] { 0,100}); break;
default:
motorIDs.Add(0); break;
}
PlayVibrationEffect(
effectName: $"Hit_{hitPart}",
motorIndex: motorIDs,
startIntensity: isArm?20:50,
endIntensity: isArm?20:50,
endTime: 400,
actionType: isArm? "Electrical" :"Shake"
);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e7c907821bb6e484689d92d3dc05f5a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: