NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/Team/TeamWrapperAdapter.cs

600 lines
19 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using PhxhSDK;
using Gameplay;
using Framework;
using System.Linq;
using UnityEngine;
using Gameplay.Net;
using Gameplay.Utils;
using Gameplay.Emoji;
using Gameplay.Common;
using GameWrapper.Team;
using Gameplay.Performance;
using UnityEngine.Playables;
using Cysharp.Threading.Tasks;
using cfg.VihecleCultivateCfg;
using System.Collections.Generic;
public class TeamPreviewImpl : ITeamPreviewService
{
private const string VehicleBatteryPointName = "Battery_point01";
private RenderTexture _rTexture;
private Transform[] characterPos;
private Transform[] vehiclesPos;
private Transform characterRoot;
private Transform vehicleRoot;
private uint[] _vehicleIDs;
private uint[] _charIDs;
private int _teamIdx;
private bool _isLoading;
private bool _isReleasing;
private Dictionary<int, GameObject> _vehicleDic;
private Dictionary<int, GameObject> _characterDic;
private readonly Dictionary<string, int> _assetsLoadDic = new();
private readonly List<UnitEmojiManager> _emojiMgrList = new();
private readonly Dictionary<Renderer, Shader[]> originalShaderDic = new();
public struct CharAddData
{
public uint ID;
public int Idx;
}
public struct VehicleAddData
{
public uint ID;
public int Idx;
}
public RenderTexture RTexture => _rTexture;
public void Init(Transform[] cPos, Transform[] vPos, Transform cRoot, Transform vRoot)
{
characterRoot = cRoot;
vehicleRoot = vRoot;
characterPos = cPos;
vehiclesPos = vPos;
_characterDic = new Dictionary<int, GameObject>();
_vehicleDic = new Dictionary<int, GameObject>();
EventManager.Instance.Register(EventManager.EventName.TeamEditCharacterModelCreate,
(Action<CharAddData>)OnCharModelCreate);
EventManager.Instance.Register(EventManager.EventName.TeamEditCharacterModelClear,
(Action<int>)OnCharModelClear);
EventManager.Instance.Register(EventManager.EventName.TeamEditVehicleModelCreate,
(Action<VehicleAddData>)OnVehicleModelCreate);
EventManager.Instance.Register(EventManager.EventName.TeamEditVehicleModelClear,
(Action<int>)OnVehicleModelClear);
EventManager.Instance.Register(EventManager.EventName.TeamEditAllModelClear, ClearAllGo);
EventManager.Instance.Register<ValueTuple<int, bool>>(EventManager.EventName.TeamEditModelUpdate,
RefreshNode);
EventManager.Instance.Register(EventManager.EventName.TeamCameraSet, _OnTeamEditCameraSet);
}
public void CreateRt()
{
if (!_rTexture)
{
_rTexture = RenderTexturePool.Instance.Create("TeamPreviewNode",
PerformanceManager.instance.fullScreenWidth,
PerformanceManager.instance.fullScreenHeight);
}
}
public void Release()
{
EventManager.Instance.Unregister(EventManager.EventName.TeamEditCharacterModelCreate,
(Action<CharAddData>)OnCharModelCreate);
EventManager.Instance.Unregister(EventManager.EventName.TeamEditCharacterModelClear,
(Action<int>)OnCharModelClear);
EventManager.Instance.Unregister(EventManager.EventName.TeamEditVehicleModelCreate,
(Action<VehicleAddData>)OnVehicleModelCreate);
EventManager.Instance.Unregister(EventManager.EventName.TeamEditVehicleModelClear,
(Action<int>)OnVehicleModelClear);
EventManager.Instance.Unregister(EventManager.EventName.TeamEditAllModelClear, ClearAllGo);
EventManager.Instance.Unregister<ValueTuple<int, bool>>(EventManager.EventName.TeamEditModelUpdate,
RefreshNode);
EventManager.Instance.Unregister(EventManager.EventName.TeamCameraSet, _OnTeamEditCameraSet);
UnLoad();
AssetManager.Instance.Unload(Framework.Constants.TEAM_EDIT_PREFAB_PATH);
}
public void ReleaseNode(TeamPreviewNode node)
{
ReleaseRt();
RestoreOriginalShaders();
UnityEngine.Object.Destroy(node.gameObject);
}
public async UniTask Refresh()
{
ClearObjs();
var teamCamera = TeamEditCameraObj.Instance.teamEditCamera;
teamCamera.targetTexture = _rTexture;
for (var i = 0; i < _charIDs.Length; i++)
{
var dataDic = CharacterDataInfoManager.Instance.DataDic;
var id = _charIDs[i];
var isValid = dataDic.ContainsKey(id);
if (isValid)
{
var trans = characterPos[i];
if (!_isLoading)
{
_isLoading = true;
await AddCharacterGo(trans, id, i);
}
}
}
for (var i = 0; i < _vehicleIDs.Length; i++)
{
var dataDic = VehicleCultivateDataManager.Instance.DataDic;
var id = _vehicleIDs[i];
var isValid = dataDic.ContainsKey(id);
if (isValid)
{
var trans = vehiclesPos[i];
if (!_isLoading)
{
_isLoading = true;
await AddVehicleGo(trans, id, i);
}
}
}
_isLoading = false;
}
public void SetData(int teamIdx, uint[] charIDs, uint[] vehicleIDs)
{
_teamIdx = teamIdx;
_charIDs = (uint[])charIDs.Clone();
_vehicleIDs = vehicleIDs;
}
private void UnLoad()
{
foreach (var kv in _assetsLoadDic)
{
var path = kv.Key;
AssetManager.Instance.Unload(path);
}
foreach (var emojiMgr in _emojiMgrList)
{
emojiMgr.Dispose();
}
_emojiMgrList.Clear();
_characterDic.Clear();
_vehicleDic.Clear();
}
private void ClearObjs()
{
characterRoot.transform.ClearChilds(true);
vehicleRoot.transform.ClearChilds(true);
_characterDic.Clear();
_vehicleDic.Clear();
}
private void ReleaseRt()
{
if (_rTexture)
{
RenderTexturePool.Instance.Destroy(_rTexture);
_rTexture = null;
}
}
public void Clear()
{
ClearAllGo();
_rTexture.Release();
}
#region 加载模型
/// <summary>
/// 添加角色模型
/// </summary>
async UniTask AddCharacterGo(Transform trans, uint id, int idx)
{
var charData = CharacterDataInfoManager.Instance.DataDic[id];
var charCfg = charData.Cfg;
var skinID = charData.SkinID > 0 ? (int)charData.SkinID : Framework.Constants.DEFULT_SKINID;
var data = TableManager.Instance.Tables.SkinCfg.Get(skinID, charCfg.RoleID);
if (data != null)
{
var prefabPath = PathEx.GetCharacterDisplayModelPath(data.NameID);
var prefab = await AssetManager.Instance.LoadAssetAsync<GameObject>(prefabPath);
_assetsLoadDic.TryAdd(prefabPath, (int)id);
if (!trans)
{
return;
}
var go = UnityEngine.Object.Instantiate(prefab, trans.position, trans.rotation,
characterRoot.transform);
if (go)
{
_characterDic[idx] = go;
go.SetLayerEx(LayerDefine.TeamEdit);
var anim = CommonUtils.GetChildComponent<Animator>(go);
var playableDir = go.GetComponent<PlayableDirector>();
if (playableDir)
{
playableDir.enabled = false;
}
if (anim)
{
int randomIdx = UnityEngine.Random.Range(0, 3);
// if (idx < 2 || idx > 4)
// {
// anim.Play("standready001");
// }
// else
// {
// anim.Play("squatready001");
// }
switch (randomIdx)
{
case 1:
{
anim.Play("standready001");
break;
}
case 2:
{
anim.Play("standready001");
break;
}
default:
{
anim.Play("squatready001");
break;
}
}
}
var charDataCfg = TableManager.Instance.Tables.CharacterAttri;
if (charDataCfg.DataMap.TryGetValue((int)id, out var charSingleData))
{
var emojiMgr = new UnitEmojiManager(go, charSingleData.EmojiEyesColor,
charSingleData.EmojiEyeBowsType, charSingleData.EmojiEyeBowsColor, true);
emojiMgr.SwitchEmoji(charSingleData.DefaultDisplayEmojiId);
_emojiMgrList.Add(emojiMgr);
}
}
}
_isLoading = false;
}
/// <summary>
/// 添加载具模型
/// </summary>
async UniTask AddVehicleGo(Transform trans, uint id, int idx)
{
var vehicleDataDic = VehicleCultivateDataManager.Instance.DataDic;
if (vehicleDataDic.TryGetValue(id, out var vehicleData))
{
if (vehicleData != null)
{
var prefabPath = PathEx.GetVehicleGameModelPath(vehicleData.Cfg.ID);
var prefab = await AssetManager.Instance.LoadAssetAsync<GameObject>(prefabPath);
ApplyVehicleShader(prefab);
_assetsLoadDic.TryAdd(prefabPath, (int)id);
if (!trans) return;
var go = UnityEngine.Object.Instantiate(prefab, trans.position, trans.rotation,
vehicleRoot.transform);
if (go)
{
_vehicleDic[idx] = go;
go.SetLayerEx(LayerDefine.TeamEdit);
go.transform.localScale = new Vector3(1.5f, 1.5f, 1.5f);
// 炮台部分
var config = VehicleDataHelper.CombineConfigData(vehicleData);
// 炮台挂点
var allTrans = go.GetComponentsInChildren<Transform>();
var fireTrans = allTrans.First(t => t.name == VehicleBatteryPointName);
var rawConfig = TableManager.Instance.Tables.BatteryConfig.GetOrDefault(config.weaponId);
var batteryPath = PathEx.GetBatteryModelPath(rawConfig.ModelPath);
var sampleObj = await AssetManager.Instance.LoadAssetAsync<GameObject>(batteryPath);
if (sampleObj != null)
{
var rootObj = UnityEngine.Object.Instantiate(sampleObj, fireTrans);
rootObj.SetLayerEx(LayerDefine.TeamEdit);
rootObj.transform.ResetLocals();
}
else
{
DebugUtil.LogError("加载炮台失败: {0}", batteryPath);
}
//设置涂装
var paintCfg = Actor.Instance.Character.GetVehicleDevelopment(id).paint_set;
if (paintCfg != null)
{
for (int i = 1; i < (int)PaintType.Max; i++)
{
var paintID = paintCfg[i];
if (paintID == 0)
continue;
var paintPath = PathEx.GetVehiclePaintPath((int)id, (int)paintID);
//加载涂装材质球
var material = await CommonUtils.GetVehiclePaintMaterial(paintPath); //临时方法
var root = VehicleDataHelper.FindVehiclePartRoot(go, (int)id, (PaintType)i);
if (material != null && root != null)
{
var instanceMaterial = new Material(material);
var renderers = root.GetComponent<SkinnedMeshRenderer>();
renderers.materials = new Material[] { instanceMaterial };
}
}
}
else
DebugUtil.LogError("载具涂装配置为空!");
}
}
}
_isLoading = false;
}
/// <summary>
/// 更换模型shader
/// </summary>
private void ChangeModelShader(GameObject prefab)
{
var vehicleRenderers = prefab.GetComponentsInChildren<Renderer>(true);
if (TeamEditManager.Instance.VehicleShader != null)
{
foreach (var vehicleRenderer in vehicleRenderers)
{
foreach (var material in vehicleRenderer.sharedMaterials)
{
material.shader = TeamEditManager.Instance.VehicleShader;
}
}
}
}
/// <summary>
/// 替换Shader,并缓存原始Shader 用于解决场景切换后模型蒙上未知来源阴影
/// </summary>
private void ApplyVehicleShader(GameObject prefab)
{
if (TeamEditManager.Instance.VehicleShader == null) return;
var vehicleRenderers = prefab.GetComponentsInChildren<Renderer>(true);
foreach (var vehicleRenderer in vehicleRenderers)
{
if (!originalShaderDic.ContainsKey(vehicleRenderer))
{
var originalShaders = new Shader[vehicleRenderer.sharedMaterials.Length];
for (int i = 0; i < vehicleRenderer.sharedMaterials.Length; i++)
{
originalShaders[i] = vehicleRenderer.sharedMaterials[i].shader;
}
originalShaderDic[vehicleRenderer] = originalShaders;
}
// 替换 Shader
foreach (var mat in vehicleRenderer.sharedMaterials)
{
mat.shader = TeamEditManager.Instance.VehicleShader;
}
}
}
/// <summary>
/// 还原Shader
/// </summary>
private void RestoreOriginalShaders()
{
foreach (var kvp in originalShaderDic)
{
var origRenderer = kvp.Key;
var originalShaders = kvp.Value;
var materials = origRenderer.sharedMaterials;
for (int i = 0; i < materials.Length && i < originalShaders.Length; i++)
{
materials[i].shader = originalShaders[i];
}
}
originalShaderDic.Clear();
}
/// <summary>
/// 根据索引加载角色模型
/// </summary>
private async UniTask LoadCharacterModel(uint id, int idx)
{
// DebugUtil.LogError("需要在:{0}加上{1}角色", idx, id);
if (idx < 0) return;
if (_isLoading) return;
if (_charIDs[idx] != id)
{
ClearCharacterGo(idx);
_charIDs[idx] = id;
_isLoading = true;
await AddCharacterGo(characterPos[idx], id, idx);
}
}
/// <summary>
/// 根据索引加载载具模型
/// </summary>
private async UniTask LoadVehicleModel(uint id, int idx)
{
//DebugUtil.LogError("需要在:{0}加上{1}载具", idx, id);
if (idx < 0) return;
if (_isLoading) return;
if (_vehicleIDs[idx] != id)
{
ClearVehicleGo(idx);
_vehicleIDs[idx] = id;
_isLoading = true;
await AddVehicleGo(vehiclesPos[idx], id, idx);
}
/*DebugUtil.LogError("添加完{0}位置,载具的关系:-------", idx);
for (int i = 0; i < _vehicleIDs.Length; i++)
{
DebugUtil.LogError("{0}位置是{1}", i, _vehicleIDs[i]);
}
DebugUtil.LogError("-----------------------");*/
}
#endregion
#region 清除模型
/// <summary>
/// 指挥官清空后使用
/// </summary>
private void ClearAllGo()
{
for (int i = 0; i < characterPos.Length; i++)
{
ClearCharacterGo(i);
}
for (int i = 0; i < vehiclesPos.Length; i++)
{
ClearVehicleGo(i);
}
}
private void ClearCharacterGo(int idx)
{
if (_isLoading)
{
return;
}
_isLoading = true;
if (_characterDic.TryGetValue(idx, out var go))
{
if (go)
{
UnityEngine.Object.DestroyImmediate(go);
_charIDs[idx] = Team.NoneID;
_characterDic.Remove(idx);
}
}
_isLoading = false;
}
private void ClearVehicleGo(int idx)
{
if (_isLoading)
{
return;
}
_isLoading = true;
if (_vehicleDic.TryGetValue(idx, out var go))
{
if (go)
{
UnityEngine.Object.DestroyImmediate(go);
_vehicleIDs[idx] = Team.NoneID;
_vehicleDic.Remove(idx);
}
}
_isLoading = false;
}
#endregion
#region 事件监听
private async void RefreshNode(ValueTuple<int, bool> data)
{
var team = TeamEditManager.Instance.GetTeamByIndex(data.Item1, data.Item2);
if (team == null) return;
var charIDs = team.GetAllCharacters().ToArray();
var vehicleIDs = team.GetVehicleIDs().ToArray();
SetData(data.Item1, charIDs, vehicleIDs);
await Refresh();
}
private async void OnCharModelCreate(CharAddData charAddData)
{
await LoadCharacterModel(charAddData.ID, charAddData.Idx);
}
private void OnCharModelClear(int idx)
{
if (idx >= 0)
{
ClearCharacterGo(idx);
}
}
private async void OnVehicleModelCreate(VehicleAddData vehicleAddData)
{
await LoadVehicleModel(vehicleAddData.ID, vehicleAddData.Idx);
}
private void OnVehicleModelClear(int idx)
{
if (idx >= 0)
{
ClearVehicleGo(idx);
}
}
private void _OnTeamEditCameraSet()
{
if (TeamEditCameraObj.Instance)
{
if (TeamEditCameraObj.Instance.teamEditCamera)
PerformanceManager.instance.SetCameraAntialiasing(TeamEditCameraObj.Instance.teamEditCamera);
}
}
#endregion
}
/// <summary>
/// 初始化器
/// </summary>
public static class TeamWrapperAdapter
{
public static void InitializeServices()
{
TeamServiceHandle.TeamPreviewService = new TeamPreviewImpl();
}
}