using System; using DragonLi.Core; using DragonLi.Frame; using Mirror; using UnityEngine; public class Bullet : NetworkBehaviour { /// /// 子弹类型 /// #if UNITY_EDITOR [DisplayOnly] #endif public GunType type; [Header("伤害")] #if UNITY_EDITOR [DisplayOnly] #endif public float damage = 0; [Header("击中删除时间")] public float despawn_delay = 0.1f; [Header("自动删除时间")] public float auto_despawn_delay = 5f; [Header("撞击预制体")] public GameObject impact_prefab; [Header("撞击删除时间")] public float impact_despawn_time = 1f; [Header("是否使用重力")] public bool use_gravity = false; public bool hit_trigger = false; [Header("目标图层")] public LayerMask HitLayer; public TeamType team; public int score; #if UNITY_EDITOR [DisplayOnly] #endif public int ownerIndex; public float userTime; private Rigidbody rigidbodyComponent; /// /// 刚体组件 /// public Rigidbody RigidbodyComponent { get { if (rigidbodyComponent == null) { rigidbodyComponent = GetComponentInChildren(); } return rigidbodyComponent; } } private bool _isHit = false; private bool _isValid = true; private float _despawnTime = 0f; private RaycastHit _handlingHit; #region 生命周期 public void Awake() { RigidbodyComponent.useGravity = use_gravity; RigidbodyComponent.constraints = (RigidbodyConstraints)112; } public void OnEnable() { _isHit = false; _isValid = true; _despawnTime = Time.time + auto_despawn_delay; } public void Update() { if (isServer) { if (_isValid) { if (_isHit) { DespawnSelf(); return; } if (_despawnTime < Time.time) { _isValid = false; NetworkServer.Destroy(transform.gameObject); } } } } internal void FixedUpdate() { if (isServer && !_isHit && HitCheck()) { // Debug.Log("撞击"); _isHit = true; isTrigger = false; SpawnImpact(); ApplyDamage(); } OnFixedUpdate(); } public bool isTrigger; private void OnTriggerEnter(Collider other) { // 检查 other 的 layer 是否被包含在 HitLayer 中 // if (other.gameObject.layer == LayerMask.NameToLayer("Ground")||other.gameObject.layer == LayerMask.NameToLayer("Obstacle")) // { // isTrigger = true; // } if (((1 << other.gameObject.layer) & HitLayer.value) != 0) { isTrigger = true; } } /// /// This will be called when fixedupdate called /// protected virtual void OnFixedUpdate() { } #endregion [Server] public virtual void OnSpawn(int curOwnerIndex, Vector3 recoil, float recoilCount,float time) { this.ownerIndex = curOwnerIndex; rigidbodyComponent.velocity = recoil.normalized * recoilCount; rigidbodyComponent.rotation = Quaternion.LookRotation(recoil.normalized); userTime = time; foreach (var item in NetworkServer.connections.Values) { if (item != null && item.identity != null) { Player player = item.identity.GetComponent(); if (player != null&& player.index == ownerIndex) { team = player.teamType; switch (team) { case TeamType.Red: AddLayerToHitLayer("Shield_Blue"); break; case TeamType.Blue: AddLayerToHitLayer("Shield_Red"); break; } } } } gameObject.layer= GetBulletLayer(team); } public void AddLayerToHitLayer(string layerName) { int layer = LayerMask.NameToLayer(layerName); if (layer == -1) { Debug.LogWarning("Layer 名称不存在:" + layerName); return; } // LayerMask 使用位掩码表示,每一位对应一个 Layer HitLayer |= (1 << layer); } public static int GetBulletLayer(TeamType team) { switch (team) { case TeamType.Blue: return LayerMask.NameToLayer("Bullet_Blue"); case TeamType.Red: return LayerMask.NameToLayer("Bullet_Red"); } return 0; } [Server] public void DespawnSelf() { _isValid = false; CoroutineTaskManager.Instance.WaitSecondTodo(() => { NetworkServer.Destroy(transform.gameObject); }, despawn_delay); } [Server] public virtual void SpawnImpact() { if (impact_prefab != null) { GameObject impact = Instantiate(impact_prefab); impact.transform.position = _handlingHit.point; NetworkServer.Spawn(impact); Explosion ex = impact.GetComponent(); Vector3 normal = _handlingHit.normal; // 在这里处理特效的生成和方向 // 计算特效的旋转方向,使用法线信息 Quaternion rotation = Quaternion.LookRotation(normal); // 将特效的旋转方向设置为法线方向 impact.transform.rotation = rotation; if (ex != null) { ex.OnSpawn(team,userTime,ownerIndex); } // CoroutineTaskManager.Instance.WaitSecondTodo(() => // { // NetworkServer.Destroy(impact); // }, impact_despawn_time); // 碰撞点的法线方向 } } [Server] public virtual bool HitCheck() { Vector3 position = transform.position; Vector3 velocity = RigidbodyComponent.velocity * Time.deltaTime; if (isTrigger) return true; if (Physics.Raycast(position, velocity, out _handlingHit, velocity.magnitude, HitLayer)) { if (hit_trigger && _handlingHit.collider.isTrigger) { return false; } return true; } return false; } [Server] public virtual void ApplyDamage() { if(_handlingHit.collider==null) return; IDamagable component = _handlingHit.collider.transform.GetComponent(); if (component != null) { OnApplyDamage(component); } DamagePlayer hitPlayer = _handlingHit.collider.transform.GetComponentInParent(); if (hitPlayer != null) { if(team== hitPlayer.player.teamType) return; GameManager.Ins.RpcShowDamageNumber(damage,transform.position,hitPlayer.damageType==DamagePlayerType.Helmet); hitPlayer.ApplyDamage(damage,ownerIndex,transform,score); } } [Server] public virtual void OnApplyDamage(IDamagable damagable) { } }