Files
Ipseity-Demo/Packages/OctoCore/Runtime/Scripts/Components/OctoPlayerDriver.cs
T
2026-06-02 12:16:31 +02:00

175 lines
5.9 KiB
C#

using UnityEngine;
using UnityEngine.Events;
namespace OctoCore.Components
{
public class OctoPlayerDriver : MonoBehaviour
{
[System.Serializable]
public class State
{
public bool ForcePlayerToFollowTarget;
[Range(0, 1)] public float MoveInfluence;
[Range(0, 1)] public float LookInfluence;
[Range(0, 180)] public float YawRange = 180;
[Range(0, 90)] public float PitchRange = 90;
}
[System.Serializable]
public class References
{
public Transform Target;
public Transform LookAt;
}
[System.Serializable]
public class Settings
{
[Min(.1f)] public float DriveStrength = 1;
[Range(0, 1)] public float LookAtStrength = 1;
[Range(.1f, 3)] public float LookAtSmooth = 1;
[Range(0, 1)] public float LookAtPoint = .5f;
public AnimationCurve DriveCurve = AnimationCurve.EaseInOut(0, 0, 1 , 1);
public AnimationCurve LookCurve = AnimationCurve.EaseInOut(0, 0, 1 , 1);
}
[System.Serializable]
public class Events
{
public UnityEvent OnDrive;
public UnityEvent OnFullInfluence;
public UnityEvent OnRelease;
}
[SerializeField, OctoReadOnly] private State _state;
[SerializeField] private References _references;
[SerializeField] private Settings _settings;
[SerializeField] private Events _events;
public References _References => _references;
public State _State => _state;
private bool _fullInfluenceReached;
void OnDrawGizmos()
{
#if UNITY_EDITOR
UnityEditor.Handles.color = Color.cyan;
const float size = .3f;
if (_references.Target)
{
UnityEditor.Handles.matrix = _references.Target.localToWorldMatrix;
UnityEditor.Handles.DrawLine(Vector3.forward * size, Vector3.back * size);
UnityEditor.Handles.DrawLine(Vector3.left * size, Vector3.right * size);
}
if (_references.LookAt)
{
UnityEditor.Handles.matrix = _references.LookAt.localToWorldMatrix;
UnityEditor.Handles.DrawWireCube(Vector3.zero, Vector3.one * size * .75f);
}
#endif
}
void Start()
{
}
void Update()
{
}
public void DrivePlayer()
{
_fullInfluenceReached = false;
_state.YawRange = 180;
_state.PitchRange = 90;
OctoPlayer.Instance.Drive(this);
_events.OnDrive?.Invoke();
}
public void ForcePlayerToFollowTarget(bool force)
{
_state.ForcePlayerToFollowTarget = force;
}
public void ReleasePlayer()
{
OctoPlayer.Instance.ReleaseDrive();
_state.YawRange = 180;
_state.PitchRange = 90;
_events.OnRelease?.Invoke();
}
public void ApplyMoveInfluence(Vector3 inMove, float delta, out Vector3 outMove)
{
if (!OctoPlayer.Instance || !OctoPlayer.Instance._FirstPerson.Camera || !_references.Target)
{
outMove = inMove;
return;
}
_state.MoveInfluence = Mathf.Clamp01(_state.MoveInfluence + delta * (_state.ForcePlayerToFollowTarget ? 1 : inMove.magnitude) * _settings.DriveStrength);
float moveInfluence = _settings.DriveCurve.Evaluate(_state.MoveInfluence);
if (!_fullInfluenceReached && _state.MoveInfluence >= 1)
{
_events.OnFullInfluence?.Invoke();
_fullInfluenceReached = true;
}
Vector3 offset = _references.Target.position - OctoPlayer.Instance.transform.position;
Vector3 offset2D = offset;
offset2D.y = 0;
float driveAtten = Mathf.InverseLerp(1, .1f, offset2D.magnitude);
Vector3 driveMove = offset;
driveMove.y = 0;
driveMove = driveMove.normalized * (_state.ForcePlayerToFollowTarget ? 1 : inMove.magnitude);
driveMove = Vector3.Lerp(driveMove, Vector3.zero, driveAtten);
outMove = Vector3.Lerp(inMove, driveMove, moveInfluence);
}
public void ApplyLookInfluence(float inYaw, float inPitch, float deltaTime, out float outYaw, out float outPitch)
{
if (!OctoPlayer.Instance || !OctoPlayer.Instance._FirstPerson.Camera || !_references.LookAt)
{
outYaw = inYaw;
outPitch = inPitch;
return;
}
Vector3 lookAt = _references.LookAt.position - OctoPlayer.Instance._FirstPerson.Camera.transform.position;
lookAt = lookAt.normalized;
Vector3 offset = _references.Target.position - OctoPlayer.Instance.transform.position;
Vector3 offset2D = offset;
offset2D.y = 0;
float lookAtYaw = Mathf.Atan2(lookAt.x, lookAt.z) * Mathf.Rad2Deg;
float lookAtPitch = Mathf.Asin(-lookAt.y) * Mathf.Rad2Deg;
_state.LookInfluence = Mathf.InverseLerp(_settings.LookAtPoint, 1, _state.MoveInfluence) * _settings.LookAtStrength;
float lookInfluence = _settings.LookCurve.Evaluate(_state.LookInfluence);
float t = deltaTime * _settings.LookAtSmooth;
_state.YawRange = Mathf.Lerp(_state.YawRange, Mathf.Lerp(180, 0, lookInfluence), t);
_state.PitchRange = Mathf.Lerp(_state.PitchRange, Mathf.Lerp(90, 0, lookInfluence), t);
outYaw = lookAtYaw + Mathf.Clamp(Mathf.DeltaAngle(lookAtYaw, inYaw), -_state.YawRange, _state.YawRange);
outPitch = lookAtPitch + Mathf.Clamp(Mathf.DeltaAngle(lookAtPitch, inPitch), -_state.PitchRange, _state.PitchRange);
}
}
}