396 lines
14 KiB
C#
396 lines
14 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.Linq;
|
||
using System.Threading.Tasks;
|
||
using UnityEngine;
|
||
using Debug = UnityEngine.Debug;
|
||
using UnityEditor.Animations;
|
||
using DG.Tweening;
|
||
|
||
public class Attack : MonoBehaviour
|
||
{
|
||
[Header("子弹预制体")] public GameObject bulletPrefab;
|
||
[Header("子弹数据")] public BulletData bulletData;
|
||
[Header("角色对象")] public Role role;
|
||
//[Header("攻击范围")] public float attackScope;
|
||
[Header("攻击类型")] public DamageType damageTyp = DamageType.noAttributeDamage;
|
||
|
||
[Header("攻击CD时间")] public float attackCooldown = 1f; // 攻击冷却时间
|
||
private float lastAttackTime = 0f; // 上次攻击的时间
|
||
|
||
[HideInInspector]
|
||
public List<GameObject> bulltes = new List<GameObject>();
|
||
|
||
[Header("角色动画控制器")] public Animator animator;
|
||
//[Header("火焰动画控制器")] public Animator fireAni;
|
||
[Header("火焰动画控制器")] public List<Animator> fireAnis;
|
||
|
||
[Header("子弹起始点")] public Transform BulletStartPos;
|
||
[Header("攻击速度")] public float AttackSpeed=1f;
|
||
public Vector2 direction;
|
||
|
||
[Header("子弹速度加成")]public float roleBulletSpeedAdd=0f;
|
||
//[Header("子弹长度")] public float scaleFactor;
|
||
[Header("子弹数量")] public int BulletNumber = 1;
|
||
[Header("攻击碰撞体")] public CircleCollider2D attackCollider;
|
||
[Header("矩形攻击碰撞体")] public BoxCollider2D attackColliderBox;
|
||
[Header("攻击范围图片")] public SpriteRenderer attackRangeSprite;
|
||
[Header("攻击持续时间")] public float AttackStayTime;//
|
||
[Header("攻击目标")] public GameObject Target;
|
||
[Header("攻击范围显示脚本")] public CharacterClick characterClick;
|
||
public bool isAttack = true;
|
||
public bool flag = false;
|
||
[HideInInspector] public float timer = 0;
|
||
//public float AttackScope
|
||
//{
|
||
// [DebuggerStepThrough]
|
||
// get => attackScope;
|
||
// [DebuggerStepThrough]
|
||
// set
|
||
// {
|
||
// attackScope = value;
|
||
// GetComponent<CircleCollider2D>().radius = attackScope;
|
||
// //Debug.Log("攻击半径"+GetComponent<CircleCollider2D>().radius);
|
||
// }
|
||
//}
|
||
|
||
public async void Start()
|
||
{
|
||
bulletData = new BulletData();
|
||
bulletData.BulletScattering = 1;
|
||
|
||
animator.SetFloat("AttackSpeed", AttackSpeed);
|
||
|
||
attackCooldown = transform.parent.GetComponent<enemy>().AttackCD;
|
||
|
||
SetAttackRange(); // 设置攻击范围
|
||
|
||
while (isAttack)
|
||
{
|
||
if (attackCollider || attackColliderBox)
|
||
{
|
||
// 检查是否可以进行攻击(基于冷却时间)
|
||
if (Time.time - lastAttackTime >= attackCooldown)
|
||
{
|
||
|
||
|
||
|
||
if (attackCollider)
|
||
{
|
||
Collider2D[] colliders = Physics2D.OverlapCircleAll(attackCollider.transform.position, attackCollider.radius);
|
||
GetAllColliderInAttackRange(colliders);
|
||
}
|
||
else if (attackColliderBox)
|
||
{
|
||
// 获取碰撞体的尺寸
|
||
Vector2 boxSize = attackColliderBox.size;
|
||
|
||
// 只检测右边一半,修改尺寸
|
||
boxSize.x /= 2f;
|
||
|
||
// 获取碰撞体的中心位置
|
||
Vector3 colliderCenter = attackColliderBox.transform.position;
|
||
|
||
// 计算右半部分的中心位置,确保中心点在矩形的右半部分
|
||
Vector3 rightCenter = new Vector3(colliderCenter.x + attackColliderBox.size.x / 4f, colliderCenter.y, colliderCenter.z);
|
||
|
||
// 使用OverlapBoxAll检测右半部分区域
|
||
Collider2D[] colliders = Physics2D.OverlapBoxAll(rightCenter, boxSize, 0f);
|
||
GetAllColliderInAttackRange(colliders);
|
||
}
|
||
|
||
lastAttackTime = Time.time; // 更新上次攻击时间
|
||
}
|
||
|
||
|
||
|
||
await Task.Delay(100); // 延迟,避免过于频繁地检测
|
||
}
|
||
else
|
||
{
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
private void Update()
|
||
{
|
||
if (flag)
|
||
{
|
||
timer += Time.deltaTime;
|
||
if (timer>AttackStayTime)
|
||
{
|
||
animator.SetInteger("State", 0);
|
||
isAttack = true;
|
||
timer = 0;
|
||
flag = false;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
public void GetAllColliderInAttackRange(Collider2D[] colliders)
|
||
{
|
||
foreach (Collider2D collider in colliders)
|
||
{
|
||
Role targetRole = collider.GetComponent<Role>();
|
||
|
||
if (targetRole && targetRole.camp != role.camp)
|
||
{
|
||
role.animationHighlight = 1;
|
||
if (animator != null)
|
||
{
|
||
if (bulletPrefab.GetComponent<Bullet>().myBulletType != BulletType.Spraying)
|
||
{
|
||
direction = (targetRole.transform.position - BulletStartPos.position).normalized;
|
||
Target = targetRole.gameObject;
|
||
animator.SetTrigger("Attack");
|
||
}
|
||
else if (bulletPrefab.GetComponent<Bullet>().myBulletType == BulletType.Spraying)
|
||
{
|
||
animator.SetInteger("State", 1);
|
||
|
||
flag = true;
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
lastAttackTime = Time.time; // 更新上次攻击时间
|
||
}
|
||
|
||
break; // 只攻击一个目标
|
||
}
|
||
else
|
||
{
|
||
if (animator != null)
|
||
{
|
||
//animator.SetInteger("State", 0);
|
||
}
|
||
else
|
||
{
|
||
role.animationHighlight = 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/*public void attack(Role targetRole)
|
||
{
|
||
|
||
if (bulletPrefab == null)
|
||
{
|
||
Debug.LogError("子弹预制体为空");
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
Vector2 direction = (targetRole.transform.position - transform.position).normalized;
|
||
|
||
if (bulletPrefab.GetComponent<Bullet>().myBulletType == BulletType.Spraying)
|
||
{
|
||
GameObject BulletGamobj = GameObject.Instantiate(bulletPrefab, this.transform.root);
|
||
BulletGamobj.GetComponent<Bullet>().role = role;
|
||
BulletGamobj.GetComponent<Bullet>().attackObj = this;
|
||
// BulletGamobj.transform.up = direction;
|
||
BulletGamobj.transform.position =new Vector2(transform.position.x+0.15f, transform.position.y+0.2f);
|
||
bulltes.Add(BulletGamobj);
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
for (int i = 0; i < bulletData.BulletScattering; i++)
|
||
{
|
||
// 改变子弹方向,根据角色自身的攻击范围来计算
|
||
GameObject BulletGamobj = GameObject.Instantiate(bulletPrefab, this.transform.root);
|
||
BulletGamobj.GetComponent<Bullet>().role = role;
|
||
BulletGamobj.GetComponent<Bullet>().attackObj = this;
|
||
BulletGamobj.transform.up = direction;
|
||
BulletGamobj.transform.position = transform.position;
|
||
bulltes.Add(BulletGamobj);
|
||
}
|
||
}
|
||
}*/
|
||
|
||
|
||
|
||
public void Pointattack()
|
||
{
|
||
|
||
if (bulletPrefab == null)
|
||
{
|
||
Debug.LogError("子弹预制体为空");
|
||
return;
|
||
}
|
||
|
||
|
||
for (int i = 0; i < BulletNumber; i++)
|
||
{
|
||
// 改变子弹方向,根据角色自身的攻击范围来计算
|
||
GameObject BulletGamobj = GameObject.Instantiate(bulletPrefab, this.transform.root);
|
||
BulletGamobj.GetComponent<Bullet>().role = role;
|
||
BulletGamobj.GetComponent<Bullet>().attackObj = this;
|
||
BulletGamobj.GetComponent<Bullet>().bulletData.BulletSpeed *= (1 + roleBulletSpeedAdd);
|
||
BulletGamobj.GetComponent<Bullet>().Target = Target;
|
||
BulletGamobj.transform.up = direction;
|
||
BulletGamobj.transform.position = BulletStartPos.position;
|
||
bulltes.Add(BulletGamobj);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
public void Fireattack()
|
||
{
|
||
if (bulletPrefab == null)
|
||
{
|
||
Debug.LogError("子弹预制体为空");
|
||
return;
|
||
}
|
||
|
||
// 检查子弹类型是否为 Spraying
|
||
if (bulletPrefab.GetComponent<Bullet>().myBulletType == BulletType.Spraying)
|
||
{
|
||
// 根据 BulletNumber 生成不同数量和旋转角度的子弹
|
||
switch (BulletNumber)
|
||
{
|
||
case 1:
|
||
// 生成一个不旋转的子弹
|
||
GenerateBullet(0f, BulletStartPos.position, new Vector2(0, 0));
|
||
break;
|
||
|
||
case 3:
|
||
// 生成三个子弹:一个不旋转,一个向上旋转30度,一个向下旋转30度
|
||
GenerateBullet(-35f, BulletStartPos.position, new Vector2(0, -0.25f));
|
||
GenerateBullet(0f, BulletStartPos.position, new Vector2(0, 0));
|
||
GenerateBullet(35f, BulletStartPos.position, new Vector2(0, 0.25f));
|
||
break;
|
||
|
||
default:
|
||
// 可选:处理其他 BulletNumber 值的情况
|
||
Debug.LogWarning($"BulletNumber 为 {BulletNumber} 时未定义的生成逻辑。");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
private void GenerateBullet(float angle, Vector2 startPos, Vector2 changePos)//角度,旋转中心点
|
||
{
|
||
// 实例化子弹对象并设置父物体为 transform.root
|
||
GameObject bulletGameObj = GameObject.Instantiate(bulletPrefab, transform.root);
|
||
// 获取子弹的原始宽度
|
||
float originalWidth = bulletGameObj.GetComponentInChildren<SpriteRenderer>().bounds.size.x;
|
||
|
||
// 设置子弹的缩放
|
||
|
||
if (role.AttackRange / 2>1)
|
||
{
|
||
bulletGameObj.transform.localScale = new Vector2(role.AttackRange / 2, role.AttackRange / 3);
|
||
// 计算缩放后的偏移量
|
||
float offsetX = (originalWidth * (role.AttackRange / 2)) / 4f+0.15f;
|
||
|
||
// 调整子弹的位置,确保左边界不变
|
||
bulletGameObj.transform.position = new Vector2(bulletGameObj.transform.position.x + offsetX, bulletGameObj.transform.position.y);
|
||
|
||
|
||
}
|
||
bulletGameObj.transform.position = new Vector2(bulletGameObj.transform.position.x + 1.75f, bulletGameObj.transform.position.y + 0.2f);
|
||
// 获取动画组件(如果需要的话)
|
||
fireAnis.Add(bulletGameObj.GetComponentInChildren<Animator>());
|
||
|
||
// 设置子弹的初始位置,保持偏移量
|
||
|
||
|
||
bulletGameObj.GetComponent<Bullet>().role = role;
|
||
bulletGameObj.GetComponent<Bullet>().attackObj = this;
|
||
|
||
|
||
// 计算子弹相对于旋转中心的偏移
|
||
Vector2 direction = bulletGameObj.transform.position - (Vector3)startPos;
|
||
|
||
// 旋转偏移
|
||
direction = Quaternion.Euler(0, 0, angle) * direction;
|
||
|
||
// 更新子弹的位置
|
||
bulletGameObj.transform.position = startPos + direction;
|
||
|
||
// 设置子弹的旋转角度
|
||
bulletGameObj.transform.rotation = Quaternion.Euler(0, 0, angle);
|
||
bulletGameObj.transform.position = bulletGameObj.transform.position + (Vector3)changePos;
|
||
|
||
|
||
|
||
|
||
|
||
// 将生成的子弹添加到子弹列表中
|
||
bulltes.Add(bulletGameObj);
|
||
}
|
||
|
||
|
||
public void EndFire()
|
||
{
|
||
foreach (Animator ani in fireAnis)
|
||
{
|
||
ani.SetInteger("State", 1);
|
||
}
|
||
fireAnis.Clear();
|
||
//Debug.Log("停止火焰");
|
||
|
||
}
|
||
|
||
|
||
private void OnDisable()
|
||
{
|
||
bulltes.Clear();
|
||
}
|
||
|
||
public void SetAttackRange()
|
||
{
|
||
if (attackCollider)
|
||
{
|
||
// 设置碰撞体的半径
|
||
attackCollider.radius = role.AttackRange;
|
||
|
||
|
||
|
||
|
||
// 计算缩放因子,使得图片的直径与碰撞体的直径匹配
|
||
characterClick.OrSizeX = role.AttackRange * 2f / characterClick.StartSizeX; // * 2f 因为 radius 是半径,图片的尺寸通常是直径
|
||
characterClick.OrSizeY = characterClick.OrSizeX;
|
||
|
||
|
||
|
||
}
|
||
else if(attackColliderBox)
|
||
{
|
||
Vector2 boxSize = attackColliderBox.size;
|
||
|
||
// 假设攻击范围决定了矩形的长宽比
|
||
// attackRange * 2 可以增加攻击范围的矩形尺寸,调整比例或常数以适应你的需要
|
||
boxSize.x = role.AttackRange * 2f+2; // 设置矩形宽度
|
||
//boxSize.y = role.AttackRange/3; // 设置矩形高度
|
||
|
||
// 更新矩形碰撞体的尺寸
|
||
attackColliderBox.size = boxSize;
|
||
|
||
|
||
|
||
//float originalWidth = attackRangeSprite.bounds.size.x;
|
||
//attackRangeSprite.transform.localScale = new Vector3(boxSize.x*1.4f/4, boxSize.y, 1f);
|
||
characterClick.OrSizeX = boxSize.x / characterClick.StartSizeX; // * 2f 因为 radius 是半径,图片的尺寸通常是直径
|
||
characterClick.OrSizeY = boxSize.y*2 / characterClick.StartSizeY;
|
||
attackRangeSprite.transform.position = new Vector2(attackRangeSprite.transform.position.x - (characterClick.StartSizeX - characterClick.OrSizeX) / 2, attackRangeSprite.transform.position.y);
|
||
//characterClick.OrSizeY = 1;
|
||
Debug.Log("修改图片宽度");
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
}
|