```
feat(gameplay): 实现护盾系统和强化增益选择机制 - 新增护盾功能,包括护盾数值显示和护盾条UI - 重构盾卫技能,实现坚固壁垒技能效果 - 添加暴击率、吸血率等战斗属性 - 优化增益选择界面,新增传奇品质和刷新机制 - 调整材质纹理和文字着色器效果 - 修复金币显示格式问题 ```
This commit is contained in:
1 parent
336ec9980d
commit
48395ab414
27 files changed
+10343
-128
No files matched your search
Binary file not shown.
|
After Width: | Height: | Size: 165 KiB |
@@ -46,7 +46,7 @@ Material:
|
|||||||
m_Scale: {x: 3, y: 4}
|
m_Scale: {x: 3, y: 4}
|
||||||
m_Offset: {x: 0, y: 0}
|
m_Offset: {x: 0, y: 0}
|
||||||
- _MainTex:
|
- _MainTex:
|
||||||
m_Texture: {fileID: 2800000, guid: 594180e608ded448d8751c39bca40633, type: 3}
|
m_Texture: {fileID: 2800000, guid: b424ea763d6a34320bae85b1d85ef820, type: 3}
|
||||||
m_Scale: {x: 1, y: 1}
|
m_Scale: {x: 1, y: 1}
|
||||||
m_Offset: {x: 0, y: 0}
|
m_Offset: {x: 0, y: 0}
|
||||||
- _MetallicGlossMap:
|
- _MetallicGlossMap:
|
||||||
|
|||||||
@@ -30,13 +30,15 @@ Material:
|
|||||||
m_Ints: []
|
m_Ints: []
|
||||||
m_Floats:
|
m_Floats:
|
||||||
- _ColorMask: 15
|
- _ColorMask: 15
|
||||||
|
- _MidPoint: 0.5
|
||||||
- _Stencil: 0
|
- _Stencil: 0
|
||||||
- _StencilComp: 8
|
- _StencilComp: 8
|
||||||
- _StencilOp: 0
|
- _StencilOp: 0
|
||||||
- _StencilReadMask: 255
|
- _StencilReadMask: 255
|
||||||
- _StencilWriteMask: 255
|
- _StencilWriteMask: 255
|
||||||
m_Colors:
|
m_Colors:
|
||||||
- _BottomColor: {r: 0.88, g: 0.58, b: 0.08, a: 1}
|
- _BottomColor: {r: 1, g: 0.8272859, b: 0.62578607, a: 1}
|
||||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
- _TopColor: {r: 1, g: 0.96, b: 0.65, a: 1}
|
- _MiddleColor: {r: 1, g: 0.8353073, b: 0.35534585, a: 1}
|
||||||
|
- _TopColor: {r: 1, g: 0.98, b: 0.93, a: 1}
|
||||||
m_BuildTextureStacks: []
|
m_BuildTextureStacks: []
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: XHsWsyKuVn29xwSVE/3Ug9GpdtrPk+ZRNROucmeIFIhu6+A9ilqnymY=
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.0 MiB |
@@ -0,0 +1,177 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: CnxM43+qB3mU/IJVjpBlqtDrEW5/D+SiAMmbk4HP1rVTuGsPSJz7Hnc=
|
||||||
|
TextureImporter:
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 14
|
||||||
|
mipmaps:
|
||||||
|
mipMapMode: 0
|
||||||
|
enableMipMap: 0
|
||||||
|
sRGBTexture: 1
|
||||||
|
linearTexture: 0
|
||||||
|
fadeOut: 0
|
||||||
|
borderMipMap: 0
|
||||||
|
mipMapsPreserveCoverage: 0
|
||||||
|
alphaTestReferenceValue: 0.5
|
||||||
|
mipMapFadeDistanceStart: 1
|
||||||
|
mipMapFadeDistanceEnd: 3
|
||||||
|
bumpmap:
|
||||||
|
convertToNormalMap: 0
|
||||||
|
externalNormalMap: 0
|
||||||
|
heightScale: 0.25
|
||||||
|
normalMapFilter: 0
|
||||||
|
flipGreenChannel: 0
|
||||||
|
isReadable: 0
|
||||||
|
webStreaming: 0
|
||||||
|
priorityLevel: 0
|
||||||
|
uploadedMode: 2
|
||||||
|
streamingMipmaps: 0
|
||||||
|
streamingMipmapsPriority: 0
|
||||||
|
vTOnly: 0
|
||||||
|
ignoreMipmapLimit: 0
|
||||||
|
grayScaleToAlpha: 0
|
||||||
|
generateCubemap: 6
|
||||||
|
cubemapConvolution: 0
|
||||||
|
seamlessCubemap: 0
|
||||||
|
textureFormat: 1
|
||||||
|
maxTextureSize: 2048
|
||||||
|
textureSettings:
|
||||||
|
serializedVersion: 2
|
||||||
|
filterMode: 1
|
||||||
|
aniso: 1
|
||||||
|
mipBias: 0
|
||||||
|
wrapU: 1
|
||||||
|
wrapV: 1
|
||||||
|
wrapW: 0
|
||||||
|
nPOTScale: 0
|
||||||
|
lightmap: 0
|
||||||
|
compressionQuality: 50
|
||||||
|
spriteMode: 1
|
||||||
|
spriteExtrude: 1
|
||||||
|
spriteMeshType: 1
|
||||||
|
alignment: 0
|
||||||
|
spritePivot: {x: 0.5, y: 0.5}
|
||||||
|
spritePixelsToUnits: 100
|
||||||
|
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
spriteGenerateFallbackPhysicsShape: 1
|
||||||
|
alphaUsage: 1
|
||||||
|
alphaIsTransparency: 1
|
||||||
|
spriteTessellationDetail: -1
|
||||||
|
textureType: 8
|
||||||
|
textureShape: 1
|
||||||
|
singleChannelComponent: 0
|
||||||
|
flipbookRows: 1
|
||||||
|
flipbookColumns: 1
|
||||||
|
maxTextureSizeSet: 0
|
||||||
|
compressionQualitySet: 0
|
||||||
|
textureFormatSet: 0
|
||||||
|
ignorePngGamma: 0
|
||||||
|
applyGammaDecoding: 0
|
||||||
|
swizzle: 50462976
|
||||||
|
cookieLightType: 0
|
||||||
|
platformSettings:
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: DefaultTexturePlatform
|
||||||
|
maxTextureSize: 128
|
||||||
|
maxPlaceholderSize: 32
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: Standalone
|
||||||
|
maxTextureSize: 2048
|
||||||
|
maxPlaceholderSize: 32
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: Server
|
||||||
|
maxTextureSize: 2048
|
||||||
|
maxPlaceholderSize: 32
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: WebGL
|
||||||
|
maxTextureSize: 2048
|
||||||
|
maxPlaceholderSize: 32
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: WeixinMiniGame
|
||||||
|
maxTextureSize: 2048
|
||||||
|
maxPlaceholderSize: 32
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: PlayableAds
|
||||||
|
maxTextureSize: 2048
|
||||||
|
maxPlaceholderSize: 32
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
spriteSheet:
|
||||||
|
serializedVersion: 2
|
||||||
|
sprites: []
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
bones: []
|
||||||
|
spriteID: 5e97eb03825dee720800000000000000
|
||||||
|
internalID: 0
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
secondaryTextures: []
|
||||||
|
nameFileIdTable: {}
|
||||||
|
mipmapLimitGroupName:
|
||||||
|
pSDRemoveMatte: 0
|
||||||
|
doOverrideTextureManagerOperations: 0
|
||||||
|
platformOperationGroupSettings:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -313,8 +313,10 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 15c30b8bf55ed47c38c74d59aa9fd021, type: 3}
|
m_Script: {fileID: 11500000, guid: 15c30b8bf55ed47c38c74d59aa9fd021, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
maxHealth: 100
|
maxHealth: 700
|
||||||
currentHealth: 100
|
currentHealth: 700
|
||||||
|
maxShield: 0
|
||||||
|
currentShield: 0
|
||||||
showEnergyBar: 1
|
showEnergyBar: 1
|
||||||
maxEnergy: 100
|
maxEnergy: 100
|
||||||
_currentEnergy: 0
|
_currentEnergy: 0
|
||||||
@@ -329,6 +331,7 @@ MonoBehaviour:
|
|||||||
damageNumberRiseHeight: 1.2
|
damageNumberRiseHeight: 1.2
|
||||||
damageNumberSpawnHeight: 1.5
|
damageNumberSpawnHeight: 1.5
|
||||||
damageNumberSize: 0.09
|
damageNumberSize: 0.09
|
||||||
|
unitLevel: 1
|
||||||
--- !u!114 &832567817104069704
|
--- !u!114 &832567817104069704
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -364,6 +367,11 @@ MonoBehaviour:
|
|||||||
attackRange: 2
|
attackRange: 2
|
||||||
modelFacingOffset: 45
|
modelFacingOffset: 45
|
||||||
attackPower: 10
|
attackPower: 10
|
||||||
|
critRate: 0
|
||||||
|
critMultiplier: 1.5
|
||||||
|
lifestealRate: 0
|
||||||
|
damageReductionRate: 0
|
||||||
|
skillChargeMultiplier: 1
|
||||||
attackDuration: 0
|
attackDuration: 0
|
||||||
attackType: 0
|
attackType: 0
|
||||||
projectilePrefab: {fileID: 0}
|
projectilePrefab: {fileID: 0}
|
||||||
@@ -376,6 +384,8 @@ MonoBehaviour:
|
|||||||
returnToAnchorWhenIdle: 0
|
returnToAnchorWhenIdle: 0
|
||||||
anchorArrivalDistance: 0.35
|
anchorArrivalDistance: 0.35
|
||||||
useAnchorLeash: 0
|
useAnchorLeash: 0
|
||||||
|
useEngagementZLine: 1
|
||||||
|
engagementZThreshold: 10
|
||||||
target: {fileID: 0}
|
target: {fileID: 0}
|
||||||
--- !u!114 &7519013316474627281
|
--- !u!114 &7519013316474627281
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
@@ -389,11 +399,8 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 91c4440b51dd744e9857b9a5b3a0f19b, type: 3}
|
m_Script: {fileID: 11500000, guid: 91c4440b51dd744e9857b9a5b3a0f19b, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
shieldDurability: 220
|
shieldDuration: 5
|
||||||
shieldDuration: 4
|
shieldVfxPrefab: {fileID: 106386, guid: 439cf2d390c444d6b428b530f5b7eec3, type: 3}
|
||||||
damageReduction: 0.35
|
|
||||||
shieldLocalPosition: {x: 0, y: 1, z: 0.7}
|
|
||||||
shieldSize: {x: 1.5, y: 1.8, z: 0.12}
|
|
||||||
--- !u!4 &1906187853415385385 stripped
|
--- !u!4 &1906187853415385385 stripped
|
||||||
Transform:
|
Transform:
|
||||||
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: 17f7a1b7ae92f0948a5bebde8a11fc2b,
|
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: 17f7a1b7ae92f0948a5bebde8a11fc2b,
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -51,7 +51,7 @@ public class GoldUI : MonoBehaviour
|
|||||||
{
|
{
|
||||||
if (goldText != null)
|
if (goldText != null)
|
||||||
{
|
{
|
||||||
goldText.text = $"金币 {newGold}";
|
goldText.text = newGold.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@ public class WorldHealthBar : MonoBehaviour
|
|||||||
[Min(0f)] public float currentHealth = 100f;
|
[Min(0f)] public float currentHealth = 100f;
|
||||||
|
|
||||||
[Header("护盾")]
|
[Header("护盾")]
|
||||||
|
public float maxShield = 0f;
|
||||||
public float currentShield = 0f;
|
public float currentShield = 0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -18,9 +19,32 @@ public class WorldHealthBar : MonoBehaviour
|
|||||||
public void AddShield(float amount)
|
public void AddShield(float amount)
|
||||||
{
|
{
|
||||||
if (amount <= 0f || isDead) return;
|
if (amount <= 0f || isDead) return;
|
||||||
|
if (currentShield <= 0f)
|
||||||
|
{
|
||||||
|
maxShield = amount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
maxShield += amount;
|
||||||
|
}
|
||||||
currentShield += amount;
|
currentShield += amount;
|
||||||
UpdateFill();
|
UpdateFill();
|
||||||
Debug.Log($"{gameObject.name} 获得护盾 +{amount:F1},当前护盾: {currentShield:F1}");
|
UpdateShieldFill();
|
||||||
|
Debug.Log($"{gameObject.name} 获得护盾 +{amount:F1},当前护盾: {currentShield:F1}/{maxShield:F1}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 减少或清空护盾
|
||||||
|
/// </summary>
|
||||||
|
public void RemoveShield(float amount)
|
||||||
|
{
|
||||||
|
if (amount <= 0f || currentShield <= 0f) return;
|
||||||
|
currentShield = Mathf.Max(0f, currentShield - amount);
|
||||||
|
if (currentShield <= 0f)
|
||||||
|
{
|
||||||
|
maxShield = 0f;
|
||||||
|
}
|
||||||
|
UpdateShieldFill();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 技能能量上限,英雄默认使用100点;没有技能的小怪可关闭能量条。
|
// 技能能量上限,英雄默认使用100点;没有技能的小怪可关闭能量条。
|
||||||
@@ -74,7 +98,8 @@ public class WorldHealthBar : MonoBehaviour
|
|||||||
// 描边宽度设为私有常量,所有角色统一使用
|
// 描边宽度设为私有常量,所有角色统一使用
|
||||||
private const float DamageNumberOutlineWidth = 0.025f; // 从 0.015 增加到 0.025,描边更粗
|
private const float DamageNumberOutlineWidth = 0.025f; // 从 0.015 增加到 0.025,描边更粗
|
||||||
|
|
||||||
// 血条 UI 的像素尺寸,实际显示大小由 worldWidth 控制。
|
// 护盾条高 10 像素,置于血条最上方。
|
||||||
|
private const int ShieldPixelHeight = 10;
|
||||||
private const int PixelWidth = 100;
|
private const int PixelWidth = 100;
|
||||||
private const int PixelHeight = 14;
|
private const int PixelHeight = 14;
|
||||||
|
|
||||||
@@ -82,7 +107,7 @@ public class WorldHealthBar : MonoBehaviour
|
|||||||
private const int EnergyPixelWidth = 100; // 改为和血条一样宽
|
private const int EnergyPixelWidth = 100; // 改为和血条一样宽
|
||||||
private const int EnergyPixelHeight = 12; // 从 8 增加到 12,更明显
|
private const int EnergyPixelHeight = 12; // 从 8 增加到 12,更明显
|
||||||
private const int BarGap = 0; // 改为 0,让血条和能量条紧贴在一起
|
private const int BarGap = 0; // 改为 0,让血条和能量条紧贴在一起
|
||||||
private const int TotalPixelHeight = PixelHeight + BarGap + EnergyPixelHeight;
|
private const int TotalPixelHeight = ShieldPixelHeight + BarGap + PixelHeight + BarGap + EnergyPixelHeight;
|
||||||
|
|
||||||
// 世界空间 Canvas,用来承载血条 UI。
|
// 世界空间 Canvas,用来承载血条 UI。
|
||||||
private Canvas canvas;
|
private Canvas canvas;
|
||||||
@@ -90,9 +115,17 @@ public class WorldHealthBar : MonoBehaviour
|
|||||||
// 血条整体的 RectTransform。
|
// 血条整体的 RectTransform。
|
||||||
private RectTransform barRect;
|
private RectTransform barRect;
|
||||||
|
|
||||||
|
// 整体 UI 行节点引用
|
||||||
|
private RectTransform shieldRow;
|
||||||
|
private RectTransform healthRow;
|
||||||
|
private RectTransform energyRow;
|
||||||
|
|
||||||
// 绿色血量填充 Image。
|
// 绿色血量填充 Image。
|
||||||
private Image fillImage;
|
private Image fillImage;
|
||||||
|
|
||||||
|
// 浅蓝色护盾填充 Image。
|
||||||
|
private Image shieldFillImage;
|
||||||
|
|
||||||
// 金色技能能量填充 Image。
|
// 金色技能能量填充 Image。
|
||||||
private Image energyFillImage;
|
private Image energyFillImage;
|
||||||
|
|
||||||
@@ -218,6 +251,7 @@ public class WorldHealthBar : MonoBehaviour
|
|||||||
float absorbed = Mathf.Min(currentShield, amount);
|
float absorbed = Mathf.Min(currentShield, amount);
|
||||||
currentShield -= absorbed;
|
currentShield -= absorbed;
|
||||||
amount -= absorbed;
|
amount -= absorbed;
|
||||||
|
UpdateShieldFill();
|
||||||
Debug.Log($"{gameObject.name} 护盾吸收了 {absorbed:F1} 伤害,剩余护盾: {currentShield:F1}");
|
Debug.Log($"{gameObject.name} 护盾吸收了 {absorbed:F1} 伤害,剩余护盾: {currentShield:F1}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,16 +506,32 @@ public class WorldHealthBar : MonoBehaviour
|
|||||||
canvas.sortingOrder = 100;
|
canvas.sortingOrder = 100;
|
||||||
barObject.GetComponent<CanvasScaler>().dynamicPixelsPerUnit = 10f;
|
barObject.GetComponent<CanvasScaler>().dynamicPixelsPerUnit = 10f;
|
||||||
barRect = barObject.GetComponent<RectTransform>();
|
barRect = barObject.GetComponent<RectTransform>();
|
||||||
barRect.sizeDelta = new Vector2(PixelWidth, showEnergyBar ? TotalPixelHeight : PixelHeight);
|
barRect.sizeDelta = new Vector2(PixelWidth, showEnergyBar ? TotalPixelHeight : (ShieldPixelHeight + PixelHeight));
|
||||||
barRect.localScale = Vector3.one * (worldWidth / PixelWidth);
|
barRect.localScale = Vector3.one * (worldWidth / PixelWidth);
|
||||||
barRect.localPosition = GetBarRootPosition();
|
barRect.localPosition = GetBarRootPosition();
|
||||||
ApplyScaleCompensation();
|
ApplyScaleCompensation();
|
||||||
|
|
||||||
RectTransform healthRow = CreateRow(barObject.transform, "HealthBar", PixelWidth, PixelHeight, 0);
|
// 1. 顶层独立护盾条 (ShieldBar)
|
||||||
|
shieldRow = CreateRow(barObject.transform, "ShieldBar", PixelWidth, ShieldPixelHeight, 0);
|
||||||
|
Image shieldBackground = CreateImage("ShieldBorder", shieldRow, RoundedSprite(), borderColor); // 加回黑框
|
||||||
|
SetFullRect(shieldBackground.rectTransform);
|
||||||
|
|
||||||
|
Image shieldInner = CreateImage("ShieldFill", shieldRow, RoundedSprite(), new Color(0f, 0.88f, 1f, 0.95f)); // 亮天蓝色
|
||||||
|
shieldInner.rectTransform.anchorMin = Vector2.zero;
|
||||||
|
shieldInner.rectTransform.anchorMax = Vector2.one;
|
||||||
|
shieldInner.rectTransform.offsetMin = new Vector2(2f, 1f);
|
||||||
|
shieldInner.rectTransform.offsetMax = new Vector2(-2f, -1f);
|
||||||
|
shieldInner.type = Image.Type.Filled;
|
||||||
|
shieldInner.fillMethod = Image.FillMethod.Horizontal;
|
||||||
|
shieldInner.fillOrigin = 0;
|
||||||
|
shieldFillImage = shieldInner;
|
||||||
|
shieldRow.gameObject.SetActive(false); // 默认没有护盾时整体收起隐藏
|
||||||
|
|
||||||
|
// 2. 中层主血条 (HealthBar)
|
||||||
|
healthRow = CreateRow(barObject.transform, "HealthBar", PixelWidth, PixelHeight, ShieldPixelHeight + BarGap);
|
||||||
Image background = CreateImage("Border", healthRow, RoundedSprite(), borderColor);
|
Image background = CreateImage("Border", healthRow, RoundedSprite(), borderColor);
|
||||||
SetFullRect(background.rectTransform);
|
SetFullRect(background.rectTransform);
|
||||||
|
|
||||||
// 创建填充 Image,颜色暂时使用默认绿色,在 Start() 中根据最终标签设置
|
|
||||||
Image inner = CreateImage("Fill", healthRow, RoundedSprite(), Color.green);
|
Image inner = CreateImage("Fill", healthRow, RoundedSprite(), Color.green);
|
||||||
inner.rectTransform.anchorMin = Vector2.zero;
|
inner.rectTransform.anchorMin = Vector2.zero;
|
||||||
inner.rectTransform.anchorMax = Vector2.one;
|
inner.rectTransform.anchorMax = Vector2.one;
|
||||||
@@ -492,6 +542,7 @@ public class WorldHealthBar : MonoBehaviour
|
|||||||
inner.fillOrigin = 0;
|
inner.fillOrigin = 0;
|
||||||
fillImage = inner;
|
fillImage = inner;
|
||||||
|
|
||||||
|
// 3. 底层技能能量条 (EnergyBar)
|
||||||
if (!showEnergyBar)
|
if (!showEnergyBar)
|
||||||
{
|
{
|
||||||
energyFillImage = null;
|
energyFillImage = null;
|
||||||
@@ -499,12 +550,12 @@ public class WorldHealthBar : MonoBehaviour
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RectTransform energyRow = CreateRow(
|
energyRow = CreateRow(
|
||||||
barObject.transform,
|
barObject.transform,
|
||||||
"EnergyBar",
|
"EnergyBar",
|
||||||
EnergyPixelWidth,
|
EnergyPixelWidth,
|
||||||
EnergyPixelHeight,
|
EnergyPixelHeight,
|
||||||
PixelHeight + BarGap);
|
ShieldPixelHeight + BarGap + PixelHeight + BarGap);
|
||||||
Image energyBackground = CreateImage("EnergyBorder", energyRow, RoundedSprite(), borderColor);
|
Image energyBackground = CreateImage("EnergyBorder", energyRow, RoundedSprite(), borderColor);
|
||||||
SetFullRect(energyBackground.rectTransform);
|
SetFullRect(energyBackground.rectTransform);
|
||||||
|
|
||||||
@@ -619,7 +670,7 @@ public class WorldHealthBar : MonoBehaviour
|
|||||||
// 创建血条左侧的圆圈等级徽章
|
// 创建血条左侧的圆圈等级徽章
|
||||||
private void CreateLevelBadge(Transform parent)
|
private void CreateLevelBadge(Transform parent)
|
||||||
{
|
{
|
||||||
int badgeSize = 26; // 圆圈徽章直径
|
int badgeSize = 39; // 调整为原来的 1.5 倍 (从 26 增大至 39)
|
||||||
GameObject badgeObj = new GameObject("LevelBadge", typeof(RectTransform));
|
GameObject badgeObj = new GameObject("LevelBadge", typeof(RectTransform));
|
||||||
badgeObj.transform.SetParent(parent, false);
|
badgeObj.transform.SetParent(parent, false);
|
||||||
|
|
||||||
@@ -628,7 +679,7 @@ public class WorldHealthBar : MonoBehaviour
|
|||||||
badgeRect.anchorMax = new Vector2(0f, 1f);
|
badgeRect.anchorMax = new Vector2(0f, 1f);
|
||||||
badgeRect.pivot = new Vector2(1f, 0.5f); // 右边缘切齐,紧贴血条左边缘
|
badgeRect.pivot = new Vector2(1f, 0.5f); // 右边缘切齐,紧贴血条左边缘
|
||||||
badgeRect.sizeDelta = new Vector2(badgeSize, badgeSize);
|
badgeRect.sizeDelta = new Vector2(badgeSize, badgeSize);
|
||||||
badgeRect.anchoredPosition = new Vector2(2f, -PixelHeight * 0.5f); // 总是对齐第一行血条中心
|
badgeRect.anchoredPosition = new Vector2(2f, -15f); // 居中对齐主血条中心 (posY = -15f)
|
||||||
|
|
||||||
// 外层黑边圆圈
|
// 外层黑边圆圈
|
||||||
Image outerCircle = CreateImage("OuterCircle", badgeRect, CircleSprite(), new Color(0.05f, 0.05f, 0.05f, 0.95f));
|
Image outerCircle = CreateImage("OuterCircle", badgeRect, CircleSprite(), new Color(0.05f, 0.05f, 0.05f, 0.95f));
|
||||||
@@ -652,7 +703,7 @@ public class WorldHealthBar : MonoBehaviour
|
|||||||
levelText = textObj.GetComponent<Text>();
|
levelText = textObj.GetComponent<Text>();
|
||||||
levelText.text = unitLevel.ToString();
|
levelText.text = unitLevel.ToString();
|
||||||
levelText.font = GetBuiltinFont();
|
levelText.font = GetBuiltinFont();
|
||||||
levelText.fontSize = 18;
|
levelText.fontSize = 26; // 字体同步放大
|
||||||
levelText.fontStyle = FontStyle.Bold;
|
levelText.fontStyle = FontStyle.Bold;
|
||||||
levelText.alignment = TextAnchor.MiddleCenter;
|
levelText.alignment = TextAnchor.MiddleCenter;
|
||||||
levelText.color = new Color(0.95f, 0.98f, 0.95f, 1f);
|
levelText.color = new Color(0.95f, 0.98f, 0.95f, 1f);
|
||||||
@@ -701,6 +752,38 @@ public class WorldHealthBar : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 根据当前护盾值更新天蓝色填充比例与显隐。
|
||||||
|
private void UpdateShieldFill()
|
||||||
|
{
|
||||||
|
if (shieldRow != null && shieldFillImage != null)
|
||||||
|
{
|
||||||
|
if (currentShield > 0f)
|
||||||
|
{
|
||||||
|
shieldRow.gameObject.SetActive(true);
|
||||||
|
|
||||||
|
// 1. 护盾条左对齐:锚点改为左上角
|
||||||
|
shieldRow.anchorMin = new Vector2(0f, 1f);
|
||||||
|
shieldRow.anchorMax = new Vector2(0f, 1f);
|
||||||
|
shieldRow.pivot = new Vector2(0f, 1f);
|
||||||
|
shieldRow.anchoredPosition = new Vector2(0f, 0f);
|
||||||
|
|
||||||
|
// 2. 护盾条的物理宽度按 (maxShield / maxHealth) 比例,代表护盾容量占血条的比例
|
||||||
|
float shieldRatio = maxHealth > 0f ? Mathf.Clamp01(maxShield / maxHealth) : 1.0f;
|
||||||
|
float targetWidth = PixelWidth * Mathf.Max(0.05f, shieldRatio);
|
||||||
|
shieldRow.sizeDelta = new Vector2(targetWidth, ShieldPixelHeight);
|
||||||
|
|
||||||
|
// 3. 天蓝色填充条按 (currentShield / maxShield) 动态扣减
|
||||||
|
float fillRatio = maxShield > 0f ? Mathf.Clamp01(currentShield / maxShield) : 1.0f;
|
||||||
|
shieldFillImage.fillAmount = fillRatio;
|
||||||
|
shieldFillImage.SetVerticesDirty();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shieldRow.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 创建并缓存一个直角矩形白色 Sprite,供边框和填充复用。
|
// 创建并缓存一个直角矩形白色 Sprite,供边框和填充复用。
|
||||||
private static Sprite RoundedSprite()
|
private static Sprite RoundedSprite()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,62 +1,134 @@
|
|||||||
|
using System.Collections;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 盾卫技能:坚固壁垒
|
||||||
|
/// 1级:生成相当于自身 25% 最大生命值的护盾(持续 5 秒),播放 MagicShield 护盾特效
|
||||||
|
/// 3级:护盾值提升至 35% 最大生命值,护盾期间减伤 +15%
|
||||||
|
/// </summary>
|
||||||
public class ShieldGuardSkill : UnitSkill
|
public class ShieldGuardSkill : UnitSkill
|
||||||
{
|
{
|
||||||
[Header("盾牌参数")]
|
[Header("护盾配置")]
|
||||||
[Min(1f)]
|
[Tooltip("护盾持续时间(秒)")]
|
||||||
public float shieldDurability = 220f;
|
public float shieldDuration = 5.0f;
|
||||||
|
|
||||||
[Min(0.1f)]
|
[Tooltip("护盾特效预制体")]
|
||||||
public float shieldDuration = 4f;
|
public GameObject shieldVfxPrefab;
|
||||||
|
|
||||||
[Range(0f, 1f)]
|
private GameObject activeVfxInstance;
|
||||||
public float damageReduction = 0.35f;
|
private Coroutine activeShieldCoroutine;
|
||||||
|
|
||||||
public Vector3 shieldLocalPosition = new Vector3(0f, 1f, 0.7f);
|
private void EnsureUnit()
|
||||||
|
{
|
||||||
public Vector3 shieldSize = new Vector3(1.5f, 1.8f, 0.12f);
|
if (unit == null)
|
||||||
|
{
|
||||||
private ShieldBarrier shield;
|
unit = GetComponent<UnitBase>();
|
||||||
|
}
|
||||||
public ShieldBarrier ActiveShield => shield;
|
}
|
||||||
|
|
||||||
public override void ReleaseSkill()
|
public override void ReleaseSkill()
|
||||||
{
|
{
|
||||||
EnsureShield();
|
EnsureUnit();
|
||||||
shield.Refresh(shieldDurability, shieldDuration, shieldLocalPosition, shieldSize);
|
if (unit == null) return;
|
||||||
|
|
||||||
|
WorldHealthBar healthBar = unit.GetComponent<WorldHealthBar>();
|
||||||
|
if (healthBar == null || healthBar.IsDead) return;
|
||||||
|
|
||||||
|
int level = unit.level; // 从 UnitBase 字段读取 level
|
||||||
|
// 1级:25% maxHealth,3级+:35% maxHealth
|
||||||
|
float ratio = level >= 3 ? 0.35f : 0.25f;
|
||||||
|
float shieldAmount = healthBar.maxHealth * ratio;
|
||||||
|
|
||||||
|
// 1. 添加护盾值
|
||||||
|
healthBar.AddShield(shieldAmount);
|
||||||
|
|
||||||
|
// 2. 播放 MagicShield 护盾特效
|
||||||
|
PlayShieldVfx();
|
||||||
|
|
||||||
|
// 3. 开启超时自动清盾协程
|
||||||
|
if (activeShieldCoroutine != null)
|
||||||
|
{
|
||||||
|
StopCoroutine(activeShieldCoroutine);
|
||||||
|
}
|
||||||
|
activeShieldCoroutine = StartCoroutine(ShieldTimeoutRoutine(shieldDuration, shieldAmount));
|
||||||
|
|
||||||
|
Debug.Log($"<color=cyan>盾卫释放技能【坚固壁垒】</color> 获得 {shieldAmount:F1} 护盾(比例: {ratio * 100}%,等级: {level})");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override float ModifyIncomingDamage(float damage, GameObject attacker)
|
public override float ModifyIncomingDamage(float damage, GameObject attacker)
|
||||||
{
|
{
|
||||||
if (shield == null || !shield.IsActive)
|
EnsureUnit();
|
||||||
|
// 3级解锁:护盾激活期间享受额外 15% 减伤
|
||||||
|
if (unit != null && unit.level >= 3)
|
||||||
{
|
{
|
||||||
return damage;
|
WorldHealthBar healthBar = unit.GetComponent<WorldHealthBar>();
|
||||||
|
if (healthBar != null && healthBar.currentShield > 0f)
|
||||||
|
{
|
||||||
|
return damage * (1f - 0.15f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shield.TryBlock(attacker, damage))
|
|
||||||
{
|
|
||||||
return damage * (1f - damageReduction);
|
|
||||||
}
|
|
||||||
|
|
||||||
return damage;
|
return damage;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureShield()
|
private void PlayShieldVfx()
|
||||||
{
|
{
|
||||||
if (shield != null)
|
if (activeVfxInstance != null)
|
||||||
{
|
{
|
||||||
return;
|
Destroy(activeVfxInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObject shieldObject = new GameObject("ShieldBarrier");
|
GameObject prefab = shieldVfxPrefab;
|
||||||
shieldObject.transform.SetParent(unit.transform, false);
|
if (prefab == null)
|
||||||
|
{
|
||||||
|
prefab = Resources.Load<GameObject>("Prefabs/Combat/Magic/Shield/MagicShieldBlue");
|
||||||
|
}
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (prefab == null)
|
||||||
|
{
|
||||||
|
prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/TJGeneratorLibEffects/Prefabs/Combat/Magic/Shield/MagicShieldBlue.prefab");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
BoxCollider boxCollider = shieldObject.AddComponent<BoxCollider>();
|
if (prefab != null)
|
||||||
boxCollider.isTrigger = true;
|
{
|
||||||
boxCollider.size = shieldSize;
|
activeVfxInstance = Instantiate(prefab, unit.transform.position + Vector3.up * 1.0f, Quaternion.identity);
|
||||||
|
activeVfxInstance.transform.SetParent(unit.transform, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
shield = shieldObject.AddComponent<ShieldBarrier>();
|
private IEnumerator ShieldTimeoutRoutine(float duration, float amount)
|
||||||
shield.Configure(unit, boxCollider);
|
{
|
||||||
shieldObject.SetActive(false);
|
float timer = duration;
|
||||||
|
WorldHealthBar healthBar = unit != null ? unit.GetComponent<WorldHealthBar>() : null;
|
||||||
|
|
||||||
|
while (timer > 0f)
|
||||||
|
{
|
||||||
|
if (unit == null || healthBar == null || healthBar.IsDead || healthBar.currentShield <= 0f)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
timer -= Time.deltaTime;
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 超时或护盾为 0 清理特效与护盾值
|
||||||
|
if (activeVfxInstance != null)
|
||||||
|
{
|
||||||
|
Destroy(activeVfxInstance);
|
||||||
|
activeVfxInstance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (healthBar != null && healthBar.currentShield > 0f && timer <= 0f)
|
||||||
|
{
|
||||||
|
healthBar.RemoveShield(amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
if (activeVfxInstance != null)
|
||||||
|
{
|
||||||
|
Destroy(activeVfxInstance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,9 +45,10 @@ public class BuffSelectionController : MonoBehaviour
|
|||||||
|
|
||||||
public enum BuffQuality
|
public enum BuffQuality
|
||||||
{
|
{
|
||||||
Common, // 初级 (白色 55%)
|
Common, // 初级 (白色 85%)
|
||||||
Rare, // 中级 (紫色 35%)
|
Rare, // 中级 (紫色 10%)
|
||||||
Epic // 高级 (金色 10%)
|
Epic, // 高级 (金色 5%)
|
||||||
|
Legendary // 顶级 (红色/酒红 预留)
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BuffOption
|
public class BuffOption
|
||||||
@@ -68,18 +69,24 @@ public class BuffSelectionController : MonoBehaviour
|
|||||||
[Header("UI 节点引用")]
|
[Header("UI 节点引用")]
|
||||||
public GameObject buffSelectionWindow;
|
public GameObject buffSelectionWindow;
|
||||||
public Transform cardsContainer;
|
public Transform cardsContainer;
|
||||||
|
public Button rollButton; // 刷新按钮
|
||||||
|
public int rollCost = 2; // 每次刷新消耗金币
|
||||||
|
|
||||||
[Header("品质边框 Sprites")]
|
[Header("品质边框 Sprites")]
|
||||||
public Sprite commonBorderSprite; // 铜 (初级)
|
public Sprite commonBorderSprite; // 铜 (初级)
|
||||||
public Sprite rareBorderSprite; // 银 (中级)
|
public Sprite rareBorderSprite; // 银 (中级)
|
||||||
public Sprite epicBorderSprite; // 金 (高级)
|
public Sprite epicBorderSprite; // 金 (高级)
|
||||||
public Sprite legendaryBorderSprite; // 红 (最高级)
|
public Sprite legendaryBorderSprite; // 红 (顶级)
|
||||||
|
|
||||||
[Header("头像 Sprites")]
|
[Header("头像 Sprites")]
|
||||||
public Sprite allIconSprite; // 全体/全局头像 (all.png)
|
public Sprite allIconSprite; // 全体/全局头像 (all.png)
|
||||||
|
|
||||||
private bool isWindowShowing = false;
|
private bool isWindowShowing = false;
|
||||||
|
|
||||||
|
// 3 个卡槽各自独立追踪的品质与递进未升阶计数
|
||||||
|
private BuffQuality[] slotQualities = new BuffQuality[3];
|
||||||
|
private int[] slotNonUpgradeCounts = new int[3];
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
if (_instance == null)
|
if (_instance == null)
|
||||||
@@ -102,15 +109,111 @@ public class BuffSelectionController : MonoBehaviour
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成 3 个随机卡片
|
// 初始弹窗时重置 3 个卡槽的累积计数,并按初始基础概率独立抽品质 (初级 85% / 中级 10% / 高级 5%)
|
||||||
List<BuffOption> options = GenerateThreeOptions();
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
slotNonUpgradeCounts[i] = 0;
|
||||||
|
float roll = Random.value;
|
||||||
|
if (roll < 0.85f)
|
||||||
|
{
|
||||||
|
slotQualities[i] = BuffQuality.Common;
|
||||||
|
}
|
||||||
|
else if (roll < 0.95f)
|
||||||
|
{
|
||||||
|
slotQualities[i] = BuffQuality.Rare;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slotQualities[i] = BuffQuality.Epic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 3 个卡槽的增益选项
|
||||||
|
List<BuffOption> options = GenerateOptionsForSlots();
|
||||||
RenderOptionsUI(options);
|
RenderOptionsUI(options);
|
||||||
|
|
||||||
|
// 绑定刷新按钮事件
|
||||||
|
if (rollButton != null)
|
||||||
|
{
|
||||||
|
rollButton.onClick.RemoveAllListeners();
|
||||||
|
rollButton.onClick.AddListener(OnRollButtonClicked);
|
||||||
|
}
|
||||||
|
|
||||||
buffSelectionWindow.SetActive(true);
|
buffSelectionWindow.SetActive(true);
|
||||||
isWindowShowing = true;
|
isWindowShowing = true;
|
||||||
Time.timeScale = 0f; // 暂停游戏让玩家做选择
|
Time.timeScale = 0f; // 暂停游戏让玩家做选择
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 点击刷新按钮 (耗费 2 金币),3 个卡槽独立计算升阶概率并重新生成选项
|
||||||
|
/// </summary>
|
||||||
|
private void OnRollButtonClicked()
|
||||||
|
{
|
||||||
|
if (GoldManager.Instance != null && !GoldManager.Instance.TrySpendGold(rollCost))
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"金币不足 {rollCost},无法刷新!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3 个卡槽独立判定升级逻辑
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
BuffQuality currentQ = slotQualities[i];
|
||||||
|
bool upgraded = false;
|
||||||
|
BuffQuality targetQ = currentQ;
|
||||||
|
|
||||||
|
if (currentQ == BuffQuality.Common)
|
||||||
|
{
|
||||||
|
// 初级 升 中级 10% 每次 +10% (第2次20%、第3次30%...)
|
||||||
|
float chance = 0.10f + slotNonUpgradeCounts[i] * 0.10f;
|
||||||
|
if (Random.value < chance)
|
||||||
|
{
|
||||||
|
targetQ = BuffQuality.Rare;
|
||||||
|
upgraded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (currentQ == BuffQuality.Rare)
|
||||||
|
{
|
||||||
|
// 中级 升 高级 3% 每次 +5% (第2次8%、第3次13%...)
|
||||||
|
float chance = 0.03f + slotNonUpgradeCounts[i] * 0.05f;
|
||||||
|
if (Random.value < chance)
|
||||||
|
{
|
||||||
|
targetQ = BuffQuality.Epic;
|
||||||
|
upgraded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (currentQ == BuffQuality.Epic)
|
||||||
|
{
|
||||||
|
// 高级 升 顶级 1% (预留) 每次 +2%
|
||||||
|
float chance = 0.01f + slotNonUpgradeCounts[i] * 0.02f;
|
||||||
|
if (Random.value < chance)
|
||||||
|
{
|
||||||
|
targetQ = BuffQuality.Legendary;
|
||||||
|
upgraded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (upgraded)
|
||||||
|
{
|
||||||
|
slotQualities[i] = targetQ;
|
||||||
|
slotNonUpgradeCounts[i] = 0; // 刷出升阶,该槽位的追加概率重置
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (currentQ != BuffQuality.Legendary)
|
||||||
|
{
|
||||||
|
slotNonUpgradeCounts[i]++; // 未升阶,追加概率增加
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log($"<color=yellow>玩家消耗 {rollCost} 金币刷新卡牌!</color> 当前槽位品质: [{slotQualities[0]}], [{slotQualities[1]}], [{slotQualities[2]}]");
|
||||||
|
|
||||||
|
// 重新渲染 3 个卡槽
|
||||||
|
List<BuffOption> newOptions = GenerateOptionsForSlots();
|
||||||
|
RenderOptionsUI(newOptions);
|
||||||
|
}
|
||||||
|
|
||||||
private void RenderOptionsUI(List<BuffOption> options)
|
private void RenderOptionsUI(List<BuffOption> options)
|
||||||
{
|
{
|
||||||
int cardCount = cardsContainer.childCount;
|
int cardCount = cardsContainer.childCount;
|
||||||
@@ -120,7 +223,7 @@ public class BuffSelectionController : MonoBehaviour
|
|||||||
if (i < options.Count)
|
if (i < options.Count)
|
||||||
{
|
{
|
||||||
card.gameObject.SetActive(true);
|
card.gameObject.SetActive(true);
|
||||||
SetupCardUI(card, options[i]);
|
SetupCardUI(card, options[i], i);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -129,10 +232,32 @@ public class BuffSelectionController : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupCardUI(Transform cardTransform, BuffOption option)
|
private float GetNextUpgradeChance(int slotIndex)
|
||||||
|
{
|
||||||
|
if (slotIndex < 0 || slotIndex >= 3) return 0f;
|
||||||
|
BuffQuality currentQ = slotQualities[slotIndex];
|
||||||
|
int count = slotNonUpgradeCounts[slotIndex];
|
||||||
|
|
||||||
|
if (currentQ == BuffQuality.Common)
|
||||||
|
{
|
||||||
|
return 0.10f + count * 0.10f; // 10% + n * 10%
|
||||||
|
}
|
||||||
|
else if (currentQ == BuffQuality.Rare)
|
||||||
|
{
|
||||||
|
return 0.03f + count * 0.05f; // 3% + n * 5%
|
||||||
|
}
|
||||||
|
else if (currentQ == BuffQuality.Epic)
|
||||||
|
{
|
||||||
|
return 0.01f + count * 0.02f; // 1% + n * 2%
|
||||||
|
}
|
||||||
|
return 0f; // 顶级无升级
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupCardUI(Transform cardTransform, BuffOption option, int slotIndex)
|
||||||
{
|
{
|
||||||
Text buffNameText = cardTransform.Find("BuffName")?.GetComponent<Text>();
|
Text buffNameText = cardTransform.Find("BuffName")?.GetComponent<Text>();
|
||||||
Text descText = cardTransform.Find("Description")?.GetComponent<Text>();
|
Text descText = cardTransform.Find("Description")?.GetComponent<Text>();
|
||||||
|
Text upgradeRateText = cardTransform.Find("UpgradeRateText")?.GetComponent<Text>();
|
||||||
|
|
||||||
if (buffNameText != null)
|
if (buffNameText != null)
|
||||||
{
|
{
|
||||||
@@ -145,6 +270,19 @@ public class BuffSelectionController : MonoBehaviour
|
|||||||
descText.text = option.descText;
|
descText.text = option.descText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (upgradeRateText != null)
|
||||||
|
{
|
||||||
|
if (option.quality == BuffQuality.Legendary)
|
||||||
|
{
|
||||||
|
upgradeRateText.text = "已达最高品质";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float chance = GetNextUpgradeChance(slotIndex);
|
||||||
|
upgradeRateText.text = $"升阶概率: {Mathf.Min(100f, chance * 100f):F0}%";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 设置目标英雄 / 全体 Icon 头像
|
// 设置目标英雄 / 全体 Icon 头像
|
||||||
Image iconImage = cardTransform.Find("Icon")?.GetComponent<Image>();
|
Image iconImage = cardTransform.Find("Icon")?.GetComponent<Image>();
|
||||||
if (iconImage != null && option.iconSprite != null)
|
if (iconImage != null && option.iconSprite != null)
|
||||||
@@ -191,6 +329,8 @@ public class BuffSelectionController : MonoBehaviour
|
|||||||
return rareBorderSprite != null ? rareBorderSprite : Resources.Load<Sprite>("Picture/UI/增益边框/银");
|
return rareBorderSprite != null ? rareBorderSprite : Resources.Load<Sprite>("Picture/UI/增益边框/银");
|
||||||
case BuffQuality.Epic:
|
case BuffQuality.Epic:
|
||||||
return epicBorderSprite != null ? epicBorderSprite : Resources.Load<Sprite>("Picture/UI/增益边框/金");
|
return epicBorderSprite != null ? epicBorderSprite : Resources.Load<Sprite>("Picture/UI/增益边框/金");
|
||||||
|
case BuffQuality.Legendary:
|
||||||
|
return legendaryBorderSprite != null ? legendaryBorderSprite : Resources.Load<Sprite>("Picture/UI/增益边框/红");
|
||||||
default:
|
default:
|
||||||
return commonBorderSprite;
|
return commonBorderSprite;
|
||||||
}
|
}
|
||||||
@@ -335,7 +475,7 @@ public class BuffSelectionController : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<BuffOption> GenerateThreeOptions()
|
private List<BuffOption> GenerateOptionsForSlots()
|
||||||
{
|
{
|
||||||
List<BuffOption> list = new List<BuffOption>();
|
List<BuffOption> list = new List<BuffOption>();
|
||||||
HashSet<BuffType> usedTypes = new HashSet<BuffType>();
|
HashSet<BuffType> usedTypes = new HashSet<BuffType>();
|
||||||
@@ -346,7 +486,7 @@ public class BuffSelectionController : MonoBehaviour
|
|||||||
int maxAttempts = 10;
|
int maxAttempts = 10;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
opt = CreateRandomOption(i);
|
opt = CreateOptionForSlot(i, slotQualities[i]);
|
||||||
maxAttempts--;
|
maxAttempts--;
|
||||||
} while (usedTypes.Contains(opt.type) && maxAttempts > 0);
|
} while (usedTypes.Contains(opt.type) && maxAttempts > 0);
|
||||||
|
|
||||||
@@ -370,42 +510,42 @@ public class BuffSelectionController : MonoBehaviour
|
|||||||
BuffType.EmergencyHeal // 14. 紧急救急
|
BuffType.EmergencyHeal // 14. 紧急救急
|
||||||
};
|
};
|
||||||
|
|
||||||
private BuffOption CreateRandomOption(int seedOffset)
|
private BuffOption CreateOptionForSlot(int slotIndex, BuffQuality quality)
|
||||||
{
|
{
|
||||||
BuffOption opt = new BuffOption();
|
BuffOption opt = new BuffOption();
|
||||||
|
|
||||||
// 从当前开放的词条池中随机选择
|
// 从当前开放的词条池中随机选择
|
||||||
opt.type = AvailableBuffTypes[Random.Range(0, AvailableBuffTypes.Length)];
|
opt.type = AvailableBuffTypes[Random.Range(0, AvailableBuffTypes.Length)];
|
||||||
|
opt.quality = quality;
|
||||||
|
|
||||||
// 随机品质 (初级55%, 中级35%, 高级10%)
|
switch (quality)
|
||||||
float rollQuality = Random.value;
|
|
||||||
if (rollQuality < 0.55f)
|
|
||||||
{
|
{
|
||||||
opt.quality = BuffQuality.Common;
|
case BuffQuality.Common:
|
||||||
opt.qualityName = "初级";
|
opt.qualityName = "初级";
|
||||||
opt.qualityColor = new Color(0.85f, 0.85f, 0.85f); // 白色
|
opt.qualityColor = new Color(0.85f, 0.85f, 0.85f); // 白色
|
||||||
}
|
break;
|
||||||
else if (rollQuality < 0.90f)
|
case BuffQuality.Rare:
|
||||||
{
|
opt.qualityName = "中级";
|
||||||
opt.quality = BuffQuality.Rare;
|
opt.qualityColor = new Color(0.7f, 0.35f, 0.95f); // 紫色
|
||||||
opt.qualityName = "中级";
|
break;
|
||||||
opt.qualityColor = new Color(0.7f, 0.35f, 0.95f); // 紫色
|
case BuffQuality.Epic:
|
||||||
}
|
opt.qualityName = "高级";
|
||||||
else
|
opt.qualityColor = new Color(1f, 0.8f, 0.15f); // 金色
|
||||||
{
|
break;
|
||||||
opt.quality = BuffQuality.Epic;
|
case BuffQuality.Legendary:
|
||||||
opt.qualityName = "高级";
|
opt.qualityName = "顶级";
|
||||||
opt.qualityColor = new Color(1f, 0.8f, 0.15f); // 金色
|
opt.qualityColor = new Color(1f, 0.25f, 0.25f); // 红色/酒红
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否为全局属性
|
// 判断是否为全局属性 (20% 全体,80% 指定单体)
|
||||||
bool isGlobalOnly = (opt.type == BuffType.SummonerCD ||
|
bool isGlobalOnly = (opt.type == BuffType.SummonerCD ||
|
||||||
opt.type == BuffType.SummonerPower ||
|
opt.type == BuffType.SummonerPower ||
|
||||||
opt.type == BuffType.KillGold ||
|
opt.type == BuffType.KillGold ||
|
||||||
opt.type == BuffType.GoldBonus);
|
opt.type == BuffType.GoldBonus);
|
||||||
|
|
||||||
List<UnitBase> activeHeroes = GetLocalPlayerHeroes();
|
List<UnitBase> activeHeroes = GetLocalPlayerHeroes();
|
||||||
bool isAll = isGlobalOnly || (Random.value < 0.5f) || (activeHeroes.Count == 0);
|
bool isAll = isGlobalOnly || (Random.value < 0.20f) || (activeHeroes.Count == 0);
|
||||||
|
|
||||||
string heroDisplayName = "";
|
string heroDisplayName = "";
|
||||||
if (isAll)
|
if (isAll)
|
||||||
@@ -530,33 +670,33 @@ public class BuffSelectionController : MonoBehaviour
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case BuffType.AttackPower:
|
case BuffType.AttackPower:
|
||||||
return quality == BuffQuality.Common ? 0.06f : (quality == BuffQuality.Rare ? 0.12f : 0.20f);
|
return quality == BuffQuality.Common ? 0.06f : (quality == BuffQuality.Rare ? 0.12f : (quality == BuffQuality.Epic ? 0.20f : 0.32f));
|
||||||
case BuffType.MaxHealth:
|
case BuffType.MaxHealth:
|
||||||
return quality == BuffQuality.Common ? 0.10f : (quality == BuffQuality.Rare ? 0.18f : 0.30f);
|
return quality == BuffQuality.Common ? 0.10f : (quality == BuffQuality.Rare ? 0.18f : (quality == BuffQuality.Epic ? 0.30f : 0.45f));
|
||||||
case BuffType.AttackSpeed:
|
case BuffType.AttackSpeed:
|
||||||
return quality == BuffQuality.Common ? 0.05f : (quality == BuffQuality.Rare ? 0.10f : 0.16f);
|
return quality == BuffQuality.Common ? 0.05f : (quality == BuffQuality.Rare ? 0.10f : (quality == BuffQuality.Epic ? 0.16f : 0.25f));
|
||||||
case BuffType.CritRate:
|
case BuffType.CritRate:
|
||||||
return quality == BuffQuality.Common ? 0.06f : (quality == BuffQuality.Rare ? 0.12f : 0.20f);
|
return quality == BuffQuality.Common ? 0.06f : (quality == BuffQuality.Rare ? 0.12f : (quality == BuffQuality.Epic ? 0.20f : 0.30f));
|
||||||
case BuffType.Lifesteal:
|
case BuffType.Lifesteal:
|
||||||
return quality == BuffQuality.Common ? 0.04f : (quality == BuffQuality.Rare ? 0.08f : 0.14f);
|
return quality == BuffQuality.Common ? 0.04f : (quality == BuffQuality.Rare ? 0.08f : (quality == BuffQuality.Epic ? 0.14f : 0.20f));
|
||||||
case BuffType.SkillCharge:
|
case BuffType.SkillCharge:
|
||||||
return quality == BuffQuality.Common ? 0.08f : (quality == BuffQuality.Rare ? 0.15f : 0.25f);
|
return quality == BuffQuality.Common ? 0.08f : (quality == BuffQuality.Rare ? 0.15f : (quality == BuffQuality.Epic ? 0.25f : 0.40f));
|
||||||
case BuffType.SummonerCD:
|
case BuffType.SummonerCD:
|
||||||
return quality == BuffQuality.Common ? 0.05f : (quality == BuffQuality.Rare ? 0.10f : 0.18f);
|
return quality == BuffQuality.Common ? 0.05f : (quality == BuffQuality.Rare ? 0.10f : (quality == BuffQuality.Epic ? 0.18f : 0.28f));
|
||||||
case BuffType.SummonerPower:
|
case BuffType.SummonerPower:
|
||||||
return quality == BuffQuality.Common ? 0.08f : (quality == BuffQuality.Rare ? 0.15f : 0.25f);
|
return quality == BuffQuality.Common ? 0.08f : (quality == BuffQuality.Rare ? 0.15f : (quality == BuffQuality.Epic ? 0.25f : 0.40f));
|
||||||
case BuffType.AttackRange:
|
case BuffType.AttackRange:
|
||||||
return quality == BuffQuality.Common ? 0.5f : (quality == BuffQuality.Rare ? 1.0f : 1.8f);
|
return quality == BuffQuality.Common ? 0.5f : (quality == BuffQuality.Rare ? 1.0f : (quality == BuffQuality.Epic ? 1.8f : 2.5f));
|
||||||
case BuffType.DamageReduction:
|
case BuffType.DamageReduction:
|
||||||
return quality == BuffQuality.Common ? 0.05f : (quality == BuffQuality.Rare ? 0.10f : 0.16f);
|
return quality == BuffQuality.Common ? 0.05f : (quality == BuffQuality.Rare ? 0.10f : (quality == BuffQuality.Epic ? 0.16f : 0.25f));
|
||||||
case BuffType.Shield:
|
case BuffType.Shield:
|
||||||
return quality == BuffQuality.Common ? 0.15f : (quality == BuffQuality.Rare ? 0.25f : 0.40f);
|
return quality == BuffQuality.Common ? 0.15f : (quality == BuffQuality.Rare ? 0.25f : (quality == BuffQuality.Epic ? 0.40f : 0.60f));
|
||||||
case BuffType.KillGold:
|
case BuffType.KillGold:
|
||||||
return quality == BuffQuality.Common ? 0.15f : (quality == BuffQuality.Rare ? 0.30f : 0.50f);
|
return quality == BuffQuality.Common ? 0.15f : (quality == BuffQuality.Rare ? 0.30f : (quality == BuffQuality.Epic ? 0.50f : 0.80f));
|
||||||
case BuffType.GoldBonus:
|
case BuffType.GoldBonus:
|
||||||
return quality == BuffQuality.Common ? 30f : (quality == BuffQuality.Rare ? 60f : 100f);
|
return quality == BuffQuality.Common ? 30f : (quality == BuffQuality.Rare ? 60f : (quality == BuffQuality.Epic ? 100f : 160f));
|
||||||
case BuffType.EmergencyHeal:
|
case BuffType.EmergencyHeal:
|
||||||
return quality == BuffQuality.Common ? 0.25f : (quality == BuffQuality.Rare ? 0.40f : 0.60f);
|
return quality == BuffQuality.Common ? 0.25f : (quality == BuffQuality.Rare ? 0.40f : (quality == BuffQuality.Epic ? 0.60f : 0.80f));
|
||||||
default:
|
default:
|
||||||
return 0.10f;
|
return 0.10f;
|
||||||
}
|
}
|
||||||
@@ -595,10 +735,19 @@ public class BuffSelectionController : MonoBehaviour
|
|||||||
if (winTrans != null) buffSelectionWindow = winTrans.gameObject;
|
if (winTrans != null) buffSelectionWindow = winTrans.gameObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffSelectionWindow != null && cardsContainer == null)
|
if (buffSelectionWindow != null)
|
||||||
{
|
{
|
||||||
var containerTrans = buffSelectionWindow.transform.Find("BuffPanel/BuffCardsContainer");
|
if (cardsContainer == null)
|
||||||
if (containerTrans != null) cardsContainer = containerTrans;
|
{
|
||||||
|
var containerTrans = buffSelectionWindow.transform.Find("BuffPanel/BuffCardsContainer");
|
||||||
|
if (containerTrans != null) cardsContainer = containerTrans;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rollButton == null)
|
||||||
|
{
|
||||||
|
var rollTrans = buffSelectionWindow.transform.Find("BuffPanel/RollButton");
|
||||||
|
if (rollTrans != null) rollButton = rollTrans.GetComponent<Button>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,8 +5,10 @@ Shader "UI/GoldTextGradient"
|
|||||||
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
|
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
|
||||||
_Color ("Tint", Color) = (1,1,1,1)
|
_Color ("Tint", Color) = (1,1,1,1)
|
||||||
|
|
||||||
_TopColor ("Top Gold Color", Color) = (1, 0.95, 0.6, 1)
|
_TopColor ("Top Color (White)", Color) = (1.0, 0.98, 0.95, 1.0)
|
||||||
_BottomColor ("Bottom Gold Color", Color) = (0.9, 0.65, 0.1, 1)
|
_MiddleColor ("Middle Color (Light Gold)", Color) = (1.0, 0.82, 0.4, 1.0)
|
||||||
|
_BottomColor ("Bottom Color (Amber Gold)", Color) = (0.82, 0.5, 0.1, 1.0)
|
||||||
|
_MidPoint ("Gradient Mid Point", Range(0.1, 0.9)) = 0.35
|
||||||
|
|
||||||
_StencilComp ("Stencil Comparison", Float) = 8
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
_Stencil ("Stencil ID", Float) = 0
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
@@ -68,9 +70,12 @@ Shader "UI/GoldTextGradient"
|
|||||||
|
|
||||||
fixed4 _Color;
|
fixed4 _Color;
|
||||||
fixed4 _TopColor;
|
fixed4 _TopColor;
|
||||||
|
fixed4 _MiddleColor;
|
||||||
fixed4 _BottomColor;
|
fixed4 _BottomColor;
|
||||||
|
float _MidPoint;
|
||||||
sampler2D _MainTex;
|
sampler2D _MainTex;
|
||||||
float4 _MainTex_ST;
|
float4 _MainTex_ST;
|
||||||
|
fixed4 _TextureSampleAdd;
|
||||||
|
|
||||||
v2f vert(appdata_t IN)
|
v2f vert(appdata_t IN)
|
||||||
{
|
{
|
||||||
@@ -79,7 +84,19 @@ Shader "UI/GoldTextGradient"
|
|||||||
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
|
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
|
||||||
OUT.texcoord = TRANSFORM_TEX(IN.texcoord, _MainTex);
|
OUT.texcoord = TRANSFORM_TEX(IN.texcoord, _MainTex);
|
||||||
|
|
||||||
fixed4 gradColor = lerp(_BottomColor, _TopColor, saturate(IN.texcoord.y));
|
float y = saturate(IN.texcoord.y);
|
||||||
|
fixed4 gradColor;
|
||||||
|
if (y > _MidPoint)
|
||||||
|
{
|
||||||
|
float t = (y - _MidPoint) / (1.0 - _MidPoint);
|
||||||
|
gradColor = lerp(_MiddleColor, _TopColor, t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float t = y / _MidPoint;
|
||||||
|
gradColor = lerp(_BottomColor, _MiddleColor, t);
|
||||||
|
}
|
||||||
|
|
||||||
OUT.color = IN.color * _Color * gradColor;
|
OUT.color = IN.color * _Color * gradColor;
|
||||||
return OUT;
|
return OUT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:yousandi.cn,2023:
|
||||||
|
--- !u!21 &2100000
|
||||||
|
Material:
|
||||||
|
serializedVersion: 8
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: gradient_circle_ADD
|
||||||
|
m_Shader: {fileID: 211, guid: 0000000000000000f000000000000000, type: 0}
|
||||||
|
m_Parent: {fileID: 0}
|
||||||
|
m_ModifiedSerializedProperties: 0
|
||||||
|
m_ValidKeywords:
|
||||||
|
- _ALPHABLEND_ON
|
||||||
|
- _FADING_ON
|
||||||
|
m_InvalidKeywords: []
|
||||||
|
m_LightmapFlags: 0
|
||||||
|
m_EnableInstancingVariants: 0
|
||||||
|
m_DoubleSidedGI: 0
|
||||||
|
m_CustomRenderQueue: 3000
|
||||||
|
stringTagMap:
|
||||||
|
RenderType: Transparent
|
||||||
|
disabledShaderPasses:
|
||||||
|
- GRABPASS
|
||||||
|
m_LockedProperties:
|
||||||
|
m_SavedProperties:
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TexEnvs:
|
||||||
|
- _BumpMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _EmissionMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _MainTex:
|
||||||
|
m_Texture: {fileID: 2800000, guid: 0eeec03d219046ecb9cc4d051bdb0ccd, type: 3}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
m_Ints: []
|
||||||
|
m_Floats:
|
||||||
|
- _BlendOp: 0
|
||||||
|
- _BumpScale: 1
|
||||||
|
- _CameraFadingEnabled: 0
|
||||||
|
- _CameraFarFadeDistance: 2
|
||||||
|
- _CameraNearFadeDistance: 1
|
||||||
|
- _ColorMode: 0
|
||||||
|
- _Cull: 0
|
||||||
|
- _Cutoff: 0.5
|
||||||
|
- _DistortionBlend: 0.5
|
||||||
|
- _DistortionEnabled: 0
|
||||||
|
- _DistortionStrength: 1
|
||||||
|
- _DistortionStrengthScaled: 0
|
||||||
|
- _DstBlend: 1
|
||||||
|
- _EmissionEnabled: 0
|
||||||
|
- _FlipbookMode: 0
|
||||||
|
- _InvFade: 1
|
||||||
|
- _LightingEnabled: 0
|
||||||
|
- _Mode: 4
|
||||||
|
- _SoftParticlesEnabled: 1
|
||||||
|
- _SoftParticlesFarFadeDistance: 0.5
|
||||||
|
- _SoftParticlesNearFadeDistance: 0
|
||||||
|
- _SrcBlend: 5
|
||||||
|
- _ZWrite: 0
|
||||||
|
m_Colors:
|
||||||
|
- _CameraFadeParams: {r: 0, g: Infinity, b: 0, a: 0}
|
||||||
|
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _ColorAddSubDiff: {r: 0, g: 0, b: 0, a: 0}
|
||||||
|
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _SoftParticleFadeParams: {r: 0, g: 2, b: 0, a: 0}
|
||||||
|
- _TintColor: {r: 0.5, g: 0.5, b: 0.5, a: 0.5}
|
||||||
|
m_BuildTextureStacks: []
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2577b005a1f54cfda2f4aaae33e08294
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 2100000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: WX8XvC6rAHLu3SZwZD3d+Mv1uUS/aGddQKv2a1vQ+yvZsGTXkjTt8wo=
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: D3xM4HypB37iBlvRcAiTrbYIo8cOlqEfaN+IXJKRIE5GVUxFmK6+zeI=
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 439cf2d390c444d6b428b530f5b7eec3
|
||||||
|
timeCreated: 1448725631
|
||||||
|
licenseType: Store
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -1,21 +1,22 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 8787ae9d4a3a4e92a6799c3aa0c13ac4
|
guid: B30Xsnv4Wi+OvweaNazT4i1PhBCwB95YnJ/aipg2YVrG1qqIvS6dAvA=
|
||||||
timeCreated: 1520362796
|
|
||||||
licenseType: Store
|
|
||||||
AudioImporter:
|
AudioImporter:
|
||||||
serializedVersion: 6
|
externalObjects: {}
|
||||||
|
serializedVersion: 7
|
||||||
defaultSettings:
|
defaultSettings:
|
||||||
|
serializedVersion: 2
|
||||||
loadType: 0
|
loadType: 0
|
||||||
sampleRateSetting: 0
|
sampleRateSetting: 0
|
||||||
sampleRateOverride: 44100
|
sampleRateOverride: 44100
|
||||||
compressionFormat: 1
|
compressionFormat: 1
|
||||||
quality: 1
|
quality: 0.29999998
|
||||||
conversionMode: 0
|
conversionMode: 0
|
||||||
|
preloadAudioData: 1
|
||||||
platformSettingOverrides: {}
|
platformSettingOverrides: {}
|
||||||
forceToMono: 0
|
forceToMono: 0
|
||||||
normalize: 1
|
normalize: 1
|
||||||
preloadAudioData: 1
|
|
||||||
loadInBackground: 0
|
loadInBackground: 0
|
||||||
|
ambisonic: 0
|
||||||
3D: 1
|
3D: 1
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 15520b8ee45e4432a669f6f5eaf0fdf4
|
guid: Dn8atyr/Wy4CCl4fJhLc+nF733+HdmXoF2bHSYlIJfHwUJRMVtYBuLg=
|
||||||
AudioImporter:
|
AudioImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 6
|
serializedVersion: 7
|
||||||
defaultSettings:
|
defaultSettings:
|
||||||
|
serializedVersion: 2
|
||||||
loadType: 0
|
loadType: 0
|
||||||
sampleRateSetting: 0
|
sampleRateSetting: 0
|
||||||
sampleRateOverride: 44100
|
sampleRateOverride: 44100
|
||||||
compressionFormat: 1
|
compressionFormat: 1
|
||||||
quality: 1
|
quality: 0.29999998
|
||||||
conversionMode: 0
|
conversionMode: 0
|
||||||
|
preloadAudioData: 1
|
||||||
platformSettingOverrides: {}
|
platformSettingOverrides: {}
|
||||||
forceToMono: 0
|
forceToMono: 0
|
||||||
normalize: 1
|
normalize: 1
|
||||||
preloadAudioData: 1
|
|
||||||
loadInBackground: 0
|
loadInBackground: 0
|
||||||
ambisonic: 0
|
ambisonic: 0
|
||||||
3D: 1
|
3D: 1
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 59c606addec946ddb80cf1bd77227243
|
guid: CnNMsyqrAi9gaVSzBHa42o9BpEk6k2mrIzB/sTeCaLsSu9mQgxY+Ga0=
|
||||||
AudioImporter:
|
AudioImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 6
|
serializedVersion: 7
|
||||||
defaultSettings:
|
defaultSettings:
|
||||||
|
serializedVersion: 2
|
||||||
loadType: 0
|
loadType: 0
|
||||||
sampleRateSetting: 0
|
sampleRateSetting: 0
|
||||||
sampleRateOverride: 44100
|
sampleRateOverride: 44100
|
||||||
compressionFormat: 1
|
compressionFormat: 1
|
||||||
quality: 1
|
quality: 0.29999998
|
||||||
conversionMode: 0
|
conversionMode: 0
|
||||||
|
preloadAudioData: 1
|
||||||
platformSettingOverrides: {}
|
platformSettingOverrides: {}
|
||||||
forceToMono: 0
|
forceToMono: 0
|
||||||
normalize: 1
|
normalize: 1
|
||||||
preloadAudioData: 1
|
|
||||||
loadInBackground: 0
|
loadInBackground: 0
|
||||||
ambisonic: 0
|
ambisonic: 0
|
||||||
3D: 1
|
3D: 1
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 3443e358a73b4a6dbb62ad72164ec2b2
|
guid: DH4btn+uVnMofEIfWxGRXp7edhpNoYv5iBLLQrnKn1hXUCnEv5klu1c=
|
||||||
timeCreated: 1520362796
|
|
||||||
licenseType: Store
|
|
||||||
AudioImporter:
|
AudioImporter:
|
||||||
serializedVersion: 6
|
externalObjects: {}
|
||||||
|
serializedVersion: 7
|
||||||
defaultSettings:
|
defaultSettings:
|
||||||
|
serializedVersion: 2
|
||||||
loadType: 0
|
loadType: 0
|
||||||
sampleRateSetting: 0
|
sampleRateSetting: 0
|
||||||
sampleRateOverride: 44100
|
sampleRateOverride: 44100
|
||||||
compressionFormat: 1
|
compressionFormat: 1
|
||||||
quality: 1
|
quality: 0.29999998
|
||||||
conversionMode: 0
|
conversionMode: 0
|
||||||
|
preloadAudioData: 1
|
||||||
platformSettingOverrides: {}
|
platformSettingOverrides: {}
|
||||||
forceToMono: 0
|
forceToMono: 0
|
||||||
normalize: 1
|
normalize: 1
|
||||||
preloadAudioData: 1
|
|
||||||
loadInBackground: 0
|
loadInBackground: 0
|
||||||
|
ambisonic: 0
|
||||||
3D: 1
|
3D: 1
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
@@ -0,0 +1,116 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0eeec03d219046ecb9cc4d051bdb0ccd
|
||||||
|
TextureImporter:
|
||||||
|
fileIDToRecycleName: {}
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 4
|
||||||
|
mipmaps:
|
||||||
|
mipMapMode: 0
|
||||||
|
enableMipMap: 1
|
||||||
|
sRGBTexture: 1
|
||||||
|
linearTexture: 0
|
||||||
|
fadeOut: 0
|
||||||
|
borderMipMap: 0
|
||||||
|
mipMapsPreserveCoverage: 0
|
||||||
|
alphaTestReferenceValue: 0.5
|
||||||
|
mipMapFadeDistanceStart: 1
|
||||||
|
mipMapFadeDistanceEnd: 3
|
||||||
|
bumpmap:
|
||||||
|
convertToNormalMap: 0
|
||||||
|
externalNormalMap: 0
|
||||||
|
heightScale: 0.25
|
||||||
|
normalMapFilter: 0
|
||||||
|
isReadable: 0
|
||||||
|
grayScaleToAlpha: 0
|
||||||
|
generateCubemap: 6
|
||||||
|
cubemapConvolution: 0
|
||||||
|
seamlessCubemap: 0
|
||||||
|
textureFormat: 1
|
||||||
|
maxTextureSize: 2048
|
||||||
|
textureSettings:
|
||||||
|
serializedVersion: 2
|
||||||
|
filterMode: -1
|
||||||
|
aniso: -1
|
||||||
|
mipBias: -1
|
||||||
|
wrapU: -1
|
||||||
|
wrapV: -1
|
||||||
|
wrapW: -1
|
||||||
|
nPOTScale: 1
|
||||||
|
lightmap: 0
|
||||||
|
compressionQuality: 50
|
||||||
|
spriteMode: 0
|
||||||
|
spriteExtrude: 1
|
||||||
|
spriteMeshType: 1
|
||||||
|
alignment: 0
|
||||||
|
spritePivot: {x: 0.5, y: 0.5}
|
||||||
|
spritePixelsToUnits: 100
|
||||||
|
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
spriteGenerateFallbackPhysicsShape: 1
|
||||||
|
alphaUsage: 1
|
||||||
|
alphaIsTransparency: 1
|
||||||
|
spriteTessellationDetail: -1
|
||||||
|
textureType: 0
|
||||||
|
textureShape: 1
|
||||||
|
maxTextureSizeSet: 0
|
||||||
|
compressionQualitySet: 0
|
||||||
|
textureFormatSet: 0
|
||||||
|
platformSettings:
|
||||||
|
- buildTarget: DefaultTexturePlatform
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
- buildTarget: Standalone
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
- buildTarget: Android
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
- buildTarget: Windows Store Apps
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
- buildTarget: WebGL
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
spriteSheet:
|
||||||
|
serializedVersion: 2
|
||||||
|
sprites: []
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
spritePackingTag:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -146,6 +146,8 @@
|
|||||||
- [2026-10-08 00:04:53] 天雷狂轰技能实现:点击释放时在全屏中心激发 NovaLightningBlue 蓝闪电光环,同时按 80ms 节奏交错向全场敌方单位头顶劈下 LightningExplosionBlue 落雷(无敌人时在阵地随机轰炸 6 道),造成最终结算伤害并弹出漂字。具体路径与配置已同步写入项目。
|
- [2026-10-08 00:04:53] 天雷狂轰技能实现:点击释放时在全屏中心激发 NovaLightningBlue 蓝闪电光环,同时按 80ms 节奏交错向全场敌方单位头顶劈下 LightningExplosionBlue 落雷(无敌人时在阵地随机轰炸 6 道),造成最终结算伤害并弹出漂字。具体路径与配置已同步写入项目。
|
||||||
- [2026-10-08 16:33:27] 2026-10-08 敌方单位不共享 3 选 1 战斗增益卡,增益卡为玩家专属 Build 系统;关卡难度通过敌方英雄等级、星级和数量显式决定,不进行隐式数据调整。
|
- [2026-10-08 16:33:27] 2026-10-08 敌方单位不共享 3 选 1 战斗增益卡,增益卡为玩家专属 Build 系统;关卡难度通过敌方英雄等级、星级和数量显式决定,不进行隐式数据调整。
|
||||||
- [2026-10-08 16:33:41] 2026-10-08 塔防版等级与成长规则:不设立账号/玩家等级,所有成长挂载在卡牌自身的卡牌等级(1~10级),消耗金币与卡牌碎片升级;在 1/3/6/10 级大节点解锁/强化技能机制。
|
- [2026-10-08 16:33:41] 2026-10-08 塔防版等级与成长规则:不设立账号/玩家等级,所有成长挂载在卡牌自身的卡牌等级(1~10级),消耗金币与卡牌碎片升级;在 1/3/6/10 级大节点解锁/强化技能机制。
|
||||||
|
- [2026-10-09 11:31:55] 2026-10-09 3 选 1 增益 D-Card 规则:刷新消耗固定 2 金币,3 个卡槽独立计算递进升阶概率(初升中 10%+10%/次,中升高 3%+5%/次,高升顶 1%+2%/次),刷出升阶重置该槽位追加概率;选卡后重置全槽位。UI 金色文本统一使用三阶渐变 Shader UI/GoldTextGradient 与暗色 Outline。
|
||||||
|
- [2026-10-09 16:22:12] 2026-10-09 护盾 UI 规则:独立顶层护盾条 (ShieldBar),护盾槽物理宽度按 maxShield/maxHealth 占血条比例显示并保留黑边框,受击时按 currentShield/maxShield 在黑框内向左平滑缩减。盾卫技能默认使用内置粒子特效 MagicShieldBlue.prefab。
|
||||||
|
|
||||||
### Reference
|
### Reference
|
||||||
- [2026-09-09 12:23:17] 飞行物脚本 Projectile.cs 负责锁敌追踪、碰撞检测和伤害结算。箭矢预制体 ArrowProjectile_White.prefab 已配置 Projectile 组件和 CapsuleCollider(Is Trigger)。远程单位需在攻击动画松弦帧添加 OnAttackEffect Event,并在 UnitBase 中设置 attackType=RangedProjectile、projectilePrefab、projectileSpawnPoint。
|
- [2026-09-09 12:23:17] 飞行物脚本 Projectile.cs 负责锁敌追踪、碰撞检测和伤害结算。箭矢预制体 ArrowProjectile_White.prefab 已配置 Projectile 组件和 CapsuleCollider(Is Trigger)。远程单位需在攻击动画松弦帧添加 OnAttackEffect Event,并在 UnitBase 中设置 attackType=RangedProjectile、projectilePrefab、projectileSpawnPoint。
|
||||||
Reference in new issue
Block a user