110 lines
2.4 KiB
C#
110 lines
2.4 KiB
C#
using System;
|
|
using KitsuneCafe.Extension;
|
|
using KitsuneCafe.Input;
|
|
using KitsuneCafe.ItemSystem;
|
|
using KitsuneCafe.SOAP;
|
|
using R3;
|
|
using UnityEngine;
|
|
|
|
namespace KitsuneCafe.Entity
|
|
{
|
|
public class AimFeature : MonoBehaviour
|
|
{
|
|
[SerializeField]
|
|
private new Camera camera;
|
|
|
|
[SerializeField]
|
|
private EquipmentInstance equipment;
|
|
|
|
[SerializeField]
|
|
private Motor motor;
|
|
|
|
[SerializeField]
|
|
private ControlSchemeValue controlScheme;
|
|
|
|
[SerializeField]
|
|
private Vector2Value lookValue;
|
|
|
|
private void OnValidate()
|
|
{
|
|
if (camera == null)
|
|
{
|
|
camera = Camera.main;
|
|
}
|
|
|
|
if (equipment == null)
|
|
{
|
|
equipment = GetComponent<EquipmentInstance>();
|
|
}
|
|
|
|
if (motor == null)
|
|
{
|
|
motor = GetComponent<Motor>();
|
|
}
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
var d = Disposable.CreateBuilder();
|
|
|
|
var readied = Observable.FromEventHandler<bool>(
|
|
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.AsObservable()
|
|
.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;
|
|
}
|
|
}
|
|
}
|