Files
Alex38Lyon 878ea46cac update
2025-06-03 12:00:47 +02:00

154 lines
5.7 KiB
C#

using Unity.FPS.Game;
using UnityEngine;
using UnityEngine.Events;
namespace Unity.FPS.Gameplay
{
[RequireComponent(typeof(AudioSource))]
public class Jetpack : MonoBehaviour
{
[Header("References")] [Tooltip("Audio source for jetpack sfx")]
public AudioSource AudioSource;
[Tooltip("Particles for jetpack vfx")] public ParticleSystem[] JetpackVfx;
[Header("Parameters")] [Tooltip("Whether the jetpack is unlocked at the begining or not")]
public bool IsJetpackUnlockedAtStart = false;
[Tooltip("The strength with which the jetpack pushes the player up")]
public float JetpackAcceleration = 7f;
[Range(0f, 1f)]
[Tooltip(
"This will affect how much using the jetpack will cancel the gravity value, to start going up faster. 0 is not at all, 1 is instant")]
public float JetpackDownwardVelocityCancelingFactor = 1f;
[Header("Durations")] [Tooltip("Time it takes to consume all the jetpack fuel")]
public float ConsumeDuration = 1.5f;
[Tooltip("Time it takes to completely refill the jetpack while on the ground")]
public float RefillDurationGrounded = 2f;
[Tooltip("Time it takes to completely refill the jetpack while in the air")]
public float RefillDurationInTheAir = 5f;
[Tooltip("Delay after last use before starting to refill")]
public float RefillDelay = 1f;
[Header("Audio")] [Tooltip("Sound played when using the jetpack")]
public AudioClip JetpackSfx;
bool m_CanUseJetpack;
PlayerCharacterController m_PlayerCharacterController;
PlayerInputHandler m_InputHandler;
float m_LastTimeOfUse;
// stored ratio for jetpack resource (1 is full, 0 is empty)
public float CurrentFillRatio { get; private set; }
public bool IsJetpackUnlocked { get; private set; }
public bool IsPlayergrounded() => m_PlayerCharacterController.IsGrounded;
public UnityAction<bool> OnUnlockJetpack;
void Start()
{
IsJetpackUnlocked = IsJetpackUnlockedAtStart;
m_PlayerCharacterController = GetComponent<PlayerCharacterController>();
DebugUtility.HandleErrorIfNullGetComponent<PlayerCharacterController, Jetpack>(m_PlayerCharacterController,
this, gameObject);
m_InputHandler = GetComponent<PlayerInputHandler>();
DebugUtility.HandleErrorIfNullGetComponent<PlayerInputHandler, Jetpack>(m_InputHandler, this, gameObject);
CurrentFillRatio = 1f;
AudioSource.clip = JetpackSfx;
AudioSource.loop = true;
}
void Update()
{
// jetpack can only be used if not grounded and jump has been pressed again once in-air
if (IsPlayergrounded())
{
m_CanUseJetpack = false;
}
else if (!m_PlayerCharacterController.HasJumpedThisFrame && m_InputHandler.GetJumpInputDown())
{
m_CanUseJetpack = true;
}
// jetpack usage
bool jetpackIsInUse = m_CanUseJetpack && IsJetpackUnlocked && CurrentFillRatio > 0f &&
m_InputHandler.GetJumpInputHeld();
if (jetpackIsInUse)
{
// store the last time of use for refill delay
m_LastTimeOfUse = Time.time;
float totalAcceleration = JetpackAcceleration;
// cancel out gravity
totalAcceleration += m_PlayerCharacterController.GravityDownForce;
if (m_PlayerCharacterController.CharacterVelocity.y < 0f)
{
// handle making the jetpack compensate for character's downward velocity with bonus acceleration
totalAcceleration += ((-m_PlayerCharacterController.CharacterVelocity.y / Time.deltaTime) *
JetpackDownwardVelocityCancelingFactor);
}
// apply the acceleration to character's velocity
m_PlayerCharacterController.CharacterVelocity += Vector3.up * totalAcceleration * Time.deltaTime;
// consume fuel
CurrentFillRatio = CurrentFillRatio - (Time.deltaTime / ConsumeDuration);
for (int i = 0; i < JetpackVfx.Length; i++)
{
var emissionModulesVfx = JetpackVfx[i].emission;
emissionModulesVfx.enabled = true;
}
if (!AudioSource.isPlaying)
AudioSource.Play();
}
else
{
// refill the meter over time
if (IsJetpackUnlocked && Time.time - m_LastTimeOfUse >= RefillDelay)
{
float refillRate = 1 / (m_PlayerCharacterController.IsGrounded
? RefillDurationGrounded
: RefillDurationInTheAir);
CurrentFillRatio = CurrentFillRatio + Time.deltaTime * refillRate;
}
for (int i = 0; i < JetpackVfx.Length; i++)
{
var emissionModulesVfx = JetpackVfx[i].emission;
// emissionModulesVfx.enabled = false;
}
// keeps the ratio between 0 and 1
CurrentFillRatio = Mathf.Clamp01(CurrentFillRatio);
if (AudioSource.isPlaying)
AudioSource.Stop();
}
}
public bool TryUnlock()
{
if (IsJetpackUnlocked)
return false;
OnUnlockJetpack.Invoke(true);
IsJetpackUnlocked = true;
m_LastTimeOfUse = Time.time;
return true;
}
}
}