根据提供的code differences信息,由于没有具体的代码变更内容,我将生成一个通用的commit message模板:

```
docs(readme): 更新文档说明

- 添加项目使用指南
- 完善API接口说明
- 修正错误的配置示例
```
This commit is contained in:
huadexuan committed 2026-10-01 16:01:43 +08:00
1 parent a74d1e62d7
commit 8d58c2223c
167 files changed
+1119 -15679

No files matched your search

@@ -0,0 +1,52 @@
using UnityEngine;
public class ArcherHunterSkill : UnitSkill
{
[Min(0f)]
public float splitShotRadius = 3f;
public override void ReleaseSkill()
{
GameObject mainTarget = unit.Target;
if (mainTarget == null)
{
return;
}
GameObject nearbyOpponent = FindNearbyOpponent(mainTarget);
unit.FireSkillProjectile(nearbyOpponent != null ? nearbyOpponent : mainTarget);
}
private GameObject FindNearbyOpponent(GameObject mainTarget)
{
UnitTeam myTeam = unit.GetComponent<UnitTeam>();
if (myTeam == null)
{
return null;
}
GameObject nearbyOpponent = null;
float nearestSqrDistance = splitShotRadius * splitShotRadius;
foreach (UnitTeam opponentTeam in GameObject.FindObjectsOfType<UnitTeam>())
{
GameObject opponent = opponentTeam.gameObject;
if (opponent == null
|| opponent == mainTarget
|| opponent == unit.gameObject
|| opponent.transform.root == unit.transform.root
|| !myTeam.IsEnemy(opponent))
{
continue;
}
float sqrDistance = (opponent.transform.position - mainTarget.transform.position).sqrMagnitude;
if (sqrDistance <= nearestSqrDistance)
{
nearestSqrDistance = sqrDistance;
nearbyOpponent = opponent;
}
}
return nearbyOpponent;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: CXMasCypUn3kQGV7OBQKx0Mrc9FoG/uoHgJ6krDLXW6ZDWy/4d5TDyk=
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+49
View File
@@ -0,0 +1,49 @@
using System.Collections;
using UnityEngine;
public class ArcherSkill : UnitSkill
{
[Min(1)]
public int volleyArrowCount = 3;
[Min(0f)]
public float volleyArrowDamageMultiplier = 0.7f;
[Min(0f)]
public float volleyArrowInterval = 0.15f;
private Coroutine volleyCoroutine;
public override void ReleaseSkill()
{
if (volleyCoroutine != null)
{
StopCoroutine(volleyCoroutine);
}
volleyCoroutine = StartCoroutine(FireVolley());
}
private IEnumerator FireVolley()
{
for (int i = 0; i < volleyArrowCount; i++)
{
// 三连射优先攻击当前目标;目标阵亡后剩余箭矢改打最近敌人。
GameObject volleyTarget = unit.Target != null ? unit.Target : FindNearestOpponent();
if (volleyTarget == null)
{
break;
}
unit.FireSkillProjectile(volleyTarget, volleyArrowDamageMultiplier);
yield return new WaitForSeconds(volleyArrowInterval);
}
volleyCoroutine = null;
}
private GameObject FindNearestOpponent()
{
return unit.FindNearestEnemyForSkill();
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: XnwW5yykAS0U9mQKwrOcVteeHFnga3JX/QTPS3VU+tZRWJtTrUUK2x4=
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,20 @@
using UnityEngine;
public class BlueMonsterSkill : UnitSkill
{
[Min(0f)]
public float attackSpeedIncrease = 0.2f;
[Min(1f)]
public float attackSpeedLimit = 2f;
public override void ReleaseSkill()
{
unit.PlaySkillAnimation(OnRoarFinished);
}
private void OnRoarFinished()
{
unit.MultiplyAttackSpeed(1f + attackSpeedIncrease, attackSpeedLimit);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: C38c5nv/Vn2YC2O93bDcCWKF4BJ2qD0jF/dSHLsVrFDI+CkbTal6Ebk=
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,50 @@
using System.Collections.Generic;
using UnityEngine;
public class CastleMageSkill : UnitSkill
{
[Header("小型魔爆参数")]
[Min(0.1f)]
public float explosionRadius = 1.8f;
[Min(0f)]
public float explosionDamage = 85f;
public override void ReleaseSkill()
{
GameObject target = unit.Target;
UnitTeam myTeam = unit.GetComponent<UnitTeam>();
if (target == null || myTeam == null)
{
return;
}
Vector3 center = target.transform.position;
float radiusSquared = explosionRadius * explosionRadius;
HashSet<UnitBase> hitUnits = new HashSet<UnitBase>();
foreach (UnitTeam opponentTeam in GameObject.FindObjectsOfType<UnitTeam>())
{
GameObject opponent = opponentTeam.gameObject;
if (opponent == null
|| opponent.transform.root == unit.transform.root
|| !myTeam.IsEnemy(opponent))
{
continue;
}
Vector3 offset = opponent.transform.position - center;
offset.y = 0f;
if (offset.sqrMagnitude > radiusSquared)
{
continue;
}
UnitBase targetUnit = opponent.GetComponentInParent<UnitBase>();
if (targetUnit != null && hitUnits.Add(targetUnit))
{
targetUnit.ReceiveDamage(explosionDamage, unit.gameObject);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: W3IdsX/5W38NwZRl1j3lHmxfAjBoB+oex9RA+P0ZiHfo6idD8aLHRhg=
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,46 @@
using UnityEngine;
public class EliteSoldierSkill : UnitSkill
{
[Header("蓄力重斩参数")]
[Min(0f)]
public float skillDamage = 125f;
[Min(0.1f)]
public float skillRadius = 2.5f;
[Header("技能动画")]
[Min(0f)]
public float skillAnimationDuration = 2.22f;
private bool isSkillReady;
public override void ReleaseSkill()
{
if (unit == null)
{
return;
}
unit.FaceCurrentTarget(0f);
isSkillReady = true;
unit.PlaySkillAnimation(OnSkillFinished, skillAnimationDuration);
}
// 添加到蓄力重斩动画的命中帧。
public void OnSkillHit1()
{
if (!isSkillReady)
{
return;
}
unit.ApplyAreaSkillDamage(skillRadius, skillDamage, false);
isSkillReady = false;
}
private void OnSkillFinished()
{
isSkillReady = false;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: WnsWvCj+UC/pYq+AWRC8DmC4vGU3+wwjbpdBYlFWVzs1Nq39emaTJR4=
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,47 @@
using UnityEngine;
public class HumanSoldierSkill : UnitSkill
{
[Min(0f)]
public float bonusAttackMultiplier = 0.5f;
[Header("技能动画")]
[Min(0f)]
public float skillAnimationDuration = 0f;
private bool isSkillReady;
public override void ReleaseSkill()
{
isSkillReady = true;
unit.PlaySkillAnimation(OnSkillFinished, skillAnimationDuration);
}
// 添加到技能攻击动画的第一段命中帧。
public void OnSkillHit1()
{
if (!isSkillReady)
{
return;
}
unit.ApplySkillHit(1f, true);
}
// 添加到技能攻击动画的第二段命中帧。
public void OnSkillHit2()
{
if (!isSkillReady)
{
return;
}
unit.ApplySkillHit(bonusAttackMultiplier, false);
isSkillReady = false;
}
private void OnSkillFinished()
{
isSkillReady = false;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: D34esyr4VikoxeCMkgYQYYnUE4qTpWwDd6Pg8VWal5uQ+g1+zaaApAc=
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,160 @@
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 玩家技能系统(召唤师技能)
/// 管理技能释放和冷却
/// </summary>
public class PlayerSkillSystem : MonoBehaviour
{
[Header("技能1:群体治疗")]
public Button skill1Button;
public Text skill1CooldownText;
public float skill1Cooldown = 20f;
public float skill1HealAmount = 100f;
private float skill1RemainingCooldown = 0f;
[Header("技能2:全屏AOE")]
public Button skill2Button;
public Text skill2CooldownText;
public float skill2Cooldown = 20f;
public float skill2Damage = 80f;
private float skill2RemainingCooldown = 0f;
private void Start()
{
// 绑定按钮点击事件
if (skill1Button != null)
{
skill1Button.onClick.AddListener(UseSkill1);
}
if (skill2Button != null)
{
skill2Button.onClick.AddListener(UseSkill2);
}
}
private void Update()
{
// 更新技能1冷却
if (skill1RemainingCooldown > 0)
{
skill1RemainingCooldown -= Time.deltaTime;
if (skill1Button != null)
{
skill1Button.interactable = false;
}
if (skill1CooldownText != null)
{
skill1CooldownText.text = Mathf.CeilToInt(skill1RemainingCooldown).ToString();
skill1CooldownText.gameObject.SetActive(true);
}
}
else
{
if (skill1Button != null)
{
skill1Button.interactable = true;
}
if (skill1CooldownText != null)
{
skill1CooldownText.gameObject.SetActive(false);
}
}
// 更新技能2冷却
if (skill2RemainingCooldown > 0)
{
skill2RemainingCooldown -= Time.deltaTime;
if (skill2Button != null)
{
skill2Button.interactable = false;
}
if (skill2CooldownText != null)
{
skill2CooldownText.text = Mathf.CeilToInt(skill2RemainingCooldown).ToString();
skill2CooldownText.gameObject.SetActive(true);
}
}
else
{
if (skill2Button != null)
{
skill2Button.interactable = true;
}
if (skill2CooldownText != null)
{
skill2CooldownText.gameObject.SetActive(false);
}
}
}
/// <summary>
/// 使用技能1:群体治疗
/// </summary>
public void UseSkill1()
{
if (skill1RemainingCooldown > 0)
{
return;
}
Debug.Log($"释放技能1:群体治疗(恢复 {skill1HealAmount} 生命)");
// 对所有友方单位施加治疗
BuffSystem.Instance.ApplyGroupHeal(skill1HealAmount);
// 开始冷却
skill1RemainingCooldown = skill1Cooldown;
// TODO: 播放技能特效
}
/// <summary>
/// 使用技能2:全屏AOE伤害
/// </summary>
public void UseSkill2()
{
if (skill2RemainingCooldown > 0)
{
return;
}
Debug.Log($"释放技能2:全屏AOE(造成 {skill2Damage} 伤害)");
// 对所有敌方单位造成伤害
var enemies = FindObjectsOfType<UnitBase>();
int hitCount = 0;
foreach (var unit in enemies)
{
var team = unit.GetComponent<UnitTeam>();
if (team != null && team.teamId == 1) // 敌方
{
var healthBar = unit.GetComponent<WorldHealthBar>();
if (healthBar != null && !healthBar.IsDead)
{
healthBar.TakeDamage(skill2Damage);
hitCount++;
}
}
}
Debug.Log($"全屏AOE命中 {hitCount} 个敌人");
// 开始冷却
skill2RemainingCooldown = skill2Cooldown;
// TODO: 播放技能特效
}
/// <summary>
/// 重置所有技能冷却(测试用)
/// </summary>
public void ResetAllCooldowns()
{
skill1RemainingCooldown = 0f;
skill2RemainingCooldown = 0f;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: CisbvXyoUn8k0PkPTbzEfXpqiXSMhTjkHc15rVEtnbXL0NUaW4VkyD8=
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,62 @@
using UnityEngine;
public class ShieldGuardSkill : UnitSkill
{
[Header("盾牌参数")]
[Min(1f)]
public float shieldDurability = 220f;
[Min(0.1f)]
public float shieldDuration = 4f;
[Range(0f, 1f)]
public float damageReduction = 0.35f;
public Vector3 shieldLocalPosition = new Vector3(0f, 1f, 0.7f);
public Vector3 shieldSize = new Vector3(1.5f, 1.8f, 0.12f);
private ShieldBarrier shield;
public ShieldBarrier ActiveShield => shield;
public override void ReleaseSkill()
{
EnsureShield();
shield.Refresh(shieldDurability, shieldDuration, shieldLocalPosition, shieldSize);
}
public override float ModifyIncomingDamage(float damage, GameObject attacker)
{
if (shield == null || !shield.IsActive)
{
return damage;
}
if (shield.TryBlock(attacker, damage))
{
return damage * (1f - damageReduction);
}
return damage;
}
private void EnsureShield()
{
if (shield != null)
{
return;
}
GameObject shieldObject = new GameObject("ShieldBarrier");
shieldObject.transform.SetParent(unit.transform, false);
BoxCollider boxCollider = shieldObject.AddComponent<BoxCollider>();
boxCollider.isTrigger = true;
boxCollider.size = shieldSize;
shield = shieldObject.AddComponent<ShieldBarrier>();
shield.Configure(unit, boxCollider);
shieldObject.SetActive(false);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: BntMsS6pUymOHB/6dKfMA7C7qYr3zT7pDxKENaWTJXDll6CyvBaNH2k=
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,69 @@
using UnityEngine;
public class StoneGolemSkill : UnitSkill
{
[Header("地裂参数")]
[Min(0f)]
public float skillDamage = 110f;
[Min(0.1f)]
public float skillRadius = 2f;
[Min(0f)]
public float stunDuration = 1f;
[Header("技能动画")]
[Min(0f)]
public float skillAnimationDuration = 0f;
[Header("特效")]
public GameObject shockwaveEffectPrefab;
private bool isSkillReady;
public override void ReleaseSkill()
{
if (unit == null)
{
return;
}
unit.FaceCurrentTarget(0f);
isSkillReady = true;
unit.PlaySkillAnimation(OnSkillFinished, skillAnimationDuration);
}
// 添加到地裂技能动画的命中帧;在命中帧结算伤害和眩晕。
public void OnSkillHit1()
{
if (!isSkillReady)
{
return;
}
// 生成扩散光圈特效
if (shockwaveEffectPrefab != null)
{
Vector3 effectPosition = unit.transform.position;
var effectObj = Instantiate(shockwaveEffectPrefab, effectPosition, shockwaveEffectPrefab.transform.rotation);
// 可选:动态配置特效参数(不配置则使用Prefab默认值)
var effect = effectObj.GetComponent<ShockwaveEffect>();
if (effect != null)
{
// 根据技能范围动态设置扩散半径
effect.overrideRadius = skillRadius;
// 可以设置颜色,例如:effect.overrideColor = new Color(1f, 0.8f, 0.2f, 1f);
}
}
unit.ApplyAreaSkillDamage(skillRadius, skillDamage, false);
unit.ApplyAreaStun(skillRadius, stunDuration);
isSkillReady = false;
}
private void OnSkillFinished()
{
isSkillReady = false;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: CC8d5C+qVXL85oNIASr9QqmYpLwsA9tVuzUYro25oZb3NHl6w2iNA1E=
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+18
View File
@@ -0,0 +1,18 @@
using UnityEngine;
public abstract class UnitSkill : MonoBehaviour
{
protected UnitBase unit;
protected virtual void Awake()
{
unit = GetComponent<UnitBase>();
}
public abstract void ReleaseSkill();
public virtual float ModifyIncomingDamage(float damage, GameObject attacker)
{
return damage;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: Wi9K4CiqAHqIYi4iwkLvt2K24jVu7gOoQzrHgM9LxGqhLcEJqXPR69Y=
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,41 @@
using UnityEngine;
public class WerewolfSkill : UnitSkill
{
[Header("狼嚎效果")]
[Min(0f)]
public float attackSpeedIncrease = 0.2f;
[Min(0f)]
public float duration = 5f;
private bool buffActive;
private float buffEndTime;
public override void ReleaseSkill()
{
ApplyHowlBuff();
}
private void ApplyHowlBuff()
{
if (buffActive)
{
buffEndTime = Time.time + duration;
return;
}
buffActive = true;
buffEndTime = Time.time + duration;
unit.MultiplyAttackSpeed(1f + attackSpeedIncrease, 2f);
}
private void Update()
{
if (buffActive && Time.time >= buffEndTime)
{
buffActive = false;
unit.MultiplyAttackSpeed(1f / (1f + attackSpeedIncrease), 2f);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: CX1K4XmqUC1Wf0EVbqMJfAnOkX/FLXd2ZcMaE6q7L8nno/KCp7gb5kA=
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: