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(); private Collider[] _colliders=Array.Empty(); private Collider[] _selfColliders = Array.Empty(); private Rigidbody[] _rigidbodies = Array.Empty(); private Collider _selfCollider; private Rigidbody _selfRigidbody; private void OnEnable() { if (_isInitialized) { Play(); } } private void Start() { _selfRigidbody = GetComponent(); _selfCollider = GetComponent(); _animancerComponent=GetComponent(); _selfColliders = GetComponentsInChildren().RemoveIn(_selfCollider).ToArray(); _rigidbodies = GetComponentsInChildren().RemoveIn(_selfRigidbody).ToArray(); _hips = _animancerComponent.Animator.GetBoneTransform(HumanBodyBones.Hips); foreach (var collisionController in _collisionControllers=_animancerComponent.GetComponentsInChildren()) { collisionController.OnUnityTriggerEnter += OnUnityTriggerEnter; } _colliders = _collisionControllers.Select(x => x.GetComponent()).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; } } } }