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

598 lines
18 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.Emoji;
using Gameplay.Utils;
using Gameplay.Common;
using Gameplay.Performance;
using UnityEngine.Playables;
using Cysharp.Threading.Tasks;
using System.Collections.Generic;
using Random = UnityEngine.Random;
using Constants = Framework.Constants;
using cfg.VihecleCultivateCfg;
using Gameplay.Net;
public class TeamPreviewNode : MonoBehaviour
{
private const string VehicleBatteryPointName = "Battery_point01";
public Transform[] characterPos;
public Transform[] vehiclesPos;
public Transform cRoot;
public Transform vRoot;
public struct CharAddData
{
public uint ID;
public int Idx;
}
public struct VehicleAddData
{
public uint ID;
public int Idx;
}
public RenderTexture RTexture => _rTexture;
private Dictionary<int, GameObject> _vehicleDic;
private Dictionary<int, GameObject> _characterDic;
private uint[] _vehicleIDs;
private uint[] _charIDs;
private bool _isLoading;
private int _teamIdx;
private bool _isReleasing;
private RenderTexture _rTexture;
private Dictionary<string, int> _assetsLoadDic = new Dictionary<string, int>();
private List<UnitEmojiManager> _emojiMgrList = new List<UnitEmojiManager>();
#region Static
public static async UniTask<TeamPreviewNode> LoadNode()
{
var prefab = await AssetManager.Instance.LoadAssetAsync<GameObject>(Constants.TEAM_EDIT_PREFAB_PATH);
var go = Instantiate(prefab, Vector3.up, Quaternion.identity);
var component = go.GetComponent<TeamPreviewNode>();
return component;
}
public static void ReleaseNode(TeamPreviewNode node)
{
node.ReleaseRt();
node.RestoreOriginalShaders();
Destroy(node.gameObject);
}
private void ReleaseRt()
{
if (_rTexture)
{
RenderTexturePool.Instance.Destroy(_rTexture);
_rTexture = null;
}
}
#endregion
#region MainLife
private void Awake()
{
_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);
}
private void OnDestroy()
{
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);
UnLoad();
AssetManager.Instance.Unload(Constants.TEAM_EDIT_PREFAB_PATH);
}
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()
{
cRoot.transform.ClearChilds(true);
vRoot.transform.ClearChilds(true);
_characterDic.Clear();
_vehicleDic.Clear();
}
#endregion
#region 对外方法
/// <summary>
/// 刷新节点
/// </summary>
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;
}
public void CreateRt()
{
if (!_rTexture)
{
_rTexture = RenderTexturePool.Instance.Create("TeamPreviewNode",
PerformanceManager.instance.fullScreenWidth,
PerformanceManager.instance.fullScreenHeight);
}
}
public void Clear()
{
ClearAllGo();
_rTexture.Release();
}
#endregion
#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 : 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 = Instantiate(prefab, trans.position, trans.rotation, cRoot.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 = 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);
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 = Instantiate(prefab, trans.position, trans.rotation, vRoot.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)
{
sampleObj.SetLayerEx(LayerDefine.TeamEdit);
var rootObj = Instantiate(sampleObj, fireTrans);
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 renderers = root.GetComponent<SkinnedMeshRenderer>();
renderers.materials = new Material[] { material };
}
}
}
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;
}
}
}
}
private Dictionary<Renderer, Shader[]> originalShaderDic = new Dictionary<Renderer, Shader[]>();
/// <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)
{
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)
{
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);
}
}
#endregion
}