598 lines
18 KiB
C#
598 lines
18 KiB
C#
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
|
||
} |