using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMotion : MonoBehaviour
{
private Player player;
[field: SerializeField] public Transform ArmTransform { get; private set; }
[field: SerializeField] public GameObject HandPos { get; private set; }
public Transform rootCam;
[Range(0.0001f, 1f), SerializeField]
private float amount = 0.005f;
[Range(1f, 30f), SerializeField]
private float frequency = 10.0f;
[Range(10f, 100f), SerializeField]
private float smooth = 10.0f;
#region
private float eulerAngleX;
private float eulerAngleY;
private float limitMinX = -80;
private float limitMaxX = 50;
#endregion
private Quaternion initialLocalRotation;
private void Awake()
{
player = GetComponent<Player>();
}
private void Start()
{
initialLocalRotation = HandPos.transform.localRotation;
}
/// <summary>
/// 조준 시 캐릭터 STP 수치에 따른 흔들림 기능
/// </summary>
public void StartHeadBob()
{
float t = Mathf.InverseLerp(1f, 99f, player.Stat.STP); // STP가 1일 때 0, 99일 때 1
Debug.Log($"플레이어 스텝:: { player.Stat.STP}");
float inverseEffect = 1f - t; // 반비례 효과
Vector3 pos = Vector3.zero;
pos.z += Mathf.Lerp(pos.z, Mathf.Sin(Time.time * frequency) * amount * inverseEffect, smooth * Time.deltaTime);
rootCam.localPosition = pos;
Debug.Log(ArmTransform.localPosition);
}
/// <summary>
/// 조준 시 캐릭터 HDL 수치에 따른 조준 흔들림 기능
/// </summary>
public void WeaponShake()
{
var accuracy = Mathf.Clamp01((99f - player.Stat.HDL) / 98f);
var shakeAmount = accuracy * 7.5f;
var rotX = (Mathf.PerlinNoise(Time.time * 0.7f, 0f) - 0.5f) * shakeAmount;
var rotY = (Mathf.PerlinNoise(0f, Time.time * 0.7f) - 0.5f) * shakeAmount * 3f;
var rotZ = (Mathf.PerlinNoise(Time.time * 0.7f, Time.time * 0.7f) - 0.5f) * shakeAmount;
var shakeRotation = Quaternion.Euler(rotX, rotY, rotZ);
HandPos.transform.localRotation = initialLocalRotation * shakeRotation;
}
public void ApplyRecoil(float recoilAmount)
{
StopAllCoroutines();
StartCoroutine(RecoilCoroutine(recoilAmount));
}
private IEnumerator RecoilCoroutine(float recoilAmount)
{
float duration = 0.075f; // 반동 걸리는 시간
float elapsed = 0f;
float startX = eulerAngleX;
float targetX = eulerAngleX - recoilAmount;
targetX = ClampAngle(targetX, limitMinX, limitMaxX);
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = elapsed / duration;
eulerAngleX = Mathf.Lerp(startX, targetX, t);
ArmTransform.rotation = Quaternion.Euler(eulerAngleX, eulerAngleY, 0);
yield return null;
}
eulerAngleX = targetX;
ArmTransform.rotation = Quaternion.Euler(eulerAngleX, eulerAngleY, 0);
}
private float ClampAngle(float angle, float min, float max)
{
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp(angle, min, max);
}
}
Player에 웨폰 효과를 넣는건 애매한 것 같아서
PlayerMotion 스크립트를 따로 파서 Player에 캐싱해주었다.
'Game Engine > Game Project' 카테고리의 다른 글
[Unity] Nan을 조심하자 (0) | 2025.04.30 |
---|---|
[Unity] Cinemachine으로 FPS Headbob 구현하기 (0) | 2025.04.29 |
[Unity] 덜컹 거리는 움직임 (0) | 2025.04.18 |
[Unity] HeadBob 구현 (0) | 2025.04.17 |
[Unity] JsonUtility NewtonSoft JSON 차이 (0) | 2025.04.15 |