392 lines
13 KiB
C#
392 lines
13 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
using Unity.VisualScripting;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
using System.Linq;
|
|
|
|
public enum BulletType
|
|
{
|
|
Bullet,
|
|
Lightning,
|
|
Spraying, //原地喷射
|
|
XuLi //蓄力攻击
|
|
}
|
|
public enum BulletAttributes
|
|
{
|
|
Not,
|
|
Gold,//金木水火土
|
|
Wood,
|
|
Water,
|
|
Fire,
|
|
Earth
|
|
}
|
|
|
|
|
|
|
|
public enum BulletMoveType
|
|
{/// <summary>
|
|
/// 子弹移动方式:点对点,
|
|
/// </summary>
|
|
PeerToPeer,
|
|
/// <summary>
|
|
/// 方向移动
|
|
/// </summary>
|
|
PointToDirection,
|
|
Scope
|
|
}
|
|
|
|
|
|
public class BulletData
|
|
{
|
|
[Header("子弹穿透次数")] public int NumberOfBulletPenetrations = 1;
|
|
/// <summary>
|
|
/// 子弹散射次数
|
|
/// </summary>
|
|
[Header("子弹散射次数")] public int BulletScattering = 1;
|
|
[Header("子弹连发次数")] public int BulletBurstTimes = 1;
|
|
[Header("子弹连发间隔")] public float BulletBurstInterval ;
|
|
[Header("子弹穿透衰减")] public float BulletPenetrationAttenuation = 0.2f;
|
|
[Header("子弹飞行速度")] public float BulletSpeed = 5f;
|
|
[Header("子弹攻击冷却")] public float BulletAttackCooldown = 1f;
|
|
[Header("子弹伤害")] public float attack = 10;
|
|
|
|
public BulletData()
|
|
{
|
|
|
|
}
|
|
public BulletData(int numberOfBulletPenetrations, int bulletScattering, int bulletBurstTimes, float bulletBurstInterval, float bulletPenetrationAttenuation, float bulletSpeed, float bulletAttackCooldown)
|
|
{
|
|
NumberOfBulletPenetrations = numberOfBulletPenetrations;
|
|
BulletScattering = bulletScattering;
|
|
BulletBurstTimes = bulletBurstTimes;
|
|
BulletBurstInterval = bulletBurstInterval;
|
|
BulletPenetrationAttenuation = bulletPenetrationAttenuation;
|
|
BulletSpeed = bulletSpeed;
|
|
BulletAttackCooldown = bulletAttackCooldown;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return
|
|
$"{nameof(NumberOfBulletPenetrations)}: {NumberOfBulletPenetrations}, {nameof(BulletScattering)}: {BulletScattering}, {nameof(BulletBurstTimes)}: {BulletBurstTimes}, {nameof(BulletBurstInterval)}: {BulletBurstInterval}, {nameof(BulletPenetrationAttenuation)}: {BulletPenetrationAttenuation}, {nameof(BulletSpeed)}: {BulletSpeed}, {nameof(BulletAttackCooldown)}: {BulletAttackCooldown}";
|
|
}
|
|
}
|
|
public class Bullet : MonoBehaviour
|
|
{
|
|
[Header("子弹发射角色对象")] public Role role;
|
|
[Header("子弹发射范围对象")] public Attack attackObj;
|
|
[Header("子弹类型")] public BulletType myBulletType;
|
|
[Header("子弹属性")] public BulletAttributes bulletAttributes;
|
|
[Header("攻击类型")] public BulletMoveType bulletMoveType;
|
|
[Header("子弹数据")] public BulletData bulletData = new BulletData();
|
|
[Header("销毁时间,默认是10f")] public float BulletDeadTimer = 10f;
|
|
[Header("子弹动画")] public Animator animator;
|
|
[Header("子弹移动参数")] public bool IsMove = true;
|
|
[Header("子弹碰撞体")] public CircleCollider2D Collider2D;
|
|
[Header("子弹特效预制体")] public List<GameObject> effectPres = new List<GameObject>();
|
|
public float timer = 0;
|
|
[Header("子弹攻击数量")] public int NumberOfBulletAttacks = 1;
|
|
[Header("攻击目标")] public GameObject Target;
|
|
[Header("子弹是否不锁定目标")] public bool noLockEnemy=false;
|
|
[Header("子弹是否会分裂")] public bool Cansplit = false;
|
|
[Header("分裂子弹的预制体")] public GameObject smallBulletPrefab;
|
|
[Header("子弹是否会爆炸")] public bool CanBoom = false;
|
|
private void Update()
|
|
{
|
|
switch (this.bulletMoveType)
|
|
{
|
|
//更具子弹的移动方式来移动
|
|
case BulletMoveType.PeerToPeer:
|
|
if (IsMove)
|
|
{
|
|
|
|
if (Target != null&&Target.activeSelf==true&&!noLockEnemy)
|
|
{
|
|
this.gameObject.transform.position = Vector3.MoveTowards(this.gameObject.transform.position, Target.transform.position, Time.deltaTime * bulletData.BulletSpeed);
|
|
}
|
|
else
|
|
{
|
|
this.gameObject.transform.Translate(Vector3.up * Time.deltaTime * bulletData.BulletSpeed);
|
|
}
|
|
|
|
|
|
timer += Time.deltaTime;
|
|
if (timer > BulletDeadTimer)
|
|
{
|
|
attackObj.bulltes.Remove(this.gameObject);
|
|
Debug.Log("对象已成功移除。当前列表数量:" + attackObj.bulltes.Count);
|
|
Destroy(this.gameObject);
|
|
}
|
|
}
|
|
|
|
break;
|
|
case BulletMoveType.PointToDirection:
|
|
break;
|
|
case BulletMoveType.Scope:
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
private void OnTriggerEnter2D(Collider2D collision)
|
|
{
|
|
Role Crole = collision.gameObject.GetComponent<Role>();
|
|
if (Crole)
|
|
{
|
|
if (Crole.camp != role.camp)
|
|
{
|
|
if (NumberOfBulletAttacks < 0)
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (this.myBulletType== BulletType.Spraying)
|
|
{
|
|
NumberOfBulletAttacks += 1;
|
|
}
|
|
|
|
NumberOfBulletAttacks -= 1;
|
|
|
|
foreach (var buff in role.storageBuff)
|
|
{
|
|
if (!Crole.PlayerBuff.Contains(buff))
|
|
{
|
|
Crole.PlayerBuff.Add(buff);
|
|
}
|
|
}
|
|
|
|
Crole.ApplyBuffs();
|
|
|
|
// Debug.Log(this.role.gameObject.name + "进行攻击计算");
|
|
int direction = 0;
|
|
if (collision.transform.position.x > transform.position.x) //子弹打到敌人左边,飘字显示到右边
|
|
{
|
|
direction = 1;
|
|
}
|
|
if (!CanBoom)//判断子弹是否会爆炸
|
|
{
|
|
Crole.bloodLoss(new object[] { Crole, role.DamageCreate(Crole.GetComponent<Role>()), attackObj.damageTyp, role }, direction);
|
|
attackObj.bulltes.Remove(this.gameObject);
|
|
if (myBulletType != BulletType.Spraying)
|
|
{
|
|
|
|
|
|
if (animator == null)
|
|
{
|
|
SplitBullet();
|
|
attackObj.bulltes.Remove(this.gameObject);
|
|
Destroy(this.gameObject);
|
|
}
|
|
else
|
|
{
|
|
IsMove = false; //停止移动
|
|
Collider2D.enabled = false; //关闭碰撞体
|
|
transform.position = collision.transform.position;
|
|
animator.SetTrigger("Boom");
|
|
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (animator!=null)
|
|
{
|
|
IsMove = false; //停止移动
|
|
Collider2D.enabled = false; //关闭碰撞体
|
|
transform.position = collision.transform.position;
|
|
animator.SetTrigger("Boom");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bulletAttributes == BulletAttributes.Not) //无属性
|
|
{
|
|
Crole.FlashRedEffect();
|
|
|
|
}
|
|
|
|
if (bulletAttributes == BulletAttributes.Fire) //火
|
|
{
|
|
|
|
if (effectPres.Count == 1)
|
|
{
|
|
GameObject go = Instantiate(effectPres[0], collision.transform);
|
|
go.transform.position = new Vector2(collision.transform.position.x,
|
|
collision.transform.position.y + 0.2f);
|
|
go.GetComponent<Huo>().bullet = this;
|
|
Crole.FlashRedEffect();
|
|
//Debug.Log("创建火焰");
|
|
}
|
|
|
|
}
|
|
|
|
if (bulletAttributes == BulletAttributes.Water) //水
|
|
{
|
|
if (effectPres.Count > 1)
|
|
{
|
|
GameObject go = Instantiate(effectPres[Random.Range(0, effectPres.Count - 1)],
|
|
collision.transform);
|
|
go.transform.position = new Vector2(collision.transform.position.x,
|
|
collision.transform.position.y - 0.2f);
|
|
collision.transform.GetComponent<enemy>().SlowDown(0.2f, 3f);
|
|
Crole.FlashRedEffect(1, 3f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private float lastDamageTime = 0f;
|
|
private void OnTriggerStay2D(Collider2D collision)
|
|
{
|
|
Role Crole = collision.gameObject.GetComponent<Role>();
|
|
if (Crole)
|
|
{
|
|
if (Crole.camp != role.camp)
|
|
{
|
|
|
|
|
|
int direction = 0;
|
|
if (collision.transform.position.x >= transform.position.x)//子弹打到敌人左边,飘字显示到右边
|
|
{
|
|
direction = 1;
|
|
}
|
|
|
|
if (myBulletType == BulletType.Spraying)
|
|
{
|
|
|
|
if (Time.time - lastDamageTime > 1f) // 每秒扣一次血
|
|
{
|
|
|
|
Crole.bloodLoss(new object[] { Crole, role.DamageCreate( Crole.GetComponent<Role>()), attackObj.damageTyp, role });
|
|
Crole.FlashRedEffect();
|
|
lastDamageTime = Time.time;
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void DesBullet()
|
|
{
|
|
attackObj.bulltes.Remove(this.gameObject);
|
|
Destroy(this.gameObject);
|
|
}
|
|
|
|
|
|
private void OnTriggerExit2D(Collider2D collision)
|
|
{
|
|
//Debug.Log("进入检测范围");
|
|
Role Crole = collision.gameObject.GetComponent<Role>();
|
|
if (Crole)
|
|
{
|
|
if (Crole.camp != role.camp)
|
|
{
|
|
|
|
//Debug.Log("对象已成功移除。当前列表数量:" + attackObj.bulltes.Count);
|
|
if (myBulletType != BulletType.Spraying)
|
|
{
|
|
if (animator==null)
|
|
{
|
|
attackObj.bulltes.Remove(this.gameObject);
|
|
Destroy(this.gameObject);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SplitBullet()//子弹分列
|
|
{
|
|
if (Cansplit)
|
|
{
|
|
// 获取当前子弹的前进方向
|
|
Vector3 currentDirection = transform.forward;
|
|
|
|
// 根据生成的数量来生成小子弹
|
|
for (int i = 0; i < attackObj.splitNum; i++)
|
|
{
|
|
// 在当前方向上随机生成偏移量
|
|
Vector3 randomOffset = new Vector3(Random.Range(-0.2f, 0.2f), Random.Range(-0.2f, 0.2f));
|
|
|
|
// 生成一个小子弹
|
|
GameObject smallBullet = Instantiate(smallBulletPrefab, transform.position, Quaternion.identity);
|
|
smallBullet.GetComponent<SmallBullet>().role = role;
|
|
smallBullet.GetComponent<SmallBullet>().attackObj=attackObj;
|
|
smallBullet.GetComponent<SmallBullet>().Target = Target;
|
|
// 为小子弹设置飞行方向(当前方向 + 随机偏移)
|
|
smallBullet.transform.up = currentDirection+randomOffset;
|
|
|
|
// 处理小子弹的相关逻辑,例如攻击属性、生命周期等
|
|
}
|
|
}
|
|
}
|
|
|
|
public void BulletBoom() // 子弹爆炸
|
|
{
|
|
|
|
|
|
// 扩展碰撞体的大小,模拟爆炸范围
|
|
float explosionRadius = attackObj.BoomRange; // 设置爆炸的半径大小
|
|
|
|
|
|
|
|
// 检测爆炸范围内的敌人
|
|
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(transform.position, explosionRadius);
|
|
|
|
foreach (var enemyCollider in hitEnemies)
|
|
{
|
|
Role enemyRole = enemyCollider.gameObject.GetComponent<Role>();
|
|
if (enemyRole != null && enemyRole.camp != role.camp) // 如果是敌人并且属于不同的阵营
|
|
{
|
|
// 计算伤害值,可以根据子弹的类型或其他参数来调整
|
|
float damage = role.DamageCreate(enemyRole);
|
|
|
|
// 扣血操作
|
|
enemyRole.bloodLoss(new object[] { enemyRole, damage, attackObj.damageTyp, role });
|
|
|
|
enemyRole.FlashRedEffect();
|
|
}
|
|
}
|
|
|
|
|
|
// 销毁当前子弹
|
|
attackObj.bulltes.Remove(this.gameObject);
|
|
Destroy(this.gameObject);
|
|
}
|
|
|
|
void OnDestroy()
|
|
{
|
|
// 清理动态加载资源
|
|
if (transform.GetComponent<Renderer>() != null)
|
|
{
|
|
var material = transform.GetComponent<Renderer>().material;
|
|
if (material != null) Destroy(material);
|
|
|
|
var texture = material.mainTexture;
|
|
if (texture != null) Destroy(texture);
|
|
}
|
|
|
|
// 停止协程
|
|
StopAllCoroutines();
|
|
|
|
|
|
// 清理未使用的资源
|
|
Resources.UnloadUnusedAssets();
|
|
}
|
|
}
|