BITFALL/Assets/Artists/Scripts/BulletManager/BulletService.cs

192 lines
6.8 KiB
C#
Raw Normal View History

2023-06-08 14:09:50 +08:00
using System;
using System.Collections.Generic;
2023-08-12 01:43:24 +08:00
using System.Linq;
using System.Text;
2023-06-08 14:09:50 +08:00
using UnityEngine;
using BITKit;
2023-08-12 01:43:24 +08:00
using BITKit.Core.Entites;
2023-06-08 14:09:50 +08:00
using BITKit.Entities;
using Cysharp.Threading.Tasks;
2023-08-12 01:43:24 +08:00
using UnityEditor;
2023-06-08 14:09:50 +08:00
using UnityEngine.Animations;
2023-08-12 01:43:24 +08:00
using UnityEngine.UIElements;
2023-06-08 14:09:50 +08:00
namespace BITFALL
{
2023-08-12 01:43:24 +08:00
[Serializable]
2023-06-08 14:09:50 +08:00
public record InstanceBullet : SpawnBullet
{
public Vector3 currentPos;
public float currentSpeed = 64;
public BITBullet model;
}
public class BulletService : MonoBehaviour
{
public static Action<SpawnBullet> Spawn;
2023-08-12 01:43:24 +08:00
2023-06-08 14:09:50 +08:00
[Header(Constant.Header.Settings)]
public LayerMask layerMask;
2023-06-17 16:30:53 +08:00
[Header(Constant.Header.Providers)]
[SerializeField, SerializeReference, SubclassSelector]
2023-08-12 01:43:24 +08:00
private IEntitiesService entitiesService;
[SerializeField, SerializeReference, SubclassSelector]
2023-06-17 16:30:53 +08:00
private INetProvider netProvider;
2023-08-12 01:43:24 +08:00
[SerializeField, SerializeReference, SubclassSelector]
private IDamageService damageService;
2023-06-08 14:09:50 +08:00
[Header(Constant.Header.Settings)]
public UnityPool<BITBullet> pool = new();
2023-08-12 01:43:24 +08:00
2023-06-08 14:09:50 +08:00
[Header(Constant.Header.InternalVariables)]
public List<InstanceBullet> instances = new();
2023-08-12 01:43:24 +08:00
public string Log => _stringBuilder.ToString();
private readonly StringBuilder _stringBuilder = new();
private readonly RaycastHit[] _raycastHits = new RaycastHit[16];
private void Start()
2023-06-08 14:09:50 +08:00
{
Spawn += SpawnBullet;
}
2023-08-12 01:43:24 +08:00
private void OnDestroy()
2023-06-08 14:09:50 +08:00
{
Spawn -= SpawnBullet;
}
2023-08-12 01:43:24 +08:00
private void FixedUpdate()
2023-06-08 14:09:50 +08:00
{
2023-08-12 01:43:24 +08:00
instances ??= new List<InstanceBullet>();
2023-06-08 14:09:50 +08:00
foreach (var bullet in instances.ToArray())
{
2023-08-12 01:43:24 +08:00
var size = Physics.RaycastNonAlloc(bullet.currentPos, bullet.forward, _raycastHits, bullet.currentSpeed * Time.fixedDeltaTime, layerMask);
var validHit = false;
foreach (var raycastHit in _raycastHits.Take(size).OrderBy(x => Vector3.Distance(bullet.pos, x.point)))
2023-06-08 14:09:50 +08:00
{
2023-08-12 01:43:24 +08:00
if (!IsValidHit(raycastHit, bullet))
continue;
validHit = true;
break;
2023-06-08 14:09:50 +08:00
}
2023-08-12 01:43:24 +08:00
if (validHit ||bullet.currentSpeed <= 0)
2023-06-08 14:09:50 +08:00
{
instances.TryRemove(bullet);
2023-08-12 01:43:24 +08:00
pool.Return(bullet.model);
2023-06-08 14:09:50 +08:00
}
else
{
bullet.currentSpeed -= bullet.startSpeed * Time.fixedDeltaTime;
bullet.currentPos += (Vector3)bullet.forward * (bullet.currentSpeed * Time.fixedDeltaTime);
bullet.model.transform.position = bullet.currentPos;
}
}
}
2023-08-12 01:43:24 +08:00
private async void RpcSpawnBullet(SpawnBullet x)
2023-06-08 14:09:50 +08:00
{
await UniTask.SwitchToMainThread();
var instance = pool.Get();
InstanceBullet bullet = new()
{
initiator = x.initiator,
currentPos = x.pos,
pos = x.pos,
rot = x.rot,
2023-08-12 01:43:24 +08:00
forward = x.forward,
initialDamage = x.initialDamage,
model = instance
2023-06-08 14:09:50 +08:00
};
2023-08-12 01:43:24 +08:00
var instanceTransform = instance.transform;
instanceTransform.SetPositionAndRotation(x.pos, x.rot);
instanceTransform.forward = x.forward;
2023-06-08 14:09:50 +08:00
instances.Add(bullet);
}
2023-08-12 01:43:24 +08:00
private void SpawnBullet(SpawnBullet x)
{
RpcSpawnBullet(x);
}
private bool IsValidHit(RaycastHit raycastHit,InstanceBullet bullet)
{
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);
if (raycastHit.collider.TryGetComponent<IDamagable>(out var damagable))
{
if(damagable.Entity.Id == bullet.initiator) return false;
if (layerMask.Includes(raycastHit.collider.gameObject.layer) is false) return false;
var msg = new DamageMessage()
{
target = damagable.Entity,
hit = damagable,
damage = bullet.initialDamage,
};
damageService.Execute(msg);
if (damagable.Rigidbody is not null)
damagable.Rigidbody.AddForceAtPositionAsync(force, raycastHit.point, ForceMode.Impulse);
}
else
{
if (raycastHit.rigidbody is not null)
raycastHit.rigidbody.AddForceAtPositionAsync(force, raycastHit.point, ForceMode.Impulse);
}
_stringBuilder.AppendLine(
$"{bullet.initiator}击中了:{raycastHit.collider.name},Layer:{LayerMask.LayerToName(raycastHit.collider.gameObject.layer)}"
);
List<string> tags = new()
{
"BulletHit",
};
if (raycastHit.transform.TryGetComponent<ITag>(out var _tag))
{
tags.AddRange(_tag.GetTags());
}
Location location = new()
{
position = raycastHit.point,
forward = raycastHit.normal,
};
var vfx = DI.Get<VFXService>().Spawn(location, tags.ToArray());
var constraint = vfx.gameObject.AddComponent<ParentConstraint>();
var sourceTransform = raycastHit.transform;
constraint.AddSource(new ConstraintSource()
{
sourceTransform = sourceTransform,
weight = 1,
});
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;
return true;
}
}
#if UNITY_EDITOR
[CustomEditor(typeof(BulletService))]
public class BulletServiceInspector:BITInspector<BulletService>
{
private Label logLabel;
public override VisualElement CreateInspectorGUI()
{
FillDefaultInspector();
logLabel = root.Create<Label>();
return root;
}
protected override void OnUpdate()
2023-06-08 14:09:50 +08:00
{
2023-08-12 01:43:24 +08:00
if (logLabel is null) return;
logLabel.text = agent.Log;
2023-06-08 14:09:50 +08:00
}
}
2023-08-12 01:43:24 +08:00
#endif
2023-06-08 14:09:50 +08:00
}