245 lines
6.0 KiB
C#
245 lines
6.0 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using DragonLi.Core;
|
|
using Mirror;
|
|
using UnityEngine;
|
|
using NaughtyAttributes;
|
|
using DragonLi.Frame;
|
|
using System;
|
|
|
|
|
|
public enum BulletType
|
|
{
|
|
Normal = 1,
|
|
Energy = 2,
|
|
Rocket = 3,
|
|
Shot = 4,
|
|
QY = 5,
|
|
RobotMesh = 6,
|
|
Super = 7,
|
|
Grenade = 8,
|
|
BossGrenadeBullet = 9,
|
|
BossNormal = 10,
|
|
Turret = 11,
|
|
}
|
|
|
|
public class Bullet : Entity
|
|
{
|
|
[Header("伤害")]
|
|
public float damage = 0;
|
|
[Header("击中删除时间")]
|
|
public float despawn_delay = 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;
|
|
|
|
[SyncVar]
|
|
[NonSerialized]
|
|
public bool isHit = false;
|
|
[NonSerialized]
|
|
public bool isValid = true;
|
|
[NonSerialized]
|
|
public float despawnTime = 0f;
|
|
[NonSerialized]
|
|
public RaycastHit handlingHit;
|
|
|
|
public int ownerIndex;
|
|
|
|
public float GunDamage
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public string SpawnPoolID
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
#region 生命周期
|
|
|
|
public override void InitData()
|
|
{
|
|
Data.Add("despawn_delay", new DataRow(SupportDataType.Int)
|
|
{
|
|
Name = "despawn_delay",
|
|
FloatValue = despawn_delay
|
|
});
|
|
Data.Add("auto_despawn_delay", new DataRow(SupportDataType.Float)
|
|
{
|
|
Name = "auto_despawn_delay",
|
|
FloatValue = auto_despawn_delay
|
|
});
|
|
Data.Add("use_gravity", new DataRow(SupportDataType.Boolean)
|
|
{
|
|
Name = "use_gravity",
|
|
BooleanValue = use_gravity
|
|
});
|
|
Data.Add("hit_trigger", new DataRow(SupportDataType.Boolean)
|
|
{
|
|
Name = "hit_trigger",
|
|
BooleanValue = hit_trigger
|
|
});
|
|
Data.Add("impact_prefab", new DataRow(SupportDataType.UObject)
|
|
{
|
|
Name = "impact_prefab",
|
|
ObjectValue = impact_prefab
|
|
});
|
|
Data.Add("impact_despawn_time", new DataRow(SupportDataType.Float)
|
|
{
|
|
Name = "impact_despawn_time",
|
|
FloatValue = impact_despawn_time
|
|
});
|
|
base.InitData();
|
|
}
|
|
|
|
[Server]
|
|
public void Init(int ownerIndex)
|
|
{
|
|
this.ownerIndex = ownerIndex;
|
|
}
|
|
|
|
public override void Awake()
|
|
{
|
|
base.Awake();
|
|
RigidbodyComponent.useGravity = Data["use_gravity"].BooleanValue;
|
|
RigidbodyComponent.constraints = (RigidbodyConstraints)112;
|
|
}
|
|
|
|
public override void OnEnable()
|
|
{
|
|
isHit = false;
|
|
isValid = true;
|
|
despawnTime = Time.time + Data["auto_despawn_delay"].FloatValue;
|
|
base.OnEnable();
|
|
}
|
|
|
|
public override void Update()
|
|
{
|
|
if (isServer)
|
|
{
|
|
if (isValid)
|
|
{
|
|
if (isHit)
|
|
{
|
|
DespawnSelf();
|
|
return;
|
|
}
|
|
if (despawnTime < Time.time)
|
|
{
|
|
|
|
isValid = false;
|
|
NetworkServer.Destroy(transform.gameObject);
|
|
}
|
|
base.Update();
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void FixedUpdate()
|
|
{
|
|
if (isServer && !isHit && HitCheck())
|
|
{
|
|
isHit = true;
|
|
SpawnImpact();
|
|
ApplyDamage();
|
|
HitTarget();
|
|
}
|
|
OnFixedUpdate();
|
|
}
|
|
|
|
/// <summary>
|
|
/// This will be called when fixedupdate called
|
|
/// </summary>
|
|
protected virtual void OnFixedUpdate()
|
|
{
|
|
}
|
|
|
|
#endregion
|
|
|
|
[Server]
|
|
public virtual void SpawnImpact()
|
|
{
|
|
GameObject impactPre = (GameObject)Data["impact_prefab"].ObjectValue;
|
|
if (impactPre != null)
|
|
{
|
|
GameObject impact = Instantiate(impactPre);
|
|
impact.transform.position = handlingHit.point;
|
|
//impact.transform.localEulerAngles
|
|
NetworkServer.Spawn(impact);
|
|
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
|
|
{
|
|
NetworkServer.Destroy(impact);
|
|
}, Data["impact_despawn_time"].FloatValue);
|
|
|
|
// 碰撞点的法线方向
|
|
Vector3 normal = handlingHit.normal;
|
|
// 在这里处理特效的生成和方向
|
|
// 计算特效的旋转方向,使用法线信息
|
|
Quaternion rotation = Quaternion.LookRotation(normal);
|
|
// 将特效的旋转方向设置为法线方向
|
|
impact.transform.rotation = rotation;
|
|
}
|
|
}
|
|
|
|
[Server]
|
|
public void DespawnSelf()
|
|
{
|
|
isValid = false;
|
|
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
|
|
{
|
|
NetworkServer.Destroy(transform.gameObject);
|
|
}, Data["despawn_delay"].FloatValue);
|
|
}
|
|
|
|
[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))
|
|
{
|
|
// Debug.Log("击中 - " + handlingHit.transform.name);
|
|
if (!Data["hit_trigger"].BooleanValue && handlingHit.collider.isTrigger)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
[Server]
|
|
// todo
|
|
public virtual void ApplyDamage()
|
|
{
|
|
IDamagable component = handlingHit.transform.GetComponent<IDamagable>();
|
|
if (component != null)
|
|
{
|
|
OnApplyDamage(component);
|
|
}
|
|
}
|
|
[Server]
|
|
public virtual void HitTarget()
|
|
{
|
|
|
|
}
|
|
|
|
[Server]
|
|
public virtual void OnApplyDamage(IDamagable damagable) { }
|
|
|
|
[Server]
|
|
public virtual void OnHitTarget(RaycastHit hit) { }
|
|
|
|
}
|