Files
MRCS/Assets/_MrCs/Scripts/Bullets/Bullet.cs

275 lines
7.4 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 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;
#if UNITY_EDITOR
[DisplayOnly]
#endif
public int ownerIndex;
public float userTime;
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;
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;
}
}
/// <summary>
/// This will be called when fixedupdate called
/// </summary>
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<Player>();
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<Explosion>();
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<IDamagable>();
if (component != null)
{
OnApplyDamage(component);
}
DamagePlayer hitPlayer = _handlingHit.collider.transform.GetComponentInParent<DamagePlayer>();
if (hitPlayer != null)
{
if(team== hitPlayer.player.teamType)
return;
GameManager.Ins.RpcShowDamageNumber(damage,transform.position,hitPlayer.damageType==DamagePlayerType.Helmet);
hitPlayer.ApplyDamage(damage,ownerIndex,transform);
}
}
[Server]
public virtual void OnApplyDamage(IDamagable damagable) { }
}