using System; using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; using BITKit; using BITKit.Entities; using BITKit.Entities.Player; using BITKit.UX; using UnityEngine; using UnityEngine.UIElements; namespace BITFALL.UX { public class UXDamageIndicator : MonoBehaviour { [SerializeReference, SubclassSelector] private IPlayerService playerService; [SerializeField] private UIDocument document; [SerializeField] private VisualTreeAsset indicatorAsset; [UXBindPath("indicator-container")] private VisualElement indicatorContainer; [Inject] private IHealth _health; [Inject] private IEntityMovement _movement; private List<(VisualElement visualElement, Vector3 position, float exitTime)> _indicators = new(); private void Start() { playerService.OnPlayerInitialized += OnPlayerInitialized; playerService.OnPlayerDisposed+=OnPlayerDisposed; destroyCancellationToken.Register(() => { playerService.OnPlayerInitialized -= OnPlayerInitialized; playerService.OnPlayerDisposed-=OnPlayerDisposed; }); BITKit.UX.UXUtils.Inject(this); indicatorContainer.Clear(); } private void OnPlayerDisposed(Entity obj) { foreach (var x in _indicators) { x.visualElement.RemoveFromHierarchy(); } _indicators.Clear(); } private void OnPlayerInitialized(Entity obj) { obj.Inject(this); _health.OnDamageRelease += OnDamageRelease; } private void Update() { foreach (var x in _indicators) { // // var direction =Vector3.ProjectOnPlane(x.position - _movement.Position,Vector3.up).normalized; // // direction = Quaternion.LookRotation(direction) * _movement.Rotation * Vector3.forward; // // var rotation = Quaternion.LookRotation(direction); // var angle =(rotation.eulerAngles.y+180)%360; // // x.visualElement.transform.rotation = Quaternion.Euler(0, 0, -angle); //Calculate direction Vector3 rhs = x.position - _movement.Position; Vector3 offset = x.visualElement.transform.rotation.eulerAngles; var forward = _movement.Forward; //Convert angle into screen space rhs.y = 0f; rhs.Normalize(); //Get the angle between two positions. float angle = Vector3.Angle(rhs, forward); //Calculate the perpendicular of both vectors //More information about this calculation: https://unity3d.com/es/learn/tutorials/modules/beginner/scripting/vector-maths-dot-cross-products?playlist=17117 Vector3 Perpendicular = Vector3.Cross(forward, rhs); //Calculate magnitude between two vectors float dot = -Vector3.Dot(Perpendicular, Vector3.up); //get the horizontal angle in direction of target / sender. angle = AngleCircumference(dot, angle); //Apply the horizontal rotation to the indicator. offset.z = -angle; x.visualElement.transform.rotation = Quaternion.Euler(offset); if (Time.time > x.exitTime) x.visualElement.RemoveFromHierarchy(); float AngleCircumference(float dot, float angle) { float ac = angle; float circumference = 360f; ac = angle - 10; if (dot < 0) { ac = circumference - angle; } return ac; } } _indicators.RemoveAll(x => x.exitTime < Time.time); } private void OnDamageRelease(DamageMessage arg1) { if (arg1.Position.IsDefault()) return; var indicator =indicatorContainer.Create(()=>indicatorAsset.CloneTree()[0]); if (arg1.Damage is 0) { indicator[0].style.unityBackgroundImageTintColor = Color.black; } _indicators.Add((indicator, (Vector3)arg1.Position, Time.time + 1)); } // private async void KillIndicator(VisualElement indicator) // { // try // { // await Task.Delay(500, destroyCancellationToken); // indicator.RemoveFromHierarchy(); // } // catch (Exception e) // { // Console.WriteLine(e); // throw; // } // } } }