139 lines
3.8 KiB
C#
139 lines
3.8 KiB
C#
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<VisualElement>(()=>indicatorAsset.CloneTree()[0]);
|
|
|
|
_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;
|
|
// }
|
|
// }
|
|
}
|
|
|
|
}
|