UnityCommon/Role/Attack.cs
2024-12-28 16:22:54 +08:00

396 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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("修改图片宽度");
}
}
}