158 lines
4.9 KiB
C#
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;
|
|
}
|
|
}
|