149 lines
4.8 KiB
C#
149 lines
4.8 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Animancer;
|
|
using BITKit;
|
|
using BITKit.Physics;
|
|
using UnityEngine;
|
|
using Cysharp.Threading.Tasks;
|
|
|
|
namespace Net.Project.B.World
|
|
{
|
|
public class WorldRagdollController : MonoBehaviour
|
|
{
|
|
[SerializeField] private AnimationClip[] startClips;
|
|
private AnimancerComponent _animancerComponent;
|
|
private Transform _hips;
|
|
private bool _isInitialized;
|
|
private bool _isPlaying;
|
|
private bool _isBreak;
|
|
private UnityCollisionController[] _collisionControllers=Array.Empty<UnityCollisionController>();
|
|
private Collider[] _colliders=Array.Empty<Collider>();
|
|
private Collider[] _selfColliders = Array.Empty<Collider>();
|
|
private Rigidbody[] _rigidbodies = Array.Empty<Rigidbody>();
|
|
private Collider _selfCollider;
|
|
private Rigidbody _selfRigidbody;
|
|
|
|
private void OnEnable()
|
|
{
|
|
if (_isInitialized)
|
|
{
|
|
Play();
|
|
}
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
_selfRigidbody = GetComponent<Rigidbody>();
|
|
_selfCollider = GetComponent<Collider>();
|
|
_animancerComponent=GetComponent<AnimancerComponent>();
|
|
_selfColliders = GetComponentsInChildren<Collider>().RemoveIn(_selfCollider).ToArray();
|
|
_rigidbodies = GetComponentsInChildren<Rigidbody>().RemoveIn(_selfRigidbody).ToArray();
|
|
_hips = _animancerComponent.Animator.GetBoneTransform(HumanBodyBones.Hips);
|
|
foreach (var collisionController in _collisionControllers=_animancerComponent.GetComponentsInChildren<UnityCollisionController>())
|
|
{
|
|
collisionController.OnUnityTriggerEnter += OnUnityTriggerEnter;
|
|
}
|
|
_colliders = _collisionControllers.Select(x => x.GetComponent<Collider>()).ToArray();
|
|
if (_isInitialized) return;
|
|
_isInitialized = true;
|
|
Play();
|
|
}
|
|
|
|
private void OnUnityTriggerEnter(Collider obj)
|
|
{
|
|
if (_isPlaying is false) return;
|
|
if (_selfColliders.Contains(obj)) return;
|
|
if (obj is not MeshCollider{convex:false} && obj.ClosestPoint(transform.position).y > transform.position.y)
|
|
{
|
|
Stop();
|
|
}
|
|
|
|
}
|
|
|
|
private void Stop()
|
|
{
|
|
_isBreak = true;
|
|
_selfRigidbody.isKinematic = true;
|
|
_animancerComponent.enabled = _selfCollider.enabled = _animancerComponent.Animator.enabled = false;
|
|
}
|
|
private async void Play()
|
|
{
|
|
if(!_animancerComponent)return;
|
|
|
|
_isBreak = false;
|
|
foreach (var x in _colliders)
|
|
{
|
|
x.isTrigger = true;
|
|
}
|
|
_animancerComponent.enabled = _selfCollider.enabled = _animancerComponent.Animator.enabled = true;
|
|
_selfRigidbody.isKinematic = false;
|
|
_isPlaying = true;
|
|
foreach (var x in _rigidbodies)
|
|
{
|
|
x.isKinematic = true;
|
|
}
|
|
var play = _animancerComponent.Play(startClips.Random());
|
|
play.Time = 0;
|
|
try
|
|
{
|
|
await play.WithCancellation(destroyCancellationToken);
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_isPlaying = false;
|
|
_animancerComponent.enabled = _selfCollider.enabled =_animancerComponent.Animator.enabled= false;
|
|
_selfRigidbody.isKinematic = true;
|
|
|
|
|
|
if (_isBreak)
|
|
{
|
|
foreach (var x in _colliders)
|
|
{
|
|
x.isTrigger = false;
|
|
}
|
|
foreach (var x in _rigidbodies)
|
|
{
|
|
x.isKinematic = false;
|
|
x.velocity = default;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (var x in _colliders)
|
|
{
|
|
x.isTrigger = false;
|
|
}
|
|
foreach (var x in _rigidbodies)
|
|
{
|
|
x.isKinematic = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
private void OnCollisionEnter(Collision other)
|
|
{
|
|
if (other.gameObject.layer == LayerMask.NameToLayer("Entities"))
|
|
{
|
|
Stop();
|
|
}
|
|
}
|
|
|
|
private void OnAnimatorMove()
|
|
{
|
|
var isGrounded = Physics.Raycast(transform.position+Vector3.up*0.1f,Vector3.down,0.11f);
|
|
_animancerComponent.Animator.applyRootMotion = isGrounded;
|
|
if (isGrounded)
|
|
{
|
|
_selfRigidbody.velocity = _animancerComponent.Animator.velocity;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|