Add player profile system
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bb501fa36e5ab8c4ca5c128ba1c27f5b
|
||||||
|
PrefabImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 731c3655c93ed604c92315654f622432
|
||||||
|
PrefabImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using XGame;
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
using XGame.EditorTools;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public sealed class PlayerProfileModuleTests
|
||||||
|
{
|
||||||
|
[TearDown]
|
||||||
|
public void TearDown()
|
||||||
|
{
|
||||||
|
PlayerProfileStore.ResetToDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void DefaultProfile_HasPlayableCombatStats()
|
||||||
|
{
|
||||||
|
PlayerProfileData profile = PlayerProfileData.CreateDefault();
|
||||||
|
|
||||||
|
Assert.That(profile.Nickname, Is.EqualTo("Player"));
|
||||||
|
Assert.That(profile.Uid, Is.EqualTo("0"));
|
||||||
|
Assert.That(profile.Lv, Is.EqualTo(1));
|
||||||
|
Assert.That(profile.HpMax, Is.GreaterThan(0));
|
||||||
|
Assert.That(profile.Hp, Is.EqualTo(profile.HpMax));
|
||||||
|
Assert.That(profile.MpMax, Is.GreaterThan(0));
|
||||||
|
Assert.That(profile.Mp, Is.EqualTo(profile.MpMax));
|
||||||
|
Assert.That(profile.Ad, Is.GreaterThan(0));
|
||||||
|
Assert.That(profile.MoveSpeed, Is.GreaterThan(0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Replace_SanitizesInvalidValuesAndRaisesChanged()
|
||||||
|
{
|
||||||
|
int changed = 0;
|
||||||
|
Action<PlayerProfileData> handler = _ => changed++;
|
||||||
|
PlayerProfileStore.Changed += handler;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PlayerProfileStore.Replace(new PlayerProfileData
|
||||||
|
{
|
||||||
|
Nickname = "Alice",
|
||||||
|
Uid = "42",
|
||||||
|
AvatarId = -1,
|
||||||
|
RoleType = PlayerRoleType.Mage,
|
||||||
|
Lv = -5,
|
||||||
|
Exp = -20,
|
||||||
|
Hp = 999,
|
||||||
|
HpMax = 100,
|
||||||
|
Mp = -3,
|
||||||
|
MpMax = 50,
|
||||||
|
AtkSpeed = -1f,
|
||||||
|
MoveSpeed = -2f
|
||||||
|
});
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
PlayerProfileStore.Changed -= handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerProfileData current = PlayerProfileStore.Current;
|
||||||
|
Assert.That(changed, Is.EqualTo(1));
|
||||||
|
Assert.That(current.AvatarId, Is.EqualTo(0));
|
||||||
|
Assert.That(current.Lv, Is.EqualTo(1));
|
||||||
|
Assert.That(current.Exp, Is.EqualTo(0));
|
||||||
|
Assert.That(current.Hp, Is.EqualTo(100));
|
||||||
|
Assert.That(current.Mp, Is.EqualTo(0));
|
||||||
|
Assert.That(current.AtkSpeed, Is.GreaterThan(0f));
|
||||||
|
Assert.That(current.MoveSpeed, Is.GreaterThan(0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Experience01_ClampsAgainstLevelRequirement()
|
||||||
|
{
|
||||||
|
PlayerProfileData profile = PlayerProfileData.CreateDefault();
|
||||||
|
profile.Lv = 2;
|
||||||
|
profile.Exp = 150;
|
||||||
|
|
||||||
|
Assert.That(profile.Experience01, Is.EqualTo(0.75f).Within(0.001f));
|
||||||
|
|
||||||
|
profile.Exp = 999;
|
||||||
|
Assert.That(profile.Experience01, Is.EqualTo(1f));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
[Test]
|
||||||
|
public void PlayerProfileJsonFiles_PassPrefabBuilderValidation()
|
||||||
|
{
|
||||||
|
Assert.That(JsonUIPrefabBuilder.Validate("../Doc/UIPrefabCreater/UI_PlayerProfileHud.json").Ok, Is.True);
|
||||||
|
Assert.That(JsonUIPrefabBuilder.Validate("../Doc/UIPrefabCreater/UI_PlayerProfilePanel.json").Ok, Is.True);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3b4203a5eef50434ca57e39295869354
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -41,6 +41,7 @@ namespace XGame
|
|||||||
private MiniGameStageIsolation stageIsolation;
|
private MiniGameStageIsolation stageIsolation;
|
||||||
private LobbyWorldController lobbyWorld;
|
private LobbyWorldController lobbyWorld;
|
||||||
private WorldChatModule worldChat;
|
private WorldChatModule worldChat;
|
||||||
|
private PlayerProfileModule playerProfile;
|
||||||
private readonly List<GameInfoMsg> games = new List<GameInfoMsg>();
|
private readonly List<GameInfoMsg> games = new List<GameInfoMsg>();
|
||||||
private readonly List<NetMessage> pendingGameMessages = new List<NetMessage>();
|
private readonly List<NetMessage> pendingGameMessages = new List<NetMessage>();
|
||||||
private readonly HashSet<int> canceledMatchRequestIds = new HashSet<int>();
|
private readonly HashSet<int> canceledMatchRequestIds = new HashSet<int>();
|
||||||
@@ -129,6 +130,7 @@ namespace XGame
|
|||||||
lobbyActive = false;
|
lobbyActive = false;
|
||||||
lobbyWorld?.SendLeave();
|
lobbyWorld?.SendLeave();
|
||||||
CloseWorldChat();
|
CloseWorldChat();
|
||||||
|
ClosePlayerProfile();
|
||||||
lobbyNet = null;
|
lobbyNet = null;
|
||||||
socket?.close();
|
socket?.close();
|
||||||
socket = null;
|
socket = null;
|
||||||
@@ -315,6 +317,8 @@ namespace XGame
|
|||||||
private void EnterLobby()
|
private void EnterLobby()
|
||||||
{
|
{
|
||||||
CloseLoginPanel();
|
CloseLoginPanel();
|
||||||
|
SyncPlayerProfile();
|
||||||
|
EnsurePlayerProfileModule();
|
||||||
OpenLobby();
|
OpenLobby();
|
||||||
ConnectLobby();
|
ConnectLobby();
|
||||||
}
|
}
|
||||||
@@ -886,6 +890,40 @@ namespace XGame
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void EnsurePlayerProfileModule()
|
||||||
|
{
|
||||||
|
if (playerProfile == null)
|
||||||
|
{
|
||||||
|
playerProfile = gameObject.GetComponent<PlayerProfileModule>();
|
||||||
|
if (playerProfile == null)
|
||||||
|
{
|
||||||
|
playerProfile = gameObject.AddComponent<PlayerProfileModule>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!playerProfile.IsOpen)
|
||||||
|
{
|
||||||
|
XWCoroutine.StartCo(playerProfile.OpenAsync());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClosePlayerProfile()
|
||||||
|
{
|
||||||
|
if (playerProfile != null)
|
||||||
|
{
|
||||||
|
playerProfile.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SyncPlayerProfile()
|
||||||
|
{
|
||||||
|
int pid = GetLobbyPlayerId();
|
||||||
|
PlayerProfileStore.SetSessionIdentity(
|
||||||
|
GetLobbyPlayerName(),
|
||||||
|
pid.ToString(CultureInfo.InvariantCulture),
|
||||||
|
pid <= 0 ? 0 : pid % 8 + 1,
|
||||||
|
PlayerRoleType.Adventurer);
|
||||||
|
}
|
||||||
|
|
||||||
private static string GetLobbyPlayerName()
|
private static string GetLobbyPlayerName()
|
||||||
{
|
{
|
||||||
string account = XData.GetString(LoginAccountKey, string.Empty);
|
string account = XData.GetString(LoginAccountKey, string.Empty);
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 15830dfd44b61334f8fb32f2e70da201
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace XGame
|
||||||
|
{
|
||||||
|
public enum PlayerRoleType
|
||||||
|
{
|
||||||
|
Adventurer = 0,
|
||||||
|
Warrior = 1,
|
||||||
|
Mage = 2,
|
||||||
|
Archer = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public sealed class PlayerProfileData
|
||||||
|
{
|
||||||
|
public string Nickname = "Player";
|
||||||
|
public string Uid = "0";
|
||||||
|
public int AvatarId;
|
||||||
|
public PlayerRoleType RoleType = PlayerRoleType.Adventurer;
|
||||||
|
public int Gold;
|
||||||
|
public int Diamond;
|
||||||
|
public int Lv = 1;
|
||||||
|
public int Exp;
|
||||||
|
public int Hp = 100;
|
||||||
|
public int HpMax = 100;
|
||||||
|
public int Mp = 50;
|
||||||
|
public int MpMax = 50;
|
||||||
|
public int Ad = 10;
|
||||||
|
public int Ap = 5;
|
||||||
|
public float AtkSpeed = 1f;
|
||||||
|
public float MoveSpeed = 4f;
|
||||||
|
|
||||||
|
public int RequiredExp => Mathf.Max(100, Lv * 100);
|
||||||
|
public float Experience01 => Mathf.Clamp01((float)Mathf.Max(0, Exp) / RequiredExp);
|
||||||
|
|
||||||
|
public static PlayerProfileData CreateDefault()
|
||||||
|
{
|
||||||
|
PlayerProfileData data = new PlayerProfileData();
|
||||||
|
data.Normalize();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerProfileData Clone()
|
||||||
|
{
|
||||||
|
return (PlayerProfileData)MemberwiseClone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Normalize()
|
||||||
|
{
|
||||||
|
Nickname = string.IsNullOrWhiteSpace(Nickname) ? "Player" : Nickname.Trim();
|
||||||
|
Uid = string.IsNullOrWhiteSpace(Uid) ? "0" : Uid.Trim();
|
||||||
|
AvatarId = Mathf.Max(0, AvatarId);
|
||||||
|
Gold = Mathf.Max(0, Gold);
|
||||||
|
Diamond = Mathf.Max(0, Diamond);
|
||||||
|
Lv = Mathf.Max(1, Lv);
|
||||||
|
Exp = Mathf.Max(0, Exp);
|
||||||
|
HpMax = Mathf.Max(1, HpMax);
|
||||||
|
MpMax = Mathf.Max(1, MpMax);
|
||||||
|
Hp = Mathf.Clamp(Hp, 0, HpMax);
|
||||||
|
Mp = Mathf.Clamp(Mp, 0, MpMax);
|
||||||
|
Ad = Mathf.Max(0, Ad);
|
||||||
|
Ap = Mathf.Max(0, Ap);
|
||||||
|
AtkSpeed = Mathf.Max(0.01f, AtkSpeed);
|
||||||
|
MoveSpeed = Mathf.Max(0.01f, MoveSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b80a1b74b02355444aefdcc7c580468b
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,247 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UObject = UnityEngine.Object;
|
||||||
|
|
||||||
|
namespace XGame
|
||||||
|
{
|
||||||
|
public sealed class PlayerProfileModule : MonoBehaviour
|
||||||
|
{
|
||||||
|
private const string HudPrefabPath = "Assets/Game/Art/UI/Prefab/UI_PlayerProfileHud.prefab";
|
||||||
|
private const string PanelPrefabPath = "Assets/Game/Art/UI/Prefab/UI_PlayerProfilePanel.prefab";
|
||||||
|
|
||||||
|
private GameObject hudView;
|
||||||
|
private GameObject detailView;
|
||||||
|
private bool openingHud;
|
||||||
|
private bool openingDetail;
|
||||||
|
private int openVersion;
|
||||||
|
|
||||||
|
private TMP_Text hudNicknameText;
|
||||||
|
private TMP_Text hudLevelText;
|
||||||
|
private TMP_Text hudExpText;
|
||||||
|
private RectTransform hudExpFill;
|
||||||
|
private RectTransform hudExpTrack;
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
PlayerProfileStore.Changed += OnProfileChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
PlayerProfileStore.Changed -= OnProfileChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsOpen => hudView != null;
|
||||||
|
|
||||||
|
public IEnumerator OpenAsync()
|
||||||
|
{
|
||||||
|
if (hudView != null || openingHud)
|
||||||
|
{
|
||||||
|
RefreshAll(PlayerProfileStore.Current);
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
openingHud = true;
|
||||||
|
int version = ++openVersion;
|
||||||
|
UObject loaded = null;
|
||||||
|
yield return XResLoader.coLoadRes(HudPrefabPath, typeof(GameObject), obj => loaded = obj);
|
||||||
|
openingHud = false;
|
||||||
|
|
||||||
|
if (version != openVersion)
|
||||||
|
{
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject prefab = loaded as GameObject;
|
||||||
|
if (prefab == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("[PlayerProfileModule] load HUD prefab failed: " + HudPrefabPath);
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
hudView = Instantiate(prefab);
|
||||||
|
UIManager.AttachTo(UILayer.HUD, hudView);
|
||||||
|
CacheHudControls();
|
||||||
|
BindHudEvents();
|
||||||
|
RefreshHud(PlayerProfileStore.Current);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
openVersion++;
|
||||||
|
openingHud = false;
|
||||||
|
openingDetail = false;
|
||||||
|
if (hudView != null)
|
||||||
|
{
|
||||||
|
Destroy(hudView);
|
||||||
|
}
|
||||||
|
if (detailView != null)
|
||||||
|
{
|
||||||
|
Destroy(detailView);
|
||||||
|
}
|
||||||
|
hudView = null;
|
||||||
|
detailView = null;
|
||||||
|
hudNicknameText = null;
|
||||||
|
hudLevelText = null;
|
||||||
|
hudExpText = null;
|
||||||
|
hudExpFill = null;
|
||||||
|
hudExpTrack = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnProfileChanged(PlayerProfileData profile)
|
||||||
|
{
|
||||||
|
RefreshAll(profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshAll(PlayerProfileData profile)
|
||||||
|
{
|
||||||
|
RefreshHud(profile);
|
||||||
|
RefreshDetail(profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CacheHudControls()
|
||||||
|
{
|
||||||
|
if (hudView == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hudNicknameText = FindComponent<TMP_Text>(hudView, "Txt_Nickname");
|
||||||
|
hudLevelText = FindComponent<TMP_Text>(hudView, "Txt_Level");
|
||||||
|
hudExpText = FindComponent<TMP_Text>(hudView, "Txt_Exp");
|
||||||
|
hudExpTrack = FindRect(hudView, "Img_ExpBg");
|
||||||
|
hudExpFill = FindRect(hudView, "Img_ExpFill");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BindHudEvents()
|
||||||
|
{
|
||||||
|
Button button = FindComponent<Button>(hudView, "Btn_Profile");
|
||||||
|
if (button == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
button.onClick.RemoveAllListeners();
|
||||||
|
button.onClick.AddListener(OpenDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshHud(PlayerProfileData profile)
|
||||||
|
{
|
||||||
|
if (hudView == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
profile = profile ?? PlayerProfileStore.Current;
|
||||||
|
if (hudNicknameText != null) hudNicknameText.text = profile.Nickname;
|
||||||
|
if (hudLevelText != null) hudLevelText.text = "Lv." + profile.Lv;
|
||||||
|
if (hudExpText != null) hudExpText.text = profile.Exp + "/" + profile.RequiredExp;
|
||||||
|
|
||||||
|
if (hudExpTrack != null && hudExpFill != null)
|
||||||
|
{
|
||||||
|
float width = Mathf.Max(0f, hudExpTrack.rect.width);
|
||||||
|
hudExpFill.sizeDelta = new Vector2(width * profile.Experience01, hudExpFill.sizeDelta.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OpenDetail()
|
||||||
|
{
|
||||||
|
if (detailView != null || openingDetail)
|
||||||
|
{
|
||||||
|
RefreshDetail(PlayerProfileStore.Current);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
XWCoroutine.StartCo(CoOpenDetail());
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator CoOpenDetail()
|
||||||
|
{
|
||||||
|
openingDetail = true;
|
||||||
|
UObject loaded = null;
|
||||||
|
yield return XResLoader.coLoadRes(PanelPrefabPath, typeof(GameObject), obj => loaded = obj);
|
||||||
|
openingDetail = false;
|
||||||
|
|
||||||
|
GameObject prefab = loaded as GameObject;
|
||||||
|
if (prefab == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("[PlayerProfileModule] load detail prefab failed: " + PanelPrefabPath);
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
detailView = Instantiate(prefab);
|
||||||
|
UIManager.AttachTo(UILayer.Dialog, detailView);
|
||||||
|
BindDetailEvents();
|
||||||
|
RefreshDetail(PlayerProfileStore.Current);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BindDetailEvents()
|
||||||
|
{
|
||||||
|
BindCloseButton("Btn_Close");
|
||||||
|
BindCloseButton("Img_Mask");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BindCloseButton(string nodeName)
|
||||||
|
{
|
||||||
|
Button button = FindComponent<Button>(detailView, nodeName);
|
||||||
|
if (button == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
button.onClick.RemoveAllListeners();
|
||||||
|
button.onClick.AddListener(CloseDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CloseDetail()
|
||||||
|
{
|
||||||
|
if (detailView != null)
|
||||||
|
{
|
||||||
|
Destroy(detailView);
|
||||||
|
}
|
||||||
|
detailView = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshDetail(PlayerProfileData profile)
|
||||||
|
{
|
||||||
|
if (detailView == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
profile = profile ?? PlayerProfileStore.Current;
|
||||||
|
SetText("Txt_Nickname", profile.Nickname);
|
||||||
|
SetText("Txt_Uid", "UID: " + profile.Uid);
|
||||||
|
SetText("Txt_RoleType", profile.RoleType.ToString());
|
||||||
|
SetText("Txt_Gold", profile.Gold.ToString());
|
||||||
|
SetText("Txt_Diamond", profile.Diamond.ToString());
|
||||||
|
SetText("Txt_Lv", profile.Lv.ToString());
|
||||||
|
SetText("Txt_Exp", profile.Exp + "/" + profile.RequiredExp);
|
||||||
|
SetText("Txt_Hp", profile.Hp + "/" + profile.HpMax);
|
||||||
|
SetText("Txt_Mp", profile.Mp + "/" + profile.MpMax);
|
||||||
|
SetText("Txt_Ad", profile.Ad.ToString());
|
||||||
|
SetText("Txt_Ap", profile.Ap.ToString());
|
||||||
|
SetText("Txt_AtkSpeed", profile.AtkSpeed.ToString("0.##"));
|
||||||
|
SetText("Txt_MoveSpeed", profile.MoveSpeed.ToString("0.##"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetText(string nodeName, string value)
|
||||||
|
{
|
||||||
|
TMP_Text text = FindComponent<TMP_Text>(detailView, nodeName);
|
||||||
|
if (text != null)
|
||||||
|
{
|
||||||
|
text.text = value ?? string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RectTransform FindRect(GameObject root, string nodeName)
|
||||||
|
{
|
||||||
|
Transform t = root == null ? null : root.transform.FindTransform(nodeName);
|
||||||
|
return t == null ? null : t.GetComponent<RectTransform>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static T FindComponent<T>(GameObject root, string nodeName) where T : Component
|
||||||
|
{
|
||||||
|
Transform t = root == null ? null : root.transform.FindTransform(nodeName);
|
||||||
|
return t == null ? null : t.GetComponent<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b19aceb62ce32574ab5918471bc49d8d
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace XGame
|
||||||
|
{
|
||||||
|
public static class PlayerProfileStore
|
||||||
|
{
|
||||||
|
private static PlayerProfileData current = PlayerProfileData.CreateDefault();
|
||||||
|
|
||||||
|
public static event Action<PlayerProfileData> Changed;
|
||||||
|
|
||||||
|
public static PlayerProfileData Current => current.Clone();
|
||||||
|
|
||||||
|
public static void Replace(PlayerProfileData profile)
|
||||||
|
{
|
||||||
|
current = profile == null ? PlayerProfileData.CreateDefault() : profile.Clone();
|
||||||
|
current.Normalize();
|
||||||
|
Changed?.Invoke(Current);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Update(Action<PlayerProfileData> updater)
|
||||||
|
{
|
||||||
|
PlayerProfileData next = Current;
|
||||||
|
updater?.Invoke(next);
|
||||||
|
Replace(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ResetToDefault()
|
||||||
|
{
|
||||||
|
Replace(PlayerProfileData.CreateDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetSessionIdentity(string nickname, string uid, int avatarId = 0, PlayerRoleType roleType = PlayerRoleType.Adventurer)
|
||||||
|
{
|
||||||
|
Update(profile =>
|
||||||
|
{
|
||||||
|
profile.Nickname = nickname;
|
||||||
|
profile.Uid = uid;
|
||||||
|
profile.AvatarId = avatarId;
|
||||||
|
profile.RoleType = roleType;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 87850bdd4bcb84c4a953202d393f0003
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,263 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"prefabName": "UI_PlayerProfileHud",
|
||||||
|
"prefabPath": "Assets/Game/Art/UI/Prefab/UI_PlayerProfileHud.prefab",
|
||||||
|
"description": "HUD layer player profile entry for lobby and mini games. Runtime PlayerProfileModule binds Btn_Profile/Txt_Nickname/Txt_Level/Txt_Exp/Img_ExpBg/Img_ExpFill and opens the detail panel on click.",
|
||||||
|
"canvas": {
|
||||||
|
"canvasScaler": {
|
||||||
|
"referenceResolution": [2048, 1024],
|
||||||
|
"matchWidthOrHeight": 0.5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"assets": {
|
||||||
|
"sprites": {
|
||||||
|
"ui_panel_content": "Assets/Game/Art/UI/Texture/Common/ui_panel_content.png",
|
||||||
|
"avatar_frame": "Assets/Game/Art/UI/Texture/Common/avatar_frame.png",
|
||||||
|
"ico_user": "Assets/Game/Art/UI/Texture/Common/ico_user.png",
|
||||||
|
"ui_badge_base": "Assets/Game/Art/UI/Texture/Common/ui_badge_base.png",
|
||||||
|
"progress_bg": "Assets/Game/Art/UI/Texture/Common/progress_bg.png",
|
||||||
|
"progress_fill_green": "Assets/Game/Art/UI/Texture/Common/progress_fill_green.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"name": "UI_PlayerProfileHud",
|
||||||
|
"parent": null,
|
||||||
|
"active": true,
|
||||||
|
"rect": {
|
||||||
|
"anchorMin": [0, 1],
|
||||||
|
"anchorMax": [0, 1],
|
||||||
|
"pivot": [0, 1],
|
||||||
|
"anchoredPosition": [24, -24],
|
||||||
|
"sizeDelta": [424, 136]
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "CanvasGroup",
|
||||||
|
"alpha": 0.98,
|
||||||
|
"interactable": true,
|
||||||
|
"blocksRaycasts": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Btn_Profile",
|
||||||
|
"parent": "UI_PlayerProfileHud",
|
||||||
|
"active": true,
|
||||||
|
"rect": {
|
||||||
|
"anchorMin": [0, 0],
|
||||||
|
"anchorMax": [1, 1],
|
||||||
|
"offsetMin": [0, 0],
|
||||||
|
"offsetMax": [0, 0]
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "Image",
|
||||||
|
"sprite": "ui_panel_content",
|
||||||
|
"imageType": "Sliced",
|
||||||
|
"raycastTarget": true,
|
||||||
|
"color": "#FFFFFFFF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Button",
|
||||||
|
"onClick": "PlayerProfile.OpenDetail"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Shadow",
|
||||||
|
"effectColor": "#06101F66",
|
||||||
|
"effectDistance": [0, -6],
|
||||||
|
"useGraphicAlpha": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Img_AvatarFrame",
|
||||||
|
"parent": "Btn_Profile",
|
||||||
|
"active": true,
|
||||||
|
"rect": {
|
||||||
|
"anchorMin": [0, 0.5],
|
||||||
|
"anchorMax": [0, 0.5],
|
||||||
|
"pivot": [0.5, 0.5],
|
||||||
|
"anchoredPosition": [68, 0],
|
||||||
|
"sizeDelta": [96, 96]
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "Image",
|
||||||
|
"sprite": "avatar_frame",
|
||||||
|
"imageType": "Sliced",
|
||||||
|
"raycastTarget": false,
|
||||||
|
"color": "#FFFFFFFF"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Img_AvatarIcon",
|
||||||
|
"parent": "Img_AvatarFrame",
|
||||||
|
"active": true,
|
||||||
|
"rect": {
|
||||||
|
"anchorMin": [0.5, 0.5],
|
||||||
|
"anchorMax": [0.5, 0.5],
|
||||||
|
"pivot": [0.5, 0.5],
|
||||||
|
"anchoredPosition": [0, 0],
|
||||||
|
"sizeDelta": [56, 56]
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "Image",
|
||||||
|
"sprite": "ico_user",
|
||||||
|
"imageType": "Simple",
|
||||||
|
"preserveAspect": true,
|
||||||
|
"raycastTarget": false,
|
||||||
|
"color": "#FFFFFFFF"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Txt_Nickname",
|
||||||
|
"parent": "Btn_Profile",
|
||||||
|
"active": true,
|
||||||
|
"rect": {
|
||||||
|
"anchorMin": [0, 1],
|
||||||
|
"anchorMax": [0, 1],
|
||||||
|
"pivot": [0, 1],
|
||||||
|
"anchoredPosition": [132, -22],
|
||||||
|
"sizeDelta": [188, 34]
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "TextMeshProUGUI",
|
||||||
|
"text": "Player",
|
||||||
|
"fontSize": 26,
|
||||||
|
"fontStyle": "Bold",
|
||||||
|
"alignment": "Left",
|
||||||
|
"color": "#33405EFF",
|
||||||
|
"raycastTarget": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Badge_Level",
|
||||||
|
"parent": "Btn_Profile",
|
||||||
|
"active": true,
|
||||||
|
"rect": {
|
||||||
|
"anchorMin": [1, 1],
|
||||||
|
"anchorMax": [1, 1],
|
||||||
|
"pivot": [1, 1],
|
||||||
|
"anchoredPosition": [-22, -18],
|
||||||
|
"sizeDelta": [74, 38]
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "Image",
|
||||||
|
"sprite": "ui_badge_base",
|
||||||
|
"imageType": "Sliced",
|
||||||
|
"raycastTarget": false,
|
||||||
|
"color": "#FFFFFFFF"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Txt_Level",
|
||||||
|
"parent": "Badge_Level",
|
||||||
|
"active": true,
|
||||||
|
"rect": {
|
||||||
|
"anchorMin": [0, 0],
|
||||||
|
"anchorMax": [1, 1],
|
||||||
|
"offsetMin": [0, 0],
|
||||||
|
"offsetMax": [0, 0]
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "TextMeshProUGUI",
|
||||||
|
"text": "Lv.1",
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontStyle": "Bold",
|
||||||
|
"alignment": "Center",
|
||||||
|
"color": "#F6F8FFFF",
|
||||||
|
"raycastTarget": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Outline",
|
||||||
|
"effectColor": "#102033CC",
|
||||||
|
"effectDistance": [1, -1],
|
||||||
|
"useGraphicAlpha": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Img_ExpBg",
|
||||||
|
"parent": "Btn_Profile",
|
||||||
|
"active": true,
|
||||||
|
"rect": {
|
||||||
|
"anchorMin": [0, 0],
|
||||||
|
"anchorMax": [1, 0],
|
||||||
|
"pivot": [0.5, 0],
|
||||||
|
"anchoredPosition": [66, 26],
|
||||||
|
"sizeDelta": [-170, 28]
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "Image",
|
||||||
|
"sprite": "progress_bg",
|
||||||
|
"imageType": "Sliced",
|
||||||
|
"raycastTarget": false,
|
||||||
|
"color": "#FFFFFFFF"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Img_ExpFill",
|
||||||
|
"parent": "Img_ExpBg",
|
||||||
|
"active": true,
|
||||||
|
"rect": {
|
||||||
|
"anchorMin": [0, 0.5],
|
||||||
|
"anchorMax": [0, 0.5],
|
||||||
|
"pivot": [0, 0.5],
|
||||||
|
"anchoredPosition": [0, 0],
|
||||||
|
"sizeDelta": [1, 22]
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "Image",
|
||||||
|
"sprite": "progress_fill_green",
|
||||||
|
"imageType": "Sliced",
|
||||||
|
"raycastTarget": false,
|
||||||
|
"color": "#FFFFFFFF"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Txt_Exp",
|
||||||
|
"parent": "Img_ExpBg",
|
||||||
|
"active": true,
|
||||||
|
"rect": {
|
||||||
|
"anchorMin": [0, 0],
|
||||||
|
"anchorMax": [1, 1],
|
||||||
|
"offsetMin": [0, 0],
|
||||||
|
"offsetMax": [0, 0]
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "TextMeshProUGUI",
|
||||||
|
"text": "0/100",
|
||||||
|
"fontSize": 18,
|
||||||
|
"fontStyle": "Bold",
|
||||||
|
"alignment": "Center",
|
||||||
|
"color": "#F6F8FFFF",
|
||||||
|
"raycastTarget": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Outline",
|
||||||
|
"effectColor": "#102033CC",
|
||||||
|
"effectDistance": [1, -1],
|
||||||
|
"useGraphicAlpha": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bindings": ["Btn_Profile", "Txt_Nickname", "Txt_Level", "Txt_Exp", "Img_ExpBg", "Img_ExpFill"],
|
||||||
|
"events": [
|
||||||
|
{ "name": "PlayerProfile.OpenDetail", "node": "Btn_Profile" }
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,221 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"prefabName": "UI_PlayerProfilePanel",
|
||||||
|
"prefabPath": "Assets/Game/Art/UI/Prefab/UI_PlayerProfilePanel.prefab",
|
||||||
|
"description": "Dialog layer player profile detail panel. Runtime PlayerProfileModule binds all Txt_* values and Btn_Close/Img_Mask close actions.",
|
||||||
|
"canvas": {
|
||||||
|
"canvasScaler": {
|
||||||
|
"referenceResolution": [2048, 1024],
|
||||||
|
"matchWidthOrHeight": 0.5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"assets": {
|
||||||
|
"sprites": {
|
||||||
|
"ui_overlay_dim": "Assets/Game/Art/UI/Texture/Common/ui_overlay_dim.png",
|
||||||
|
"ui_panel_popup": "Assets/Game/Art/UI/Texture/Common/ui_panel_popup.png",
|
||||||
|
"ui_panel_header": "Assets/Game/Art/UI/Texture/Common/ui_panel_header.png",
|
||||||
|
"ui_panel_content": "Assets/Game/Art/UI/Texture/Common/ui_panel_content.png",
|
||||||
|
"ui_list_item_normal": "Assets/Game/Art/UI/Texture/Common/ui_list_item_normal.png",
|
||||||
|
"avatar_frame": "Assets/Game/Art/UI/Texture/Common/avatar_frame.png",
|
||||||
|
"btn_close": "Assets/Game/Art/UI/Texture/Common/btn_close.png",
|
||||||
|
"ico_user": "Assets/Game/Art/UI/Texture/Common/ico_user.png",
|
||||||
|
"ico_coin": "Assets/Game/Art/UI/Texture/Common/ico_coin.png",
|
||||||
|
"ico_diamond": "Assets/Game/Art/UI/Texture/Common/ico_diamond.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"name": "UI_PlayerProfilePanel",
|
||||||
|
"parent": null,
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0, 0], "anchorMax": [1, 1], "offsetMin": [0, 0], "offsetMax": [0, 0] },
|
||||||
|
"components": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Img_Mask",
|
||||||
|
"parent": "UI_PlayerProfilePanel",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0, 0], "anchorMax": [1, 1], "offsetMin": [0, 0], "offsetMax": [0, 0] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "Image", "sprite": "ui_overlay_dim", "imageType": "Simple", "raycastTarget": true, "color": "#FFFFFFFF" },
|
||||||
|
{ "type": "Button", "onClick": "PlayerProfile.CloseDetail" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Panel_Profile",
|
||||||
|
"parent": "UI_PlayerProfilePanel",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0.5, 0.5], "anchorMax": [0.5, 0.5], "pivot": [0.5, 0.5], "anchoredPosition": [0, 0], "sizeDelta": [780, 740] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "Image", "sprite": "ui_panel_popup", "imageType": "Sliced", "raycastTarget": true, "color": "#FFFFFFFF" },
|
||||||
|
{ "type": "Shadow", "effectColor": "#06101F80", "effectDistance": [0, -8], "useGraphicAlpha": true }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Img_Header",
|
||||||
|
"parent": "Panel_Profile",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0, 1], "anchorMax": [1, 1], "pivot": [0.5, 1], "anchoredPosition": [0, -22], "sizeDelta": [-54, 82] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "Image", "sprite": "ui_panel_header", "imageType": "Sliced", "raycastTarget": false, "color": "#FFFFFFFF" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Txt_Title",
|
||||||
|
"parent": "Img_Header",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0, 0], "anchorMax": [1, 1], "offsetMin": [0, 0], "offsetMax": [0, 0] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "TextMeshProUGUI", "text": "Role Profile", "fontSize": 38, "fontStyle": "Bold", "alignment": "Center", "color": "#F6F8FFFF", "raycastTarget": false },
|
||||||
|
{ "type": "Outline", "effectColor": "#102033CC", "effectDistance": [1, -1], "useGraphicAlpha": true }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Btn_Close",
|
||||||
|
"parent": "Panel_Profile",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [1, 1], "anchorMax": [1, 1], "pivot": [0.5, 0.5], "anchoredPosition": [-38, -36], "sizeDelta": [64, 64] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "Image", "sprite": "btn_close", "imageType": "Simple", "preserveAspect": true, "raycastTarget": true, "color": "#FFFFFFFF" },
|
||||||
|
{ "type": "Button", "onClick": "PlayerProfile.CloseDetail" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Panel_Identity",
|
||||||
|
"parent": "Panel_Profile",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0, 1], "anchorMax": [1, 1], "pivot": [0.5, 1], "anchoredPosition": [0, -124], "sizeDelta": [-64, 164] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "Image", "sprite": "ui_panel_content", "imageType": "Sliced", "raycastTarget": false, "color": "#FFFFFFFF" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Img_AvatarFrame",
|
||||||
|
"parent": "Panel_Identity",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0, 0.5], "anchorMax": [0, 0.5], "pivot": [0.5, 0.5], "anchoredPosition": [86, 0], "sizeDelta": [112, 112] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "Image", "sprite": "avatar_frame", "imageType": "Sliced", "raycastTarget": false, "color": "#FFFFFFFF" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Img_AvatarIcon",
|
||||||
|
"parent": "Img_AvatarFrame",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0.5, 0.5], "anchorMax": [0.5, 0.5], "pivot": [0.5, 0.5], "anchoredPosition": [0, 0], "sizeDelta": [64, 64] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "Image", "sprite": "ico_user", "imageType": "Simple", "preserveAspect": true, "raycastTarget": false, "color": "#FFFFFFFF" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Txt_Nickname",
|
||||||
|
"parent": "Panel_Identity",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0, 1], "anchorMax": [0, 1], "pivot": [0, 1], "anchoredPosition": [164, -32], "sizeDelta": [330, 44] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "TextMeshProUGUI", "text": "Player", "fontSize": 34, "fontStyle": "Bold", "alignment": "Left", "color": "#33405EFF", "raycastTarget": false }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Txt_Uid",
|
||||||
|
"parent": "Panel_Identity",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0, 1], "anchorMax": [0, 1], "pivot": [0, 1], "anchoredPosition": [166, -82], "sizeDelta": [280, 30] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "TextMeshProUGUI", "text": "UID: 0", "fontSize": 22, "alignment": "Left", "color": "#5A4632FF", "raycastTarget": false }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Txt_RoleType",
|
||||||
|
"parent": "Panel_Identity",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [1, 1], "anchorMax": [1, 1], "pivot": [1, 1], "anchoredPosition": [-34, -44], "sizeDelta": [180, 38] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "TextMeshProUGUI", "text": "Adventurer", "fontSize": 26, "fontStyle": "Bold", "alignment": "Right", "color": "#1E84C8FF", "raycastTarget": false }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Panel_Currencies",
|
||||||
|
"parent": "Panel_Profile",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0, 1], "anchorMax": [1, 1], "pivot": [0.5, 1], "anchoredPosition": [0, -306], "sizeDelta": [-64, 72] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "Image", "sprite": "ui_panel_content", "imageType": "Sliced", "raycastTarget": false, "color": "#FFFFFFFF" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Img_GoldIcon",
|
||||||
|
"parent": "Panel_Currencies",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0, 0.5], "anchorMax": [0, 0.5], "pivot": [0.5, 0.5], "anchoredPosition": [58, 0], "sizeDelta": [48, 48] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "Image", "sprite": "ico_coin", "imageType": "Simple", "preserveAspect": true, "raycastTarget": false, "color": "#FFFFFFFF" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Txt_Gold",
|
||||||
|
"parent": "Panel_Currencies",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0, 0], "anchorMax": [0.5, 1], "offsetMin": [96, 0], "offsetMax": [-18, 0] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "TextMeshProUGUI", "text": "0", "fontSize": 28, "fontStyle": "Bold", "alignment": "Left", "color": "#C88010FF", "raycastTarget": false }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Img_DiamondIcon",
|
||||||
|
"parent": "Panel_Currencies",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0.5, 0.5], "anchorMax": [0.5, 0.5], "pivot": [0.5, 0.5], "anchoredPosition": [56, 0], "sizeDelta": [48, 48] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "Image", "sprite": "ico_diamond", "imageType": "Simple", "preserveAspect": true, "raycastTarget": false, "color": "#FFFFFFFF" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Txt_Diamond",
|
||||||
|
"parent": "Panel_Currencies",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0.5, 0], "anchorMax": [1, 1], "offsetMin": [96, 0], "offsetMax": [-24, 0] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "TextMeshProUGUI", "text": "0", "fontSize": 28, "fontStyle": "Bold", "alignment": "Left", "color": "#1E84C8FF", "raycastTarget": false }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Panel_Stats",
|
||||||
|
"parent": "Panel_Profile",
|
||||||
|
"active": true,
|
||||||
|
"rect": { "anchorMin": [0, 0], "anchorMax": [1, 1], "offsetMin": [32, 34], "offsetMax": [-32, -402] },
|
||||||
|
"components": [
|
||||||
|
{ "type": "Image", "sprite": "ui_panel_content", "imageType": "Sliced", "raycastTarget": false, "color": "#FFFFFFFF" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ "name": "Row_Lv", "parent": "Panel_Stats", "active": true, "rect": { "anchorMin": [0, 1], "anchorMax": [0.5, 1], "pivot": [0.5, 1], "anchoredPosition": [0, -22], "sizeDelta": [-28, 52] }, "components": [{ "type": "Image", "sprite": "ui_list_item_normal", "imageType": "Sliced", "raycastTarget": false, "color": "#FFFFFFFF" }] },
|
||||||
|
{ "name": "Txt_LabelLv", "parent": "Row_Lv", "active": true, "rect": { "anchorMin": [0, 0], "anchorMax": [0.55, 1], "offsetMin": [20, 0], "offsetMax": [0, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "Level", "fontSize": 24, "alignment": "Left", "color": "#5A4632FF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Txt_Lv", "parent": "Row_Lv", "active": true, "rect": { "anchorMin": [0.55, 0], "anchorMax": [1, 1], "offsetMin": [0, 0], "offsetMax": [-18, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "1", "fontSize": 24, "fontStyle": "Bold", "alignment": "Right", "color": "#33405EFF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Row_Exp", "parent": "Panel_Stats", "active": true, "rect": { "anchorMin": [0.5, 1], "anchorMax": [1, 1], "pivot": [0.5, 1], "anchoredPosition": [0, -22], "sizeDelta": [-28, 52] }, "components": [{ "type": "Image", "sprite": "ui_list_item_normal", "imageType": "Sliced", "raycastTarget": false, "color": "#FFFFFFFF" }] },
|
||||||
|
{ "name": "Txt_LabelExp", "parent": "Row_Exp", "active": true, "rect": { "anchorMin": [0, 0], "anchorMax": [0.45, 1], "offsetMin": [20, 0], "offsetMax": [0, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "Exp", "fontSize": 24, "alignment": "Left", "color": "#5A4632FF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Txt_Exp", "parent": "Row_Exp", "active": true, "rect": { "anchorMin": [0.45, 0], "anchorMax": [1, 1], "offsetMin": [0, 0], "offsetMax": [-18, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "0/100", "fontSize": 24, "fontStyle": "Bold", "alignment": "Right", "color": "#33405EFF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Row_Hp", "parent": "Panel_Stats", "active": true, "rect": { "anchorMin": [0, 1], "anchorMax": [0.5, 1], "pivot": [0.5, 1], "anchoredPosition": [0, -90], "sizeDelta": [-28, 52] }, "components": [{ "type": "Image", "sprite": "ui_list_item_normal", "imageType": "Sliced", "raycastTarget": false, "color": "#FFFFFFFF" }] },
|
||||||
|
{ "name": "Txt_LabelHp", "parent": "Row_Hp", "active": true, "rect": { "anchorMin": [0, 0], "anchorMax": [0.45, 1], "offsetMin": [20, 0], "offsetMax": [0, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "HP", "fontSize": 24, "alignment": "Left", "color": "#5A4632FF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Txt_Hp", "parent": "Row_Hp", "active": true, "rect": { "anchorMin": [0.45, 0], "anchorMax": [1, 1], "offsetMin": [0, 0], "offsetMax": [-18, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "100/100", "fontSize": 24, "fontStyle": "Bold", "alignment": "Right", "color": "#D63333FF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Row_Mp", "parent": "Panel_Stats", "active": true, "rect": { "anchorMin": [0.5, 1], "anchorMax": [1, 1], "pivot": [0.5, 1], "anchoredPosition": [0, -90], "sizeDelta": [-28, 52] }, "components": [{ "type": "Image", "sprite": "ui_list_item_normal", "imageType": "Sliced", "raycastTarget": false, "color": "#FFFFFFFF" }] },
|
||||||
|
{ "name": "Txt_LabelMp", "parent": "Row_Mp", "active": true, "rect": { "anchorMin": [0, 0], "anchorMax": [0.45, 1], "offsetMin": [20, 0], "offsetMax": [0, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "MP", "fontSize": 24, "alignment": "Left", "color": "#5A4632FF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Txt_Mp", "parent": "Row_Mp", "active": true, "rect": { "anchorMin": [0.45, 0], "anchorMax": [1, 1], "offsetMin": [0, 0], "offsetMax": [-18, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "50/50", "fontSize": 24, "fontStyle": "Bold", "alignment": "Right", "color": "#1E84C8FF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Row_Ad", "parent": "Panel_Stats", "active": true, "rect": { "anchorMin": [0, 1], "anchorMax": [0.5, 1], "pivot": [0.5, 1], "anchoredPosition": [0, -158], "sizeDelta": [-28, 52] }, "components": [{ "type": "Image", "sprite": "ui_list_item_normal", "imageType": "Sliced", "raycastTarget": false, "color": "#FFFFFFFF" }] },
|
||||||
|
{ "name": "Txt_LabelAd", "parent": "Row_Ad", "active": true, "rect": { "anchorMin": [0, 0], "anchorMax": [0.55, 1], "offsetMin": [20, 0], "offsetMax": [0, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "AD", "fontSize": 24, "alignment": "Left", "color": "#5A4632FF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Txt_Ad", "parent": "Row_Ad", "active": true, "rect": { "anchorMin": [0.55, 0], "anchorMax": [1, 1], "offsetMin": [0, 0], "offsetMax": [-18, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "10", "fontSize": 24, "fontStyle": "Bold", "alignment": "Right", "color": "#33405EFF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Row_Ap", "parent": "Panel_Stats", "active": true, "rect": { "anchorMin": [0.5, 1], "anchorMax": [1, 1], "pivot": [0.5, 1], "anchoredPosition": [0, -158], "sizeDelta": [-28, 52] }, "components": [{ "type": "Image", "sprite": "ui_list_item_normal", "imageType": "Sliced", "raycastTarget": false, "color": "#FFFFFFFF" }] },
|
||||||
|
{ "name": "Txt_LabelAp", "parent": "Row_Ap", "active": true, "rect": { "anchorMin": [0, 0], "anchorMax": [0.55, 1], "offsetMin": [20, 0], "offsetMax": [0, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "AP", "fontSize": 24, "alignment": "Left", "color": "#5A4632FF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Txt_Ap", "parent": "Row_Ap", "active": true, "rect": { "anchorMin": [0.55, 0], "anchorMax": [1, 1], "offsetMin": [0, 0], "offsetMax": [-18, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "5", "fontSize": 24, "fontStyle": "Bold", "alignment": "Right", "color": "#33405EFF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Row_AtkSpeed", "parent": "Panel_Stats", "active": true, "rect": { "anchorMin": [0, 1], "anchorMax": [0.5, 1], "pivot": [0.5, 1], "anchoredPosition": [0, -226], "sizeDelta": [-28, 52] }, "components": [{ "type": "Image", "sprite": "ui_list_item_normal", "imageType": "Sliced", "raycastTarget": false, "color": "#FFFFFFFF" }] },
|
||||||
|
{ "name": "Txt_LabelAtkSpeed", "parent": "Row_AtkSpeed", "active": true, "rect": { "anchorMin": [0, 0], "anchorMax": [0.55, 1], "offsetMin": [20, 0], "offsetMax": [0, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "Atk Spd", "fontSize": 24, "alignment": "Left", "color": "#5A4632FF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Txt_AtkSpeed", "parent": "Row_AtkSpeed", "active": true, "rect": { "anchorMin": [0.55, 0], "anchorMax": [1, 1], "offsetMin": [0, 0], "offsetMax": [-18, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "1", "fontSize": 24, "fontStyle": "Bold", "alignment": "Right", "color": "#33405EFF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Row_MoveSpeed", "parent": "Panel_Stats", "active": true, "rect": { "anchorMin": [0.5, 1], "anchorMax": [1, 1], "pivot": [0.5, 1], "anchoredPosition": [0, -226], "sizeDelta": [-28, 52] }, "components": [{ "type": "Image", "sprite": "ui_list_item_normal", "imageType": "Sliced", "raycastTarget": false, "color": "#FFFFFFFF" }] },
|
||||||
|
{ "name": "Txt_LabelMoveSpeed", "parent": "Row_MoveSpeed", "active": true, "rect": { "anchorMin": [0, 0], "anchorMax": [0.55, 1], "offsetMin": [20, 0], "offsetMax": [0, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "Move Spd", "fontSize": 24, "alignment": "Left", "color": "#5A4632FF", "raycastTarget": false }] },
|
||||||
|
{ "name": "Txt_MoveSpeed", "parent": "Row_MoveSpeed", "active": true, "rect": { "anchorMin": [0.55, 0], "anchorMax": [1, 1], "offsetMin": [0, 0], "offsetMax": [-18, 0] }, "components": [{ "type": "TextMeshProUGUI", "text": "4", "fontSize": 24, "fontStyle": "Bold", "alignment": "Right", "color": "#33405EFF", "raycastTarget": false }] }
|
||||||
|
],
|
||||||
|
"bindings": ["Img_Mask", "Btn_Close", "Txt_Nickname", "Txt_Uid", "Txt_RoleType", "Txt_Gold", "Txt_Diamond", "Txt_Lv", "Txt_Exp", "Txt_Hp", "Txt_Mp", "Txt_Ad", "Txt_Ap", "Txt_AtkSpeed", "Txt_MoveSpeed"],
|
||||||
|
"events": [
|
||||||
|
{ "name": "PlayerProfile.CloseDetail", "node": "Btn_Close" },
|
||||||
|
{ "name": "PlayerProfile.CloseDetail", "node": "Img_Mask" }
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user