Added UI and more

This commit is contained in:
2026-07-02 17:04:29 +03:00
parent eca9be620a
commit 8ac38208ae
190 changed files with 555483 additions and 101 deletions
@@ -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;
}
}