using KitsuneCafe.Extension; using KitsuneCafe.Input; using KitsuneCafe.ItemSystem.Entities; using R3; using UnityAtoms.BaseAtoms; using UnityAtoms.KitsuneCafe.Input; using UnityEngine; namespace KitsuneCafe.Entities { public class AimFeature : MonoBehaviour { [SerializeField] private new Camera camera; [SerializeField] private EquipmentInstance equipment; [SerializeField] private Motor motor; [SerializeField] private ControlSchemeReference controlScheme; [SerializeField] private Vector2Reference lookValue; private void Reset() { camera = Camera.main; equipment = GetComponent(); motor = GetComponent(); } private void Start() { var d = Disposable.CreateBuilder(); var readied = Observable.FromEventHandler( e => equipment.Readied += e, e => equipment.Readied -= e ) .Select(static eh => eh.e); readied .Subscribe(isReady => { motor.enabled = !isReady; }) .AddTo(ref d); readied .WhereTrue() .SelectMany(_ => controlScheme.ObserveChange() .CombineLatest( Observable.IntervalFrame(1), static (scheme, _) => scheme ).TakeUntil(readied.WhereFalse()) ) .Subscribe(Aim) .AddTo(ref d); d.RegisterTo(destroyCancellationToken); } private void Aim(ControlScheme scheme) { switch (scheme) { case ControlScheme.Gamepad: LookInDirection(lookValue.Value); break; default: LookAtPosition(lookValue.Value); break; } } private void LookInDirection(Vector2 value) { transform.LookAt(transform.position + new Vector3(value.x, 0, value.y)); } private void LookAtPosition(Vector2 value) { var screenPosition = camera.WorldToViewportPoint(transform.position); var mouseOnScreen = camera.ScreenToViewportPoint(value); float angle = AngleBetween(screenPosition, mouseOnScreen); transform.rotation = Quaternion.Euler(new Vector3(0, -angle + 90, 0)); } static float AngleBetween(Vector3 a, Vector3 b) { return Mathf.Atan2(b.y - a.y, b.x - a.x) * Mathf.Rad2Deg; } } }