initial
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
[RequireComponent(typeof(AudioSource))]
|
||||
public class MotionAudioController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform targetTransform;
|
||||
[SerializeField] private Animator animator;
|
||||
[SerializeField] private AudioSource audioSource;
|
||||
[SerializeField] private Vector3 lastPosition;
|
||||
|
||||
[SerializeField, Tooltip("Threshold for movement detection. Adjust as needed.")]
|
||||
private float movementThreshold = 0.0001f;
|
||||
|
||||
[SerializeField, Tooltip("Duration of the fade-out effect in seconds")]
|
||||
private float fadeOutDuration = 0.5f;
|
||||
|
||||
private bool wasMoving = false;
|
||||
private Coroutine fadeCoroutine;
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Get the AudioSource attached to this GameObject
|
||||
audioSource = GetComponent<AudioSource>();
|
||||
|
||||
// Find the Animator in sibling or child objects
|
||||
animator = GetComponentInParent<Animator>();
|
||||
|
||||
if (animator != null)
|
||||
{
|
||||
targetTransform = animator.transform;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("No Animator component found in parent or its children.");
|
||||
}
|
||||
|
||||
// Initialize last position
|
||||
if (targetTransform != null)
|
||||
{
|
||||
lastPosition = targetTransform.position;
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (targetTransform == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the object has moved significantly
|
||||
float movement = Vector3.Distance(targetTransform.position, lastPosition);
|
||||
bool isMoving = movement > movementThreshold;
|
||||
|
||||
if (isMoving && !wasMoving)
|
||||
{
|
||||
// If there's a fade-out in progress, stop it
|
||||
if (fadeCoroutine != null)
|
||||
{
|
||||
StopCoroutine(fadeCoroutine);
|
||||
fadeCoroutine = null;
|
||||
}
|
||||
|
||||
// Reset volume to full
|
||||
audioSource.volume = 1f;
|
||||
|
||||
// Start playing audio only when movement starts
|
||||
if (!audioSource.isPlaying)
|
||||
{
|
||||
audioSource.Play();
|
||||
}
|
||||
}
|
||||
else if (!isMoving && wasMoving)
|
||||
{
|
||||
// Start fade-out when movement stops
|
||||
if (audioSource.isPlaying)
|
||||
{
|
||||
// If there's already a fade-out in progress, stop it
|
||||
if (fadeCoroutine != null)
|
||||
{
|
||||
StopCoroutine(fadeCoroutine);
|
||||
}
|
||||
fadeCoroutine = StartCoroutine(FadeOut());
|
||||
}
|
||||
}
|
||||
|
||||
// Update movement state
|
||||
wasMoving = isMoving;
|
||||
|
||||
// Update last position for the next frame
|
||||
lastPosition = targetTransform.position;
|
||||
}
|
||||
|
||||
private IEnumerator FadeOut()
|
||||
{
|
||||
float startVolume = audioSource.volume;
|
||||
float currentTime = 0;
|
||||
|
||||
while (currentTime < fadeOutDuration)
|
||||
{
|
||||
currentTime += Time.deltaTime;
|
||||
audioSource.volume = Mathf.Lerp(startVolume, 0, currentTime / fadeOutDuration);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Ensure volume is zero and stop the audio
|
||||
audioSource.volume = 0;
|
||||
audioSource.Stop();
|
||||
fadeCoroutine = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c2a1f8514c164c1b84d93b38976ba4d
|
||||
@@ -0,0 +1,49 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class Pickup : MonoBehaviour
|
||||
{
|
||||
[Header("Effects")]
|
||||
public GameObject particleEffectPrefab; // Assign particle system prefab in Inspector
|
||||
|
||||
[Header("Motion Settings")]
|
||||
public float rotationSpeed = 100f; // Rotation speed in degrees per second
|
||||
public float bobbingAmount = 0.1f; // Amplitude of bobbing motion
|
||||
public float bobbingSpeed = 1f; // Speed of bobbing motion
|
||||
|
||||
private Vector3 startPosition;
|
||||
private float timer;
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Remember the original position of the GameObject
|
||||
startPosition = transform.position;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// Rotate the object around its up axis
|
||||
transform.Rotate(Vector3.up, rotationSpeed * Time.deltaTime, Space.World);
|
||||
|
||||
// Create a bobbing motion up and down
|
||||
timer += Time.deltaTime * bobbingSpeed;
|
||||
float newY = startPosition.y + Mathf.Sin(timer) * bobbingAmount;
|
||||
transform.position = new Vector3(transform.position.x, newY, transform.position.z);
|
||||
}
|
||||
|
||||
void OnTriggerEnter(Collider other)
|
||||
{
|
||||
// Check if the colliding object has the "Player" tag
|
||||
if (other.CompareTag("Player"))
|
||||
{
|
||||
// Instantiate the particle effect
|
||||
if (particleEffectPrefab != null)
|
||||
{
|
||||
Instantiate(particleEffectPrefab, transform.position, Quaternion.identity);
|
||||
}
|
||||
|
||||
// Destroy the star
|
||||
Destroy(gameObject);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55fcea8a4058c4d1aa6ca8fea4168f51
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,100 @@
|
||||
using UnityEngine;
|
||||
using Unity.Cinemachine;
|
||||
|
||||
namespace StarterAssets
|
||||
{
|
||||
[RequireComponent(typeof(CharacterController))]
|
||||
public class RespawnPlayer : MonoBehaviour
|
||||
{
|
||||
[Tooltip("The Y position threshold at which the player will respawn.")]
|
||||
public float yThreshold = -5f;
|
||||
|
||||
private Vector3 _startingPosition;
|
||||
|
||||
private Quaternion _startingRotation;
|
||||
|
||||
private CharacterController _characterController;
|
||||
|
||||
public CinemachineCamera vCam;
|
||||
|
||||
private ThirdPersonController _thirdPersonController;
|
||||
public AudioClip respawnSound;
|
||||
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Save the starting position and rotation
|
||||
_startingPosition = transform.position;
|
||||
_startingRotation = transform.rotation;
|
||||
|
||||
// Get the CharacterController reference
|
||||
_characterController = GetComponent<CharacterController>();
|
||||
if (_characterController == null)
|
||||
{
|
||||
Debug.LogError("CharacterController component is required for RespawnPlayer script!");
|
||||
}
|
||||
|
||||
// Get ThirdPersonController reference
|
||||
_thirdPersonController = GetComponent<ThirdPersonController>();
|
||||
if (_thirdPersonController == null)
|
||||
{
|
||||
Debug.LogError("ThirdPersonController component is required for RespawnPlayer!");
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// Check if the player's Y position has fallen below the threshold
|
||||
if (transform.position.y < yThreshold)
|
||||
{
|
||||
Respawn();
|
||||
}
|
||||
}
|
||||
|
||||
private void Respawn()
|
||||
{
|
||||
// Disable the CharacterController so we can manually adjust position
|
||||
if (_characterController != null)
|
||||
{
|
||||
_characterController.enabled = false; // Disable to reset position/rotation correctly
|
||||
}
|
||||
|
||||
// Reset the player's position and rotation
|
||||
transform.position = _startingPosition;
|
||||
transform.rotation = Quaternion.Euler(0f, 90f, 0f); // Reset player Y rotation to 90 degrees
|
||||
|
||||
// Reset the CharacterController's vertical velocity to ensure the robot doesn't keep falling
|
||||
if (_characterController != null)
|
||||
{
|
||||
_characterController.enabled = true; // Enable it back after resetting position
|
||||
ResetVerticalVelocity();
|
||||
}
|
||||
|
||||
// Reset the camera's rotation
|
||||
ThirdPersonController thirdPersonController = GetComponent<ThirdPersonController>();
|
||||
if (thirdPersonController != null)
|
||||
{
|
||||
thirdPersonController.ResetCameraRotation(90f); // Reset camera's Y rotation to 90 degrees
|
||||
}
|
||||
|
||||
AudioSource.PlayClipAtPoint(respawnSound, transform.position);
|
||||
|
||||
}
|
||||
|
||||
private void ResetVerticalVelocity()
|
||||
{
|
||||
// Ensures no residual vertical velocity after respawning
|
||||
if (TryGetComponent<ThirdPersonController>(out ThirdPersonController controller))
|
||||
{
|
||||
// Access the private _verticalVelocity via the public interface, if exposed
|
||||
var verticalVelocityField = typeof(ThirdPersonController).GetField("_verticalVelocity",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
|
||||
if (verticalVelocityField != null)
|
||||
{
|
||||
verticalVelocityField.SetValue(controller, 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0406f8ea9ab1b4647b7fb3b65a763f94
|
||||
@@ -0,0 +1,433 @@
|
||||
using UnityEngine;
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
/* Note: animations are called via the controller for both the character and capsule using animator null checks
|
||||
*/
|
||||
|
||||
namespace StarterAssets
|
||||
{
|
||||
[RequireComponent(typeof(CharacterController))]
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
[RequireComponent(typeof(PlayerInput))]
|
||||
#endif
|
||||
public class ThirdPersonController : MonoBehaviour
|
||||
{
|
||||
[Header("Player")]
|
||||
[Tooltip("Move speed of the character in m/s")]
|
||||
public float MoveSpeed = 2.0f;
|
||||
|
||||
[Tooltip("Sprint speed of the character in m/s")]
|
||||
public float SprintSpeed = 5.335f;
|
||||
|
||||
[Tooltip("How fast the character turns to face movement direction")]
|
||||
[Range(0.0f, 0.3f)]
|
||||
public float RotationSmoothTime = 0.12f;
|
||||
|
||||
[Tooltip("Acceleration and deceleration")]
|
||||
public float SpeedChangeRate = 10.0f;
|
||||
|
||||
public AudioClip LandingAudioClip;
|
||||
public AudioClip[] FootstepAudioClips;
|
||||
[Range(0, 1)] public float FootstepAudioVolume = 0.5f;
|
||||
|
||||
[Space(10)]
|
||||
[Tooltip("The height the player can jump")]
|
||||
public float JumpHeight = 1.2f;
|
||||
|
||||
[Tooltip("The character uses its own gravity value. The engine default is -9.81f")]
|
||||
public float Gravity = -15.0f;
|
||||
|
||||
[Space(10)]
|
||||
[Tooltip("Time required to pass before being able to jump again. Set to 0f to instantly jump again")]
|
||||
public float JumpTimeout = 0.50f;
|
||||
|
||||
[Tooltip("Time required to pass before entering the fall state. Useful for walking down stairs")]
|
||||
public float FallTimeout = 0.15f;
|
||||
|
||||
[Header("Player Grounded")]
|
||||
[Tooltip("If the character is grounded or not. Not part of the CharacterController built in grounded check")]
|
||||
public bool Grounded = true;
|
||||
|
||||
[Tooltip("Useful for rough ground")]
|
||||
public float GroundedOffset = -0.14f;
|
||||
|
||||
[Tooltip("The radius of the grounded check. Should match the radius of the CharacterController")]
|
||||
public float GroundedRadius = 0.28f;
|
||||
|
||||
[Tooltip("What layers the character uses as ground")]
|
||||
public LayerMask GroundLayers;
|
||||
|
||||
[Header("Cinemachine")]
|
||||
[Tooltip("The follow target set in the Cinemachine Virtual Camera that the camera will follow")]
|
||||
public GameObject CinemachineCameraTarget;
|
||||
|
||||
[Tooltip("How far in degrees can you move the camera up")]
|
||||
public float TopClamp = 70.0f;
|
||||
|
||||
[Tooltip("How far in degrees can you move the camera down")]
|
||||
public float BottomClamp = -30.0f;
|
||||
|
||||
[Tooltip("Additional degress to override the camera. Useful for fine tuning camera position when locked")]
|
||||
public float CameraAngleOverride = 0.0f;
|
||||
|
||||
[Tooltip("For locking the camera position on all axis")]
|
||||
public bool LockCameraPosition = false;
|
||||
|
||||
public Vector2 LookSensitivity = new Vector2(7.5f, 5.0f);
|
||||
|
||||
// cinemachine
|
||||
private float _cinemachineTargetYaw;
|
||||
private float _cinemachineTargetPitch;
|
||||
|
||||
// Camera starting position and rotation
|
||||
private Vector3 _cameraStartingPosition;
|
||||
private Quaternion _cameraStartingRotation;
|
||||
|
||||
// Variable to indicate if we are resetting the camera
|
||||
public bool IsRespawning { get; set; } = false;
|
||||
|
||||
|
||||
// player
|
||||
private float _speed;
|
||||
private float _animationBlend;
|
||||
private float _targetRotation = 0.0f;
|
||||
private float _rotationVelocity;
|
||||
private float _verticalVelocity;
|
||||
private float _terminalVelocity = 53.0f;
|
||||
|
||||
// timeout deltatime
|
||||
private float _jumpTimeoutDelta;
|
||||
private float _fallTimeoutDelta;
|
||||
|
||||
// animation IDs
|
||||
private int _animIDSpeed;
|
||||
private int _animIDGrounded;
|
||||
private int _animIDJump;
|
||||
private int _animIDFreeFall;
|
||||
private int _animIDMotionSpeed;
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
private PlayerInput _playerInput;
|
||||
#endif
|
||||
private Animator _animator;
|
||||
private CharacterController _controller;
|
||||
private StarterAssetsInputs _input;
|
||||
private GameObject _mainCamera;
|
||||
|
||||
private const float _threshold = 0.01f;
|
||||
|
||||
private bool _hasAnimator;
|
||||
|
||||
private bool IsCurrentDeviceMouse
|
||||
{
|
||||
get
|
||||
{
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
return _playerInput.currentControlScheme == "KeyboardMouse";
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// get a reference to our main camera
|
||||
if (_mainCamera == null)
|
||||
{
|
||||
_mainCamera = GameObject.FindGameObjectWithTag("MainCamera");
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_cinemachineTargetYaw = CinemachineCameraTarget.transform.rotation.eulerAngles.y;
|
||||
|
||||
_hasAnimator = TryGetComponent(out _animator);
|
||||
_controller = GetComponent<CharacterController>();
|
||||
_input = GetComponent<StarterAssetsInputs>();
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
_playerInput = GetComponent<PlayerInput>();
|
||||
#else
|
||||
Debug.LogError("Starter Assets package is missing dependencies. Please use Tools/Starter Assets/Reinstall Dependencies to fix it");
|
||||
#endif
|
||||
|
||||
AssignAnimationIDs();
|
||||
|
||||
// Save the starting camera position and rotation
|
||||
_cameraStartingPosition = CinemachineCameraTarget.transform.position;
|
||||
_cameraStartingRotation = CinemachineCameraTarget.transform.rotation;
|
||||
|
||||
// reset our timeouts on start
|
||||
_jumpTimeoutDelta = JumpTimeout;
|
||||
_fallTimeoutDelta = FallTimeout;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
_hasAnimator = TryGetComponent(out _animator);
|
||||
|
||||
JumpAndGravity();
|
||||
GroundedCheck();
|
||||
Move();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
CameraRotation();
|
||||
}
|
||||
|
||||
private void AssignAnimationIDs()
|
||||
{
|
||||
_animIDSpeed = Animator.StringToHash("Speed");
|
||||
_animIDGrounded = Animator.StringToHash("Grounded");
|
||||
_animIDJump = Animator.StringToHash("Jump");
|
||||
_animIDFreeFall = Animator.StringToHash("FreeFall");
|
||||
_animIDMotionSpeed = Animator.StringToHash("MotionSpeed");
|
||||
}
|
||||
|
||||
private void GroundedCheck()
|
||||
{
|
||||
// set sphere position, with offset
|
||||
Vector3 spherePosition = new Vector3(transform.position.x, transform.position.y - GroundedOffset,
|
||||
transform.position.z);
|
||||
Grounded = Physics.CheckSphere(spherePosition, GroundedRadius, GroundLayers,
|
||||
QueryTriggerInteraction.Ignore);
|
||||
|
||||
// update animator if using character
|
||||
if (_hasAnimator)
|
||||
{
|
||||
_animator.SetBool(_animIDGrounded, Grounded);
|
||||
}
|
||||
}
|
||||
|
||||
private void CameraRotation()
|
||||
{
|
||||
// if respawning, reset to starting position and rotation
|
||||
if (IsRespawning)
|
||||
{
|
||||
_cinemachineTargetYaw = 0f; // Reset yaw to zero (or configure as needed)
|
||||
_cinemachineTargetPitch = 0f;
|
||||
|
||||
// Reset Cinemachine Camera Target to its starting state
|
||||
CinemachineCameraTarget.transform.position = _cameraStartingPosition;
|
||||
CinemachineCameraTarget.transform.rotation = _cameraStartingRotation;
|
||||
|
||||
IsRespawning = false; // Reset the respawning flag
|
||||
return;
|
||||
}
|
||||
|
||||
// if there is an input and camera position is not fixed
|
||||
if (_input.look.sqrMagnitude >= _threshold && !LockCameraPosition)
|
||||
{
|
||||
float deltaTimeMultiplier = IsCurrentDeviceMouse ? 1.0f : Time.deltaTime;
|
||||
|
||||
_cinemachineTargetYaw += _input.look.x * deltaTimeMultiplier * LookSensitivity.x;
|
||||
_cinemachineTargetPitch += _input.look.y * deltaTimeMultiplier * LookSensitivity.y;
|
||||
}
|
||||
|
||||
_cinemachineTargetYaw = ClampAngle(_cinemachineTargetYaw, float.MinValue, float.MaxValue);
|
||||
_cinemachineTargetPitch = ClampAngle(_cinemachineTargetPitch, BottomClamp, TopClamp);
|
||||
|
||||
CinemachineCameraTarget.transform.rotation = Quaternion.Euler(
|
||||
_cinemachineTargetPitch + CameraAngleOverride,
|
||||
_cinemachineTargetYaw,
|
||||
0.0f
|
||||
);
|
||||
}
|
||||
|
||||
private void Move()
|
||||
{
|
||||
// set target speed based on move speed, sprint speed and if sprint is pressed
|
||||
float targetSpeed = _input.sprint ? SprintSpeed : MoveSpeed;
|
||||
|
||||
// a simplistic acceleration and deceleration designed to be easy to remove, replace, or iterate upon
|
||||
|
||||
// note: Vector2's == operator uses approximation so is not floating point error prone, and is cheaper than magnitude
|
||||
// if there is no input, set the target speed to 0
|
||||
if (_input.move == Vector2.zero) targetSpeed = 0.0f;
|
||||
|
||||
// a reference to the players current horizontal velocity
|
||||
float currentHorizontalSpeed = new Vector3(_controller.velocity.x, 0.0f, _controller.velocity.z).magnitude;
|
||||
|
||||
float speedOffset = 0.1f;
|
||||
float inputMagnitude = _input.analogMovement ? _input.move.magnitude : 1f;
|
||||
|
||||
// accelerate or decelerate to target speed
|
||||
if (currentHorizontalSpeed < targetSpeed - speedOffset ||
|
||||
currentHorizontalSpeed > targetSpeed + speedOffset)
|
||||
{
|
||||
// creates curved result rather than a linear one giving a more organic speed change
|
||||
// note T in Lerp is clamped, so we don't need to clamp our speed
|
||||
_speed = Mathf.Lerp(currentHorizontalSpeed, targetSpeed * inputMagnitude,
|
||||
Time.deltaTime * SpeedChangeRate);
|
||||
|
||||
// round speed to 3 decimal places
|
||||
_speed = Mathf.Round(_speed * 1000f) / 1000f;
|
||||
}
|
||||
else
|
||||
{
|
||||
_speed = targetSpeed;
|
||||
}
|
||||
|
||||
_animationBlend = Mathf.Lerp(_animationBlend, targetSpeed, Time.deltaTime * SpeedChangeRate);
|
||||
if (_animationBlend < 0.01f) _animationBlend = 0f;
|
||||
|
||||
// normalise input direction
|
||||
Vector3 inputDirection = new Vector3(_input.move.x, 0.0f, _input.move.y).normalized;
|
||||
|
||||
// note: Vector2's != operator uses approximation so is not floating point error prone, and is cheaper than magnitude
|
||||
// if there is a move input rotate player when the player is moving
|
||||
if (_input.move != Vector2.zero)
|
||||
{
|
||||
_targetRotation = Mathf.Atan2(inputDirection.x, inputDirection.z) * Mathf.Rad2Deg +
|
||||
_mainCamera.transform.eulerAngles.y;
|
||||
float rotation = Mathf.SmoothDampAngle(transform.eulerAngles.y, _targetRotation, ref _rotationVelocity,
|
||||
RotationSmoothTime);
|
||||
|
||||
// rotate to face input direction relative to camera position
|
||||
transform.rotation = Quaternion.Euler(0.0f, rotation, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
Vector3 targetDirection = Quaternion.Euler(0.0f, _targetRotation, 0.0f) * Vector3.forward;
|
||||
|
||||
// move the player
|
||||
_controller.Move(targetDirection.normalized * (_speed * Time.deltaTime) +
|
||||
new Vector3(0.0f, _verticalVelocity, 0.0f) * Time.deltaTime);
|
||||
|
||||
// update animator if using character
|
||||
if (_hasAnimator)
|
||||
{
|
||||
_animator.SetFloat(_animIDSpeed, _animationBlend);
|
||||
_animator.SetFloat(_animIDMotionSpeed, inputMagnitude);
|
||||
}
|
||||
}
|
||||
|
||||
private void JumpAndGravity()
|
||||
{
|
||||
if (Grounded)
|
||||
{
|
||||
// reset the fall timeout timer
|
||||
_fallTimeoutDelta = FallTimeout;
|
||||
|
||||
// update animator if using character
|
||||
if (_hasAnimator)
|
||||
{
|
||||
_animator.SetBool(_animIDJump, false);
|
||||
_animator.SetBool(_animIDFreeFall, false);
|
||||
}
|
||||
|
||||
// stop our velocity dropping infinitely when grounded
|
||||
if (_verticalVelocity < 0.0f)
|
||||
{
|
||||
_verticalVelocity = -2f;
|
||||
}
|
||||
|
||||
// Jump
|
||||
if (_input.jump && _jumpTimeoutDelta <= 0.0f)
|
||||
{
|
||||
// the square root of H * -2 * G = how much velocity needed to reach desired height
|
||||
_verticalVelocity = Mathf.Sqrt(JumpHeight * -2f * Gravity);
|
||||
|
||||
// update animator if using character
|
||||
if (_hasAnimator)
|
||||
{
|
||||
_animator.SetBool(_animIDJump, true);
|
||||
}
|
||||
}
|
||||
|
||||
// jump timeout
|
||||
if (_jumpTimeoutDelta >= 0.0f)
|
||||
{
|
||||
_jumpTimeoutDelta -= Time.deltaTime;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset the jump timeout timer
|
||||
_jumpTimeoutDelta = JumpTimeout;
|
||||
|
||||
// fall timeout
|
||||
if (_fallTimeoutDelta >= 0.0f)
|
||||
{
|
||||
_fallTimeoutDelta -= Time.deltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
// update animator if using character
|
||||
if (_hasAnimator)
|
||||
{
|
||||
_animator.SetBool(_animIDFreeFall, true);
|
||||
}
|
||||
}
|
||||
|
||||
// if we are not grounded, do not jump
|
||||
_input.jump = false;
|
||||
}
|
||||
|
||||
// apply gravity over time if under terminal (multiply by delta time twice to linearly speed up over time)
|
||||
if (_verticalVelocity < _terminalVelocity)
|
||||
{
|
||||
_verticalVelocity += Gravity * Time.deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
private static float ClampAngle(float lfAngle, float lfMin, float lfMax)
|
||||
{
|
||||
if (lfAngle < -360f) lfAngle += 360f;
|
||||
if (lfAngle > 360f) lfAngle -= 360f;
|
||||
return Mathf.Clamp(lfAngle, lfMin, lfMax);
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
Color transparentGreen = new Color(0.0f, 1.0f, 0.0f, 0.35f);
|
||||
Color transparentRed = new Color(1.0f, 0.0f, 0.0f, 0.35f);
|
||||
|
||||
if (Grounded) Gizmos.color = transparentGreen;
|
||||
else Gizmos.color = transparentRed;
|
||||
|
||||
// when selected, draw a gizmo in the position of, and matching radius of, the grounded collider
|
||||
Gizmos.DrawSphere(
|
||||
new Vector3(transform.position.x, transform.position.y - GroundedOffset, transform.position.z),
|
||||
GroundedRadius);
|
||||
}
|
||||
|
||||
private void OnFootstep(AnimationEvent animationEvent)
|
||||
{
|
||||
if (animationEvent.animatorClipInfo.weight > 0.5f)
|
||||
{
|
||||
if (FootstepAudioClips.Length > 0)
|
||||
{
|
||||
var index = Random.Range(0, FootstepAudioClips.Length);
|
||||
AudioSource.PlayClipAtPoint(FootstepAudioClips[index], transform.TransformPoint(_controller.center), FootstepAudioVolume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLand(AnimationEvent animationEvent)
|
||||
{
|
||||
if (animationEvent.animatorClipInfo.weight > 0.5f)
|
||||
{
|
||||
AudioSource.PlayClipAtPoint(LandingAudioClip, transform.TransformPoint(_controller.center), FootstepAudioVolume);
|
||||
}
|
||||
}
|
||||
public void ResetCameraRotation(float targetYaw)
|
||||
{
|
||||
// Reset the yaw and pitch to default values (targetYaw for Y rotation, and 0 for pitch)
|
||||
_cinemachineTargetYaw = targetYaw;
|
||||
_cinemachineTargetPitch = 0f;
|
||||
|
||||
// Reset the camera target's rotation explicitly
|
||||
CinemachineCameraTarget.transform.rotation = Quaternion.Euler(_cinemachineTargetPitch, _cinemachineTargetYaw, 0f);
|
||||
|
||||
Debug.Log($"Camera Yaw reset to {targetYaw} degrees.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26e54e5a728a9234ab24fcf1460ed8a2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
using System; // Required for Type handling
|
||||
|
||||
public class UpdateCollectibleCount : MonoBehaviour
|
||||
{
|
||||
private TextMeshProUGUI collectibleText; // Reference to the TextMeshProUGUI component
|
||||
|
||||
void Start()
|
||||
{
|
||||
collectibleText = GetComponent<TextMeshProUGUI>();
|
||||
if (collectibleText == null)
|
||||
{
|
||||
Debug.LogError("UpdateCollectibleCount script requires a TextMeshProUGUI component on the same GameObject.");
|
||||
return;
|
||||
}
|
||||
UpdateCollectibleDisplay(); // Initial update on start
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
UpdateCollectibleDisplay();
|
||||
}
|
||||
|
||||
private void UpdateCollectibleDisplay()
|
||||
{
|
||||
int totalCollectibles = 0;
|
||||
|
||||
// Check and count objects of type Collectible
|
||||
Type collectibleType = Type.GetType("Collectible");
|
||||
if (collectibleType != null)
|
||||
{
|
||||
#if UNITY_6000_3_OR_NEWER
|
||||
totalCollectibles += FindObjectsByType(collectibleType).Length;
|
||||
#else
|
||||
totalCollectibles += FindObjectsByType(collectibleType, FindObjectsSortMode.None).Length;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Optionally, check and count objects of type Collectible2D as well if needed
|
||||
Type collectible2DType = Type.GetType("Collectible2D");
|
||||
if (collectible2DType != null)
|
||||
{
|
||||
#if UNITY_6000_3_OR_NEWER
|
||||
totalCollectibles += FindObjectsByType(collectible2DType).Length;
|
||||
#else
|
||||
totalCollectibles += FindObjectsByType(collectible2DType, FindObjectsSortMode.None).Length;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Update the collectible count display
|
||||
collectibleText.text = $"Collectibles remaining: {totalCollectibles}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12b990e8d7f314383856263e97f1c328
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user