1
This commit is contained in:
@@ -7,6 +7,7 @@ using UnityEngine;
|
||||
using BITKit;
|
||||
using BITKit.Entities;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Unity.Mathematics;
|
||||
using UnityEditor;
|
||||
using UnityEngine.Animations;
|
||||
using UnityEngine.UIElements;
|
||||
@@ -16,9 +17,10 @@ namespace BITFALL
|
||||
[Serializable]
|
||||
public record InstanceBullet : SpawnBullet
|
||||
{
|
||||
public Vector3 GraphicsPosition;
|
||||
public Vector3 Velocity;
|
||||
public Vector3 currentPos;
|
||||
public float currentSpeed = 64;
|
||||
public Vector3 CurrentPos;
|
||||
public float CurrentSpeed = 64;
|
||||
public float ElapsedTime;
|
||||
}
|
||||
[Serializable]
|
||||
@@ -33,6 +35,12 @@ namespace BITFALL
|
||||
[Header(Constant.Header.Settings)]
|
||||
[SerializeField] private LayerMask layerMask;
|
||||
[SerializeField] private Material material;
|
||||
[SerializeField] private Optional<float> bulletLerpSpeed;
|
||||
[SerializeField] private Optional<AnimationCurve> bulletScaleCurve;
|
||||
|
||||
[Header(Constant.Header.Prefabs)]
|
||||
[SerializeField] private Mesh rectangleMesh;
|
||||
[SerializeField] private Mesh quadMesh;
|
||||
|
||||
[Header(Constant.Header.Providers)]
|
||||
[SerializeField, SerializeReference, SubclassSelector]
|
||||
@@ -49,11 +57,14 @@ namespace BITFALL
|
||||
private const float dragCoefficient = 0.045f; // 子弹的阻力系数
|
||||
private const float bulletMass = 0.015f; // 子弹的质量,单位:千克
|
||||
|
||||
private Mesh _mesh;
|
||||
private readonly Queue<(Vector3 Position,Vector3 Forward,Quaternion StartRotation,float ElaspedTime,Vector3 StartPosition)> DrawQueue=new();
|
||||
|
||||
private readonly Queue<InstanceBullet> _newBulletQueue = new();
|
||||
|
||||
private readonly Queue<InstanceBullet> _removeBulletQueue = new();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_mesh = GetComponent<MeshFilter>().mesh;
|
||||
Spawn += SpawnBullet;
|
||||
}
|
||||
private void OnDestroy()
|
||||
@@ -64,40 +75,84 @@ namespace BITFALL
|
||||
{
|
||||
var camera = Camera.main;
|
||||
if (!camera) return;
|
||||
var rot = camera.transform.rotation * Quaternion.Euler(0, 180, 0);
|
||||
var cameraTransform = camera.transform;
|
||||
//var rot = camera.transform.rotation * Quaternion.Euler(0, 180, 0);
|
||||
foreach (var bullet in instances.ToArray())
|
||||
{
|
||||
if (bullet.ElapsedTime >= 0.04f)
|
||||
if (bullet.ElapsedTime < 0.04f) continue;
|
||||
|
||||
bullet.GraphicsPosition =
|
||||
Vector3.MoveTowards(bullet.GraphicsPosition, bullet.CurrentPos, bullet.StartSpeed*Time.deltaTime);
|
||||
|
||||
DrawQueue.Enqueue((bullet.GraphicsPosition,bullet.Forward,bullet.Rotation,bullet.ElapsedTime,bullet.Position));
|
||||
}
|
||||
|
||||
while (DrawQueue.TryDequeue(out var queue))
|
||||
{
|
||||
var direction = camera.transform.position - queue.Position;
|
||||
|
||||
var rot = Quaternion.LookRotation(queue.Position + queue.Forward, direction);
|
||||
// 获取目标方向
|
||||
|
||||
var mesh = rectangleMesh;
|
||||
|
||||
//if (MathV.InFovRange(cameraTransform.position, cameraTransform.forward, bullet.CurrentPos,8))
|
||||
if (Vector3.Angle(cameraTransform.forward, queue.Forward) < 8)
|
||||
{
|
||||
// Graphics.DrawMesh(_mesh, bullet.currentPos, bullet.rot, material,
|
||||
// LayerMask.NameToLayer("TransparentFX"));
|
||||
var martix = Matrix4x4.TRS(
|
||||
bullet.currentPos,
|
||||
rot,
|
||||
Vector3.one + Vector3.one * Mathf.Clamp(bullet.ElapsedTime, 0, 16));
|
||||
Graphics.DrawMesh(_mesh, martix, material,
|
||||
LayerMask.NameToLayer("TransparentFX"));
|
||||
if (Vector3.Distance(queue.StartPosition, queue.Position) < 3.2f)
|
||||
continue;
|
||||
|
||||
mesh = quadMesh;
|
||||
rot = cameraTransform.rotation * Quaternion.Euler(0, 180, 0);
|
||||
}
|
||||
const int count = 1;
|
||||
var matrix = Matrix4x4.TRS(
|
||||
queue.Position,
|
||||
rot,
|
||||
Vector3.one *
|
||||
Mathf.Lerp(
|
||||
0,1,Vector3.Distance(queue.StartPosition,queue.Position)
|
||||
)
|
||||
+ Vector3.one *
|
||||
(bulletScaleCurve.Allow ? bulletScaleCurve.Value.Evaluate(queue.ElaspedTime) : 0)
|
||||
);
|
||||
Graphics.DrawMesh(mesh, matrix, material,
|
||||
LayerMask.NameToLayer("TransparentFX"));
|
||||
}
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
foreach (var bullet in instances.ToArray())
|
||||
foreach (var bullet in instances)
|
||||
{
|
||||
var size = Physics.RaycastNonAlloc(bullet.currentPos, bullet.Velocity, _raycastHits, Vector3.Distance(default,bullet.Velocity) * Time.fixedDeltaTime, layerMask);
|
||||
if (destroyCancellationToken.IsCancellationRequested) return;
|
||||
var size = Physics.RaycastNonAlloc(bullet.CurrentPos, bullet.Velocity, _raycastHits, Vector3.Distance(default,bullet.Velocity) * Time.fixedDeltaTime, layerMask);
|
||||
var validHit = false;
|
||||
foreach (var raycastHit in _raycastHits.Take(size).OrderBy(x => Vector3.Distance(bullet.pos, x.point)))
|
||||
RaycastHit hit=default;
|
||||
foreach (var raycastHit in _raycastHits.Take(size).OrderBy(x => Vector3.Distance(bullet.Position, x.point)))
|
||||
{
|
||||
if (!IsValidHit(raycastHit, bullet))
|
||||
if (!IsValidHit(raycastHit, bullet,out hit))
|
||||
continue;
|
||||
validHit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (validHit ||bullet.currentSpeed <= 0 || bullet.Velocity.sqrMagnitude <= 0.01f || bullet.ElapsedTime >= 8)
|
||||
if (validHit || bullet.CurrentSpeed <= 0 || bullet.Velocity.sqrMagnitude <= 0.01f ||
|
||||
bullet.ElapsedTime >= 8)
|
||||
{
|
||||
instances.TryRemove(bullet);
|
||||
_removeBulletQueue.Enqueue(bullet);
|
||||
|
||||
if (validHit)
|
||||
{
|
||||
DrawQueue.Enqueue((hit.point - bullet.Velocity.normalized * 0.5f, bullet.Forward, bullet.Rotation,
|
||||
bullet.ElapsedTime,bullet.Position));
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawQueue.Enqueue((bullet.CurrentPos + bullet.Velocity * 0.5f, bullet.Forward, bullet.Rotation,
|
||||
bullet.ElapsedTime,bullet.Position));
|
||||
}
|
||||
|
||||
//pool.Return(bullet.model);
|
||||
}
|
||||
else
|
||||
@@ -136,53 +191,70 @@ namespace BITFALL
|
||||
|
||||
var newVelocity =bullet.Velocity * Time.fixedDeltaTime;
|
||||
|
||||
bullet.currentPos+=newVelocity;
|
||||
bullet.CurrentPos+=newVelocity;
|
||||
|
||||
float CalculateElevationAngle(float distance)
|
||||
{
|
||||
float g = Mathf.Abs(Physics.gravity.y);
|
||||
float angle = 0.5f * Mathf.Asin(distance * g / (bullet.startSpeed * bullet.startSpeed));
|
||||
float angle = 0.5f * Mathf.Asin(distance * g / (bullet.StartSpeed * bullet.StartSpeed));
|
||||
return angle * Mathf.Rad2Deg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (_removeBulletQueue.TryDequeue(out var removeBullet))
|
||||
{
|
||||
instances.Remove(removeBullet);
|
||||
}
|
||||
while (_newBulletQueue.TryDequeue(out var newBullet))
|
||||
{
|
||||
instances.Add(newBullet);
|
||||
}
|
||||
}
|
||||
private async void RpcSpawnBullet(SpawnBullet x)
|
||||
{
|
||||
await UniTask.SwitchToMainThread();
|
||||
InstanceBullet bullet = new()
|
||||
{
|
||||
initiator = x.initiator,
|
||||
currentPos = x.pos,
|
||||
startSpeed = x.startSpeed,
|
||||
pos = x.pos,
|
||||
rot = x.rot,
|
||||
forward = x.forward,
|
||||
initialDamage = x.initialDamage,
|
||||
Initiator = x.Initiator,
|
||||
CurrentPos = x.Position,
|
||||
StartSpeed = x.StartSpeed,
|
||||
Position = x.Position,
|
||||
GraphicsPosition=x.Position,
|
||||
Rotation = x.Rotation,
|
||||
Forward = x.Forward,
|
||||
InitialDamage = x.InitialDamage,
|
||||
InitialForce = x.InitialForce,
|
||||
Velocity =x.forward * x.startSpeed,
|
||||
Velocity =x.Forward * x.StartSpeed,
|
||||
Token = x.Token
|
||||
};
|
||||
instances.Add(bullet);
|
||||
// InstanceBullet bullet = x with
|
||||
// {
|
||||
//
|
||||
// };
|
||||
_newBulletQueue.Enqueue(bullet);
|
||||
//instances.Add(bullet);
|
||||
}
|
||||
private void SpawnBullet(SpawnBullet x)
|
||||
{
|
||||
RpcSpawnBullet(x);
|
||||
}
|
||||
|
||||
private bool IsValidHit(RaycastHit raycastHit, InstanceBullet bullet)
|
||||
private bool IsValidHit(RaycastHit raycastHit, InstanceBullet bullet,out RaycastHit hit)
|
||||
{
|
||||
hit = default;
|
||||
if (layerMask.Includes(raycastHit.collider.gameObject.layer) is false) return false;
|
||||
raycastHit.collider.TryGetComponentAny<IPhysicsInfo>(out var physicsInfo);
|
||||
var force = (raycastHit.point - (Vector3)bullet.pos).normalized * (physicsInfo?.AddForceMultiple ?? 64);
|
||||
var force = (raycastHit.point - (Vector3)bullet.Position).normalized * (physicsInfo?.AddForceMultiple ?? 64);
|
||||
if (raycastHit.collider.TryGetComponent<IDamagable>(out var damagable))
|
||||
{
|
||||
if (damagable.UnityEntity?.Id == bullet.initiator) return false;
|
||||
if (damagable.UnityEntity?.Id == bullet.Initiator) return false;
|
||||
if (layerMask.Includes(raycastHit.collider.gameObject.layer) is false) return false;
|
||||
var msg = new DamageMessage()
|
||||
{
|
||||
Target = damagable.UnityEntity,
|
||||
Hit = damagable,
|
||||
Damage = bullet.initialDamage,
|
||||
Damage = bullet.InitialDamage,
|
||||
};
|
||||
if (damagable is IEntityComponent)
|
||||
{
|
||||
@@ -202,7 +274,7 @@ namespace BITFALL
|
||||
(not null, null) => raycastHit.rigidbody,
|
||||
(not null, not null) => damagable?.Rigidbody,
|
||||
};
|
||||
if (_rigidbody is not null && _rigidbody.gameObject.layer is not 0)
|
||||
if (_rigidbody && _rigidbody.gameObject.layer is not 0)
|
||||
{
|
||||
_rigidbody.AddForceAtPositionAsync(force, raycastHit.point, ForceMode.Impulse).Forget();
|
||||
}
|
||||
@@ -220,29 +292,19 @@ namespace BITFALL
|
||||
Location location = new()
|
||||
{
|
||||
position = raycastHit.point,
|
||||
forward = raycastHit.normal,
|
||||
forward = tags.Contains("IgnoreRotation") ? bullet.Forward : Quaternion.LookRotation(raycastHit.normal) * Vector3.forward,
|
||||
};
|
||||
var vfx = DI.Get<VFXService>().Spawn(location, tags.ToArray());
|
||||
var constraint = vfx.gameObject.GetOrAddComponent<ParentConstraint>();
|
||||
var sourceTransform = raycastHit.transform;
|
||||
while (constraint.sourceCount>0)
|
||||
if (_rigidbody is not null && tags.Contains("Fixed") is false)
|
||||
{
|
||||
constraint.RemoveSource(0);
|
||||
vfx.SetParentConstraint(_rigidbody.transform);
|
||||
}
|
||||
constraint.AddSource(new ConstraintSource()
|
||||
else
|
||||
{
|
||||
sourceTransform = sourceTransform,
|
||||
weight = 1,
|
||||
});
|
||||
vfx.gameObject.RemoveComponent<ParentConstraint>();
|
||||
}
|
||||
|
||||
var positionOffset = sourceTransform.InverseTransformPoint(raycastHit.point);
|
||||
var rotationOffset = Quaternion.Inverse(sourceTransform.rotation) * transform.rotation;
|
||||
|
||||
constraint.SetTranslationOffset(0, positionOffset);
|
||||
//constraint.SetRotationOffset(0, rotationOffset.eulerAngles);
|
||||
|
||||
constraint.weight = 1;
|
||||
constraint.constraintActive = true;
|
||||
hit = raycastHit;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user