Added UI and more
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
using UnityEngine;
|
||||
using DG.Tweening;
|
||||
|
||||
/// <summary>
|
||||
/// Визуальная "живость" рук от первого лица: свэй за движением мыши, покачивание
|
||||
/// при ходьбе и сочная отдача при выстреле через DOTween.
|
||||
/// Висит на FPV-Hands (активен только у владельца), поэтому проверки IsOwner не нужны.
|
||||
/// Всё считается как смещение поверх исходного localPosition/localRotation,
|
||||
/// а отдача пишется в отдельные поля — свэй/боб и DOTween не конфликтуют за трансформ.
|
||||
/// </summary>
|
||||
public class WeaponView : MonoBehaviour
|
||||
{
|
||||
[Header("Sway (свэй за мышью)")]
|
||||
[SerializeField] private float swayAmount = 2f;
|
||||
[SerializeField] private float swayMax = 6f;
|
||||
[SerializeField] private float swaySmooth = 8f;
|
||||
|
||||
[Header("Bob (покачивание при ходьбе)")]
|
||||
[SerializeField] private float bobSpeed = 9f;
|
||||
[SerializeField] private float bobAmount = 0.03f;
|
||||
[SerializeField] private float bobSmooth = 10f;
|
||||
|
||||
[Header("Recoil (отдача при выстреле)")]
|
||||
[SerializeField] private float recoilKickback = 0.12f; // назад по Z
|
||||
[SerializeField] private float recoilKickUp = 9f; // поворот ствола вверх (X)
|
||||
[SerializeField] private float recoilDuration = 0.22f;
|
||||
|
||||
private Vector3 originPos;
|
||||
private Quaternion originRot;
|
||||
|
||||
private Vector3 swayRotOffset;
|
||||
private Vector3 bobPosOffset;
|
||||
|
||||
private Vector3 recoilPos;
|
||||
private Vector3 recoilRot;
|
||||
private float bobTimer;
|
||||
|
||||
private Sequence recoilSequence;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
originPos = transform.localPosition;
|
||||
originRot = transform.localRotation;
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
ApplySway();
|
||||
ApplyBob();
|
||||
|
||||
transform.localPosition = originPos + bobPosOffset + recoilPos;
|
||||
transform.localRotation = originRot * Quaternion.Euler(swayRotOffset + recoilRot);
|
||||
}
|
||||
|
||||
private void ApplySway()
|
||||
{
|
||||
float _mouseX = Input.GetAxis("Mouse X");
|
||||
float _mouseY = Input.GetAxis("Mouse Y");
|
||||
|
||||
// руки "отстают" от поворота камеры
|
||||
float _targetPitch = Mathf.Clamp(-_mouseY * swayAmount, -swayMax, swayMax);
|
||||
float _targetYaw = Mathf.Clamp(-_mouseX * swayAmount, -swayMax, swayMax);
|
||||
|
||||
Vector3 _target = new Vector3(_targetPitch, _targetYaw, 0f);
|
||||
swayRotOffset = Vector3.Lerp(swayRotOffset, _target, swaySmooth * Time.deltaTime);
|
||||
}
|
||||
|
||||
private void ApplyBob()
|
||||
{
|
||||
float _moveMagnitude = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")).magnitude;
|
||||
|
||||
Vector3 _target = Vector3.zero;
|
||||
|
||||
if (_moveMagnitude > 0.1f)
|
||||
{
|
||||
bobTimer += Time.deltaTime * bobSpeed;
|
||||
float _x = Mathf.Cos(bobTimer) * bobAmount;
|
||||
float _y = Mathf.Abs(Mathf.Sin(bobTimer)) * bobAmount;
|
||||
_target = new Vector3(_x, _y, 0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
bobTimer = 0f;
|
||||
}
|
||||
|
||||
bobPosOffset = Vector3.Lerp(bobPosOffset, _target, bobSmooth * Time.deltaTime);
|
||||
}
|
||||
|
||||
public void PlayShoot()
|
||||
{
|
||||
recoilSequence?.Kill();
|
||||
|
||||
recoilPos = Vector3.zero;
|
||||
recoilRot = Vector3.zero;
|
||||
|
||||
float _kick = recoilDuration * 0.35f;
|
||||
float _return = recoilDuration * 0.65f;
|
||||
|
||||
recoilSequence = DOTween.Sequence().SetTarget(this);
|
||||
|
||||
// Позиция: резкий отскок назад, затем плавный возврат
|
||||
recoilSequence.Append(DOTween.To(() => recoilPos, _v => recoilPos = _v,
|
||||
new Vector3(0f, 0f, -recoilKickback), _kick).SetEase(Ease.OutQuad));
|
||||
recoilSequence.Append(DOTween.To(() => recoilPos, _v => recoilPos = _v,
|
||||
Vector3.zero, _return).SetEase(Ease.OutBack));
|
||||
|
||||
// Поворот: ствол подбрасывает вверх и возвращает — параллельно позиции
|
||||
recoilSequence.Insert(0f, DOTween.To(() => recoilRot, _v => recoilRot = _v,
|
||||
new Vector3(-recoilKickUp, 0f, 0f), _kick).SetEase(Ease.OutQuad));
|
||||
recoilSequence.Insert(_kick, DOTween.To(() => recoilRot, _v => recoilRot = _v,
|
||||
Vector3.zero, _return).SetEase(Ease.OutBack));
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
recoilSequence?.Kill();
|
||||
recoilPos = Vector3.zero;
|
||||
recoilRot = Vector3.zero;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user