Files
PIM_Laba5/Assets/Scripts/PlayerStealth.cs
T
2026-05-26 01:16:57 +03:00

158 lines
4.9 KiB
C#

using UnityEngine;
[DefaultExecutionOrder(-50)]
[RequireComponent(typeof(CharacterController))]
[RequireComponent(typeof(SimpleFPSController))]
public class PlayerStealth : MonoBehaviour
{
public enum NoiseState
{
Silent,
Low,
Medium,
High
}
[Header("References")]
public CharacterController characterController;
public SimpleFPSController fpsController;
public Camera playerCamera;
[Header("Crouch")]
public float standingHeight = 2f;
public float crouchingHeight = 1.2f;
public float crouchSpeedMultiplier = 0.55f;
public float standingCameraLocalY = 0.8f;
public float crouchCameraLocalY = 0.35f;
public float crouchTransitionSpeed = 8f;
public float crouchVisibilityMultiplier = 0.72f;
[Header("Noise")]
public float noiseEmitInterval = 0.35f;
public float crouchNoiseIntensity = 0.45f;
public float walkNoiseIntensity = 0.8f;
public float runNoiseIntensity = 1.25f;
public float testNoiseIntensity = 1.6f;
public bool IsCrouching { get; private set; }
public NoiseState CurrentNoiseState { get; private set; } = NoiseState.Silent;
public float CurrentNoiseIntensity { get; private set; }
public float VisibilityMultiplier => IsCrouching ? crouchVisibilityMultiplier : 1f;
public string CurrentNoiseLabel => CurrentNoiseState.ToString().ToLowerInvariant();
private float currentControllerHeight;
private float targetCameraLocalY;
private float lastNoiseEmitTime = -999f;
private void Awake()
{
characterController = characterController != null ? characterController : GetComponent<CharacterController>();
fpsController = fpsController != null ? fpsController : GetComponent<SimpleFPSController>();
playerCamera = playerCamera != null ? playerCamera : GetComponentInChildren<Camera>();
currentControllerHeight = standingHeight;
targetCameraLocalY = standingCameraLocalY;
}
private void Start()
{
ApplyCharacterHeightImmediate(standingHeight);
SetCameraLocalY(standingCameraLocalY);
}
private void Update()
{
UpdateCrouchState();
UpdateNoiseState();
HandleManualNoise();
}
private void LateUpdate()
{
SmoothCrouchPresentation();
}
private void UpdateCrouchState()
{
IsCrouching = Input.GetKey(KeyCode.LeftControl);
fpsController.AllowRunning = !IsCrouching;
fpsController.SpeedScale = IsCrouching ? crouchSpeedMultiplier : 1f;
targetCameraLocalY = IsCrouching ? crouchCameraLocalY : standingCameraLocalY;
}
private void UpdateNoiseState()
{
if (!fpsController.HasMovementInput)
{
SetNoiseState(NoiseState.Silent, 0f);
return;
}
if (IsCrouching)
{
SetNoiseState(NoiseState.Low, crouchNoiseIntensity);
}
else if (fpsController.IsRunning)
{
SetNoiseState(NoiseState.High, runNoiseIntensity);
}
else
{
SetNoiseState(NoiseState.Medium, walkNoiseIntensity);
}
if (CurrentNoiseState != NoiseState.Silent && Time.time >= lastNoiseEmitTime + noiseEmitInterval)
{
lastNoiseEmitTime = Time.time;
// Периодические импульсы шума проще настраивать и удобнее для AI, чем шум каждый кадр.
NoiseManager.EmitNoise(transform.position, CurrentNoiseIntensity);
}
}
private void HandleManualNoise()
{
if (Input.GetKeyDown(KeyCode.R))
{
NoiseManager.EmitNoise(transform.position, testNoiseIntensity);
}
}
private void SmoothCrouchPresentation()
{
float desiredHeight = IsCrouching ? crouchingHeight : standingHeight;
currentControllerHeight = Mathf.Lerp(currentControllerHeight, desiredHeight, Time.deltaTime * crouchTransitionSpeed);
ApplyCharacterHeightImmediate(currentControllerHeight);
if (playerCamera != null)
{
Vector3 localPosition = playerCamera.transform.localPosition;
localPosition.y = Mathf.Lerp(localPosition.y, targetCameraLocalY, Time.deltaTime * crouchTransitionSpeed);
playerCamera.transform.localPosition = localPosition;
}
}
private void ApplyCharacterHeightImmediate(float height)
{
characterController.height = height;
characterController.center = new Vector3(0f, height * 0.5f, 0f);
}
private void SetCameraLocalY(float localY)
{
if (playerCamera == null)
{
return;
}
Vector3 localPosition = playerCamera.transform.localPosition;
localPosition.y = localY;
playerCamera.transform.localPosition = localPosition;
}
private void SetNoiseState(NoiseState state, float intensity)
{
CurrentNoiseState = state;
CurrentNoiseIntensity = intensity;
}
}