Files
Net.Like.Xue.Tokyo/Packages-Local/Com.Project.B.Unity/WorldNodeService/ScriptableHelicopterEvacuate.cs

155 lines
5.5 KiB
C#
Raw Normal View History

2025-06-24 23:49:13 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using BITKit;
using BITKit.Entities;
using BITKit.Tween;
using Cysharp.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Net.Project.B.Interaction;
using Project.B.Entities;
using Project.B.Map;
using Unity.Mathematics;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Net.Project.B.WorldNode
{
public class ScriptableHelicopterEvacuate : ScriptableEvacuate
{
[SerializeField] private Transform mark;
[SerializeField] private Transform helicopter;
public override async void Initialize(IEntity entity)
{
entity.ServiceProvider.QueryComponents(out Transform transform);
if (entity.ServiceProvider.QueryComponents(out IWorldInteractable interactable) is false)
{
BITApp.ServiceProvider.QueryComponents(out IEntitiesService entitiesService);
entitiesService.UnRegister(entity);
var newEntity = new Entity()
{
Id = entity.Id,
CancellationToken = entity.CancellationToken,
};
newEntity.ServiceCollection.Add(entity.ServiceCollection);
interactable = new WorldInteractable();
newEntity.ServiceCollection.AddSingleton(interactable);
if (transform.TryGetComponent<Collider>(out var collider) is false)
{
var boxCollider = transform.gameObject.AddComponent<BoxCollider>();
boxCollider.center = new Vector3(0, 0.5f, 0);
collider = boxCollider;
collider.isTrigger = true;
newEntity.ServiceCollection.AddSingleton(collider);
}
await UniTask.NextFrame();
entitiesService.Register(newEntity);
return;
}
var position = transform.position;
foreach (var raycastHit in Physics
.RaycastAll(position+Vector3.up, Vector3.down, 8,~0,QueryTriggerInteraction.Ignore)
.OrderBy(x=>Vector3.Distance(position,x.point))
)
{
if(raycastHit.transform == transform)continue;
position = raycastHit.point;
break;
}
transform.position = position;
Instantiate(mark, position, transform.rotation, transform);
}
public override async UniTask Invoke(IEntity entity,CancellationToken cancellationToken)
{
BITApp.ServiceProvider.QueryComponents(out IEntitiesService entitiesService,out IPlayerFactory playerFactory,out IGameMapService gameMapService);
entity.ServiceProvider.QueryComponents(out Transform transform,out UnityEvacuateNode evacuateNode);
if (evacuateNode.EvacuateType is not HelicopterEvacuate helicopterEvacuate)
{
Debug.LogError("EvacuateType is not HelicopterEvacuate");
return;
}
var position = transform.position;
var op =Object.InstantiateAsync(helicopter);
await op;
var model = op.Result[0];
var rigidbody = model.GetComponent<Rigidbody>();
var collider = model.GetComponent<Collider>();
var upPosition = position + Vector3.up * 16;
var startPosition = upPosition - Vector3.forward * 64 + Vector3.up * 8;
var farPosition = upPosition + Vector3.forward * 32 + Vector3.up * 8;
model.position = upPosition;
try
{
await BITween.MoveToForward(rigidbody.MovePosition, startPosition, upPosition, 8,Vector3.MoveTowards,cancellationToken);
await BITween.MoveToForward(rigidbody.MovePosition, upPosition, position, 3,Vector3.MoveTowards,cancellationToken);
await UniTask.Delay(TimeSpan.FromSeconds(helicopterEvacuate.time),cancellationToken:cancellationToken);
await BITween.MoveToForward(x=>rigidbody.velocity=x-rigidbody.position, position, upPosition, 3,Vector3.MoveTowards,cancellationToken);
await BITween.MoveToForward(x=>rigidbody.velocity=x-rigidbody.position, upPosition, farPosition, 8,Vector3.MoveTowards,cancellationToken);
Destroy(model.gameObject);
var isPlayer = false;
// ReSharper disable once Unity.PreferNonAllocApi
foreach (var x in Physics.OverlapBox(collider.bounds.center, collider.bounds.extents))
{
if (playerFactory.Entities.ContainsKey(x.gameObject.GetInstanceID()))
{
isPlayer = true;
}
Destroy(x.gameObject);
}
await UniTask.Delay(TimeSpan.FromSeconds(3),cancellationToken:cancellationToken);
if (isPlayer)
{
await gameMapService.StopMapAsync();
}
}
catch (OperationCanceledException)
{
return;
}
Destroy(this);
}
}
}