2D-Platformer/Assets/Scripts/Systems/Actor/ActorAimingAnimationSystem.cs
2022-02-12 12:53:50 +02:00

125 lines
No EOL
4.7 KiB
C#

using System;
using Unity.Entities;
using UnityEngine;
using Zenject;
namespace DefaultNamespace
{
[UpdateInGroup(typeof(PresentationSystemGroup)), UpdateBefore(typeof(ActorIkSystem))]
public class ActorAimingAnimationSystem : InjectableComponentSystem
{
[Serializable]
public class Settings
{
public float MinMouseDistanceBarrel;
public float TurnEase;
public float WeaponEase;
}
[Inject] private readonly Settings settings;
protected override void OnSystemUpdate()
{
Entities.WithAllReadOnly<RigidBody2DData, ActorBodyParts>()
.ForEach(
(
Entity entitiy,
ActorAnimationPropertiesData animationProperties,
ref Rotation2D rotation,
ref ActorData actor,
ref ActorAnimationData animation,
ref AnimatorStateData animationState) =>
{
var rigidBody = EntityManager.GetComponentData<RigidBody2DData>(entitiy);
var parts = EntityManager.GetComponentObject<ActorBodyParts>(entitiy);
if (animationState.State.IsTag("Interactive") || animationState.State.IsTag("CanLook"))
{
var playerPosition = rigidBody.Position +
(EntityManager.HasComponent<AimCenterData>(entitiy)
? EntityManager.GetComponentData<AimCenterData>(entitiy).Offset
: Vector2.zero);
var hipLookDir = (actor.Aim - playerPosition).normalized;
var hipAngle = Vector2.SignedAngle(Vector2.up, hipLookDir);
rotation.Axis = Mathf.Sign(hipAngle);
if (!EntityManager.HasComponent<ActorWeaponReferenceData>(entitiy))
{
hipAngle = -90;
}
if (parts.Hip != null)
{
var rot = Mathf.LerpAngle(
animation.LastRotation,
Mathf.Clamp(Mathf.Abs(hipAngle), animationProperties.HipAngleRange.x, animationProperties.HipAngleRange.y),
settings.TurnEase * Time.DeltaTime);
animation.LastRotation = rot;
parts.Hip.localRotation = Quaternion.Slerp(
parts.Hip.localRotation,
Quaternion.Euler(0, 0, rot),
animation.LookWeight);
if (parts.Head != null)
{
Vector2 lookDir = parts.Head.parent.InverseTransformPoint(actor.Look).normalized;
var headAngle = Vector2.SignedAngle(animationProperties.HeadForward, lookDir);
var headRot = Mathf.LerpAngle(
animation.LastHeadRotation,
Mathf.Clamp(headAngle, animationProperties.HeadAngleRange.x, animationProperties.HeadAngleRange.y),
settings.TurnEase * Time.DeltaTime);
parts.Head.localRotation = Quaternion.Slerp(
parts.Head.localRotation,
Quaternion.Euler(0, 0, headRot + parts.DefaultHeadAngle),
animation.HeadLookWeight * animation.LookWeight);
animation.LastHeadRotation = headRot;
}
}
}
});
Entities.WithAllReadOnly<Animator, ActorBodyParts>()
.ForEach(
(
Entity entity,
ActorAnimationPropertiesData animationData,
ref ActorData actor,
ref ActorAnimationData animation,
ref AnimatorStateData animationState,
ref ActorWeaponReferenceData weaponReference) =>
{
var weaponEntity = weaponReference.Weapon;
if (EntityManager.Exists(weaponEntity) && EntityManager.HasComponent<WeaponPartsData>(weaponEntity))
{
var animator = EntityManager.GetComponentObject<Animator>(entity);
var parts = EntityManager.GetComponentObject<ActorBodyParts>(entity);
if (parts.WeaponContainer != null && animationState.State.IsTag("Interactive"))
{
var barrelDistance = Vector2.Distance(parts.WeaponContainer.position, actor.Aim);
if (barrelDistance >= settings.MinMouseDistanceBarrel)
{
var weapon = EntityManager.GetSharedComponentData<WeaponPartsData>(weaponEntity);
Vector2 hipLocalLookPoint = parts.Hip.InverseTransformPoint(actor.Aim);
Vector2 hipLocalGunPos =
parts.Hip.InverseTransformPoint(weapon.Barrel != null ? weapon.Barrel.position : Vector3.zero);
var gunLookDir = (hipLocalLookPoint - hipLocalGunPos).normalized;
var gunAngle = Vector2.SignedAngle(Vector2.up, gunLookDir);
if (EntityManager.HasComponent<ActorWeaponAccuracyData>(entity))
{
gunAngle -= EntityManager.GetComponentData<ActorWeaponAccuracyData>(entity).Accuracy;
}
var rot = Mathf.LerpAngle(
animation.LastGunRotation,
Mathf.Clamp(gunAngle, animationData.WeaponAngleRange.x, animationData.WeaponAngleRange.y),
settings.WeaponEase * Time.DeltaTime);
animation.LastGunRotation = rot;
parts.WeaponContainer.localRotation = Quaternion.Euler(0, 0, rot);
}
}
animator.SetLayerWeight(1, 1);
}
});
}
}
}