Files
Zombie/Assets/_Zombie/Scripts/Bullets/Bullet.cs

204 lines
5.1 KiB
C#

using System;
using DragonLi.Core;
using DragonLi.Frame;
using Mirror;
using UnityEngine;
public class Bullet : NetworkBehaviour
{
/// <summary>
/// 子弹类型
/// </summary>
#if UNITY_EDITOR
[DisplayOnly]
#endif
public BulletType type;
[Header("伤害")]
#if UNITY_EDITOR
[DisplayOnly]
#endif
public float damage = 0;
[Header("破韧")]
#if UNITY_EDITOR
[DisplayOnly]
#endif
public float deToughness = 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;
#if UNITY_EDITOR
[DisplayOnly]
#endif
public int ownerIndex;
private Rigidbody rigidbodyComponent;
/// <summary>
/// 刚体组件
/// </summary>
public Rigidbody RigidbodyComponent
{
get
{
if (rigidbodyComponent == null)
{
rigidbodyComponent = GetComponentInChildren<Rigidbody>();
}
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;
SpawnImpact();
ApplyDamage();
}
OnFixedUpdate();
}
/// <summary>
/// This will be called when fixedupdate called
/// </summary>
protected virtual void OnFixedUpdate() { }
#endregion
[Server]
public virtual void OnSpawn(int ownerIndex, Vector3 recoil, float recoilCount)
{
this.ownerIndex = ownerIndex;
rigidbodyComponent.velocity = recoil.normalized * recoilCount;
rigidbodyComponent.rotation = Quaternion.LookRotation(recoil.normalized);
}
[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);
Debug.Log("生成击中点");
impact.transform.position = _handlingHit.point;
NetworkServer.Spawn(impact);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
NetworkServer.Destroy(impact);
}, impact_despawn_time);
// 碰撞点的法线方向
Vector3 normal = _handlingHit.normal;
// 在这里处理特效的生成和方向
// 计算特效的旋转方向,使用法线信息
Quaternion rotation = Quaternion.LookRotation(normal);
// 将特效的旋转方向设置为法线方向
impact.transform.rotation = rotation;
}
}
[Server]
public virtual bool HitCheck()
{
Vector3 position = transform.position;
Vector3 velocity = RigidbodyComponent.velocity * Time.deltaTime;
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()
{
// IDamagable component = _handlingHit.transform.GetComponent<IDamagable>();
IDamagable component = _handlingHit.transform.GetComponent<IDamagable>();
if (component != null)
{
OnApplyDamage(component);
}
Player hitPlayer = _handlingHit.transform.GetComponentInParent<Player>();
if (hitPlayer != null)
{
OnHitPlayer(hitPlayer.index);
}
}
[Server]
public virtual void OnApplyDamage(IDamagable damagable) { }
[Server]
public virtual void OnHitPlayer(int index) { }
}