693 lines
21 KiB
C#
693 lines
21 KiB
C#
|
|
using System;
|
|||
|
|
using UnityEngine;
|
|||
|
|
using UnityEngine.Playables;
|
|||
|
|
using Cysharp.Threading.Tasks;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Linq;
|
|||
|
|
using Framework;
|
|||
|
|
using Random = UnityEngine.Random;
|
|||
|
|
using GameWrapper.Team;
|
|||
|
|
using PhxhSDK;
|
|||
|
|
using Constants = Framework.Constants;
|
|||
|
|
|
|||
|
|
public class TeamPreviewNode : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
private const string VehicleBatteryPointName = "Battery_point01";
|
|||
|
|
private const string DEFAULT_SKINID_KEY = "DefaultSkinID";
|
|||
|
|
private const int DEFAULT_SKIN_ID = 1;
|
|||
|
|
|
|||
|
|
public Transform[] characterPos;
|
|||
|
|
public Transform[] vehiclesPos;
|
|||
|
|
public Transform cRoot;
|
|||
|
|
public Transform vRoot;
|
|||
|
|
|
|||
|
|
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<object> _emojiMgrList = new List<object>();
|
|||
|
|
|
|||
|
|
#region Static
|
|||
|
|
|
|||
|
|
public static async UniTask<TeamPreviewNode> LoadNode()
|
|||
|
|
{
|
|||
|
|
var prefab = await AssetManager.Instance.LoadAssetAsync<GameObject>(Framework.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);
|
|||
|
|
EventManager.Instance.Register(EventManager.EventName.TeamCameraSet, _OnTeamEditCameraSet);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
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);
|
|||
|
|
EventManager.Instance.Unregister(EventManager.EventName.TeamCameraSet, _OnTeamEditCameraSet);
|
|||
|
|
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)
|
|||
|
|
{
|
|||
|
|
TeamServiceHandle.CharacterService.DisposeEmojiManager(emojiMgr);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_emojiMgrList.Clear();
|
|||
|
|
|
|||
|
|
_characterDic.Clear();
|
|||
|
|
_vehicleDic.Clear();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void ClearObjs()
|
|||
|
|
{
|
|||
|
|
foreach (Transform child in cRoot)
|
|||
|
|
{
|
|||
|
|
Destroy(child.gameObject);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
foreach (Transform child in vRoot)
|
|||
|
|
{
|
|||
|
|
Destroy(child.gameObject);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_characterDic.Clear();
|
|||
|
|
_vehicleDic.Clear();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 对外方法
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 刷新节点
|
|||
|
|
/// </summary>
|
|||
|
|
public async UniTask Refresh()
|
|||
|
|
{
|
|||
|
|
ClearObjs();
|
|||
|
|
|
|||
|
|
var teamCamera = TeamServiceHandle.TeamEditCameraObj.teamEditCamera;
|
|||
|
|
teamCamera.targetTexture = _rTexture;
|
|||
|
|
|
|||
|
|
for (var i = 0; i < _charIDs.Length; i++)
|
|||
|
|
{
|
|||
|
|
var id = _charIDs[i];
|
|||
|
|
var isValid = TeamServiceHandle.CharacterService.CharacterDataDicContainsKey(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 id = _vehicleIDs[i];
|
|||
|
|
var isValid = TeamServiceHandle.VehicleService.VehicleDataDicContainsKey(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", Screen.width,
|
|||
|
|
Screen.height);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void Clear()
|
|||
|
|
{
|
|||
|
|
ClearAllGo();
|
|||
|
|
_rTexture.Release();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 加载模型
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 添加角色模型
|
|||
|
|
/// </summary>
|
|||
|
|
async UniTask AddCharacterGo(Transform trans, uint id, int idx)
|
|||
|
|
{
|
|||
|
|
var charData = TeamServiceHandle.CharacterService.GetCharacterData(id);
|
|||
|
|
|
|||
|
|
// 获取角色配置信息
|
|||
|
|
var charCfg = GetField<object>(charData, "Cfg");
|
|||
|
|
var skinID = GetField<uint>(charData, "SkinID") > 0
|
|||
|
|
? (int)GetField<uint>(charData, "SkinID")
|
|||
|
|
: GetDefaultSkinId();
|
|||
|
|
var roleID = GetField<int>(charCfg, "RoleID");
|
|||
|
|
|
|||
|
|
var data = TeamServiceHandle.TableService.GetSkinConfig(skinID, roleID);
|
|||
|
|
if (data != null)
|
|||
|
|
{
|
|||
|
|
var nameID = GetField<string>(data, "NameID");
|
|||
|
|
var prefabPath = TeamServiceHandle.CharacterService.GetCharacterDisplayModelPath(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;
|
|||
|
|
// TODO 层级优化
|
|||
|
|
go.SetLayerEx(9);
|
|||
|
|
var anim = go.GetComponentInChildren<Animator>();
|
|||
|
|
var playableDir = go.GetComponent<PlayableDirector>();
|
|||
|
|
if (playableDir)
|
|||
|
|
{
|
|||
|
|
playableDir.enabled = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (anim)
|
|||
|
|
{
|
|||
|
|
int randomIdx = Random.Range(0, 3);
|
|||
|
|
switch (randomIdx)
|
|||
|
|
{
|
|||
|
|
case 1:
|
|||
|
|
{
|
|||
|
|
anim.Play("standready001");
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
case 2:
|
|||
|
|
{
|
|||
|
|
anim.Play("standready001");
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
default:
|
|||
|
|
{
|
|||
|
|
anim.Play("squatready001");
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 处理角色表情
|
|||
|
|
object charSingleData = null;
|
|||
|
|
if (TeamServiceHandle.TableService.TryGetCharacterAttriData((int)id, out var data2))
|
|||
|
|
{
|
|||
|
|
charSingleData = data2;
|
|||
|
|
|
|||
|
|
var eyesColor = GetField<string>(charSingleData, "EmojiEyesColor");
|
|||
|
|
var eyeBrowsType = GetField<string>(charSingleData, "EmojiEyeBowsType");
|
|||
|
|
var eyeBrowsColor = GetField<string>(charSingleData, "EmojiEyeBowsColor");
|
|||
|
|
var defaultEmojiId = GetField<int>(charSingleData, "DefaultDisplayEmojiId");
|
|||
|
|
|
|||
|
|
var emojiMgr = TeamServiceHandle.CharacterService.CreateEmojiManager(
|
|||
|
|
go, eyesColor, eyeBrowsType, eyeBrowsColor, true);
|
|||
|
|
|
|||
|
|
TeamServiceHandle.CharacterService.SwitchEmoji(emojiMgr, defaultEmojiId);
|
|||
|
|
_emojiMgrList.Add(emojiMgr);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_isLoading = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 添加载具模型
|
|||
|
|
/// </summary>
|
|||
|
|
async UniTask AddVehicleGo(Transform trans, uint id, int idx)
|
|||
|
|
{
|
|||
|
|
var vehicleData = TeamServiceHandle.VehicleService.GetVehicleData(id);
|
|||
|
|
|
|||
|
|
if (vehicleData != null)
|
|||
|
|
{
|
|||
|
|
var vehicleCfg = GetField<object>(vehicleData, "Cfg");
|
|||
|
|
var vehicleId = GetField<int>(vehicleCfg, "ID");
|
|||
|
|
|
|||
|
|
var prefabPath = TeamServiceHandle.VehicleService.GetVehicleGameModelPath(vehicleId);
|
|||
|
|
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;
|
|||
|
|
// TODO 层级优化
|
|||
|
|
go.SetLayerEx(9);
|
|||
|
|
go.transform.localScale = new Vector3(1.5f, 1.5f, 1.5f);
|
|||
|
|
|
|||
|
|
// 炮台部分
|
|||
|
|
var config = TeamServiceHandle.VehicleService.CombineConfigData(vehicleData);
|
|||
|
|
|
|||
|
|
// 获取武器ID
|
|||
|
|
var weaponId = GetField<long>(config, "weaponId");
|
|||
|
|
|
|||
|
|
// 炮台挂点
|
|||
|
|
var allTrans = go.GetComponentsInChildren<Transform>();
|
|||
|
|
var fireTrans = allTrans.First(t => t.name == VehicleBatteryPointName);
|
|||
|
|
|
|||
|
|
var rawConfig = TeamServiceHandle.TableService.GetBatteryConfig(weaponId);
|
|||
|
|
var modelPath = GetField<string>(rawConfig, "ModelPath");
|
|||
|
|
var batteryPath = TeamServiceHandle.VehicleService.GetBatteryModelPath(modelPath);
|
|||
|
|
var sampleObj = await AssetManager.Instance.LoadAssetAsync<GameObject>(batteryPath);
|
|||
|
|
if (sampleObj != null)
|
|||
|
|
{
|
|||
|
|
var rootObj = UnityEngine.Object.Instantiate(sampleObj, fireTrans);
|
|||
|
|
// TODO 层级优化
|
|||
|
|
go.SetLayerEx(9);
|
|||
|
|
rootObj.transform.localPosition = Vector3.zero;
|
|||
|
|
rootObj.transform.localRotation = Quaternion.identity;
|
|||
|
|
rootObj.transform.localScale = Vector3.one;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"加载炮台失败: {batteryPath}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//设置涂装
|
|||
|
|
var vehicleDev = TeamServiceHandle.VehicleService.GetVehicleDevelopment(id);
|
|||
|
|
var paintCfg = GetField<int[]>(vehicleDev, "paint_set");
|
|||
|
|
|
|||
|
|
if (paintCfg != null)
|
|||
|
|
{
|
|||
|
|
for (int i = 1; i < (int)TeamPaintType.Max; i++)
|
|||
|
|
{
|
|||
|
|
var paintID = paintCfg[i];
|
|||
|
|
if (paintID == 0)
|
|||
|
|
continue;
|
|||
|
|
|
|||
|
|
var paintPath = TeamServiceHandle.VehicleService.GetVehiclePaintPath((int)id, paintID);
|
|||
|
|
|
|||
|
|
//加载涂装材质球
|
|||
|
|
var material = await TeamServiceHandle.VehicleService.GetVehiclePaintMaterial(paintPath);
|
|||
|
|
var root = TeamServiceHandle.VehicleService.FindVehiclePartRoot(go, (int)id, (TeamPaintType)i);
|
|||
|
|
|
|||
|
|
if (material != null && root != null)
|
|||
|
|
{
|
|||
|
|
var instanceMaterial = new Material(material);
|
|||
|
|
var renderers = root.GetComponent<SkinnedMeshRenderer>();
|
|||
|
|
renderers.materials = new Material[] { instanceMaterial };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
Debug.LogError("载具涂装配置为空!");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_isLoading = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 设置游戏对象及其子对象的层级
|
|||
|
|
/// </summary>
|
|||
|
|
private void SetLayerRecursively(GameObject obj, int layer)
|
|||
|
|
{
|
|||
|
|
obj.layer = layer;
|
|||
|
|
foreach (Transform child in obj.transform)
|
|||
|
|
{
|
|||
|
|
SetLayerRecursively(child.gameObject, layer);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 更换模型shader
|
|||
|
|
/// </summary>
|
|||
|
|
private void ChangeModelShader(GameObject prefab)
|
|||
|
|
{
|
|||
|
|
var vehicleShader = TeamServiceHandle.TeamService.GetVehicleShader();
|
|||
|
|
var vehicleRenderers = prefab.GetComponentsInChildren<Renderer>(true);
|
|||
|
|
|
|||
|
|
if (vehicleShader != null)
|
|||
|
|
{
|
|||
|
|
foreach (var vehicleRenderer in vehicleRenderers)
|
|||
|
|
{
|
|||
|
|
foreach (var material in vehicleRenderer.sharedMaterials)
|
|||
|
|
{
|
|||
|
|
material.shader = vehicleShader;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private Dictionary<Renderer, Shader[]> originalShaderDic = new Dictionary<Renderer, Shader[]>();
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 替换Shader,并缓存原始Shader 用于解决场景切换后模型蒙上未知来源阴影
|
|||
|
|
/// </summary>
|
|||
|
|
private void ApplyVehicleShader(GameObject prefab)
|
|||
|
|
{
|
|||
|
|
var vehicleShader = TeamServiceHandle.TeamService.GetVehicleShader();
|
|||
|
|
if (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 = 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)
|
|||
|
|
{
|
|||
|
|
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)
|
|||
|
|
{
|
|||
|
|
if (idx < 0) return;
|
|||
|
|
if (_isLoading) return;
|
|||
|
|
if (_vehicleIDs[idx] != id)
|
|||
|
|
{
|
|||
|
|
ClearVehicleGo(idx);
|
|||
|
|
_vehicleIDs[idx] = id;
|
|||
|
|
_isLoading = true;
|
|||
|
|
await AddVehicleGo(vehiclesPos[idx], id, idx);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#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] = TeamServiceHandle.TeamService.GetTeamNoneID();
|
|||
|
|
_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] = TeamServiceHandle.TeamService.GetTeamNoneID();
|
|||
|
|
_vehicleDic.Remove(idx);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_isLoading = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 事件监听
|
|||
|
|
|
|||
|
|
private async void RefreshNode(ValueTuple<int, bool> data)
|
|||
|
|
{
|
|||
|
|
var team = TeamServiceHandle.TeamService.GetTeamByIndex(data.Item1, data.Item2);
|
|||
|
|
if (team == null) return;
|
|||
|
|
var charIDs = TeamServiceHandle.TeamService.GetAllCharacters(team);
|
|||
|
|
var vehicleIDs = TeamServiceHandle.TeamService.GetVehicleIDs(team);
|
|||
|
|
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 (TeamServiceHandle.TeamEditCameraObj != null && TeamServiceHandle.TeamEditCameraObj.teamEditCamera != null)
|
|||
|
|
{
|
|||
|
|
TeamServiceHandle.TeamEditCameraObj.SetCameraAntialiasing(
|
|||
|
|
TeamServiceHandle.TeamEditCameraObj.teamEditCamera);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region Helpers
|
|||
|
|
|
|||
|
|
private int GetDefaultSkinId()
|
|||
|
|
{
|
|||
|
|
return DEFAULT_SKIN_ID;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 通过反射获取对象字段值
|
|||
|
|
// 通过反射获取对象字段值,添加更健壮的类型转换
|
|||
|
|
private T GetField<T>(object obj, string fieldName)
|
|||
|
|
{
|
|||
|
|
if (obj == null) return default;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var field = obj.GetType().GetField(fieldName);
|
|||
|
|
if (field != null)
|
|||
|
|
{
|
|||
|
|
var value = field.GetValue(obj);
|
|||
|
|
if (value == null) return default;
|
|||
|
|
|
|||
|
|
// 尝试直接转换
|
|||
|
|
if (value is T typedValue)
|
|||
|
|
return typedValue;
|
|||
|
|
|
|||
|
|
// 尝试从其他类型转换
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
return (T)Convert.ChangeType(value, typeof(T));
|
|||
|
|
}
|
|||
|
|
catch
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning($"无法将类型 {value.GetType()} 转换为 {typeof(T)} - 字段名: {fieldName}");
|
|||
|
|
return default;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var property = obj.GetType().GetProperty(fieldName);
|
|||
|
|
if (property != null)
|
|||
|
|
{
|
|||
|
|
var value = property.GetValue(obj);
|
|||
|
|
if (value == null) return default;
|
|||
|
|
|
|||
|
|
// 尝试直接转换
|
|||
|
|
if (value is T typedValue)
|
|||
|
|
return typedValue;
|
|||
|
|
|
|||
|
|
// 尝试从其他类型转换
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
return (T)Convert.ChangeType(value, typeof(T));
|
|||
|
|
}
|
|||
|
|
catch
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning($"无法将类型 {value.GetType()} 转换为 {typeof(T)} - 属性名: {fieldName}");
|
|||
|
|
return default;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Debug.LogWarning($"对象 {obj.GetType()} 中未找到字段或属性: {fieldName}");
|
|||
|
|
return default;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"从对象 {obj.GetType()} 获取字段 {fieldName} 时发生异常: {ex.Message}");
|
|||
|
|
return default;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
}
|