Bugfixes
This commit is contained in:
@@ -157,7 +157,7 @@ public class GameManager : MonoBehaviour
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
//return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,14 @@ public class HatRespawn : MonoBehaviour
|
||||
public const float respawnTime = 10f;
|
||||
private bool isDropped;
|
||||
|
||||
public Vector2 initialSubhatPosition;
|
||||
|
||||
|
||||
public static bool canBePickedUp = true; // Flag to check if the hat can be picked up
|
||||
|
||||
void Start()
|
||||
{
|
||||
initialSubhatPosition = transform.GetChild(0).transform.localPosition;
|
||||
lastInteractionTime = Time.time;
|
||||
isDropped = false;
|
||||
transform.position = GameManager.Instance.hatSpawnPositions[Random.Range(0, GameManager.Instance.hatSpawnPositions.Count - 1)];
|
||||
|
||||
@@ -1,145 +1,214 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine; using Game; using Music; using Player;
|
||||
using UnityEngine;
|
||||
using Game;
|
||||
using Music;
|
||||
using Player;
|
||||
namespace Player
|
||||
{
|
||||
|
||||
[RequireComponent(typeof(Rigidbody2D))]
|
||||
[RequireComponent(typeof(Collider2D))]
|
||||
[RequireComponent(typeof(RespawnOnTriggerEnter))]
|
||||
public class Damageable : MonoBehaviour
|
||||
{
|
||||
public float force = 50f; // Force applied when hit
|
||||
public float damage = 0f;
|
||||
public float maxDamage = 1000f; // Set max health
|
||||
public int lives = 0;
|
||||
private Animator animator;
|
||||
public bool damageSelfDebug = false;
|
||||
public bool dying = false;
|
||||
public event System.Action<GameObject> OnPlayerPunched;
|
||||
|
||||
private void Start()
|
||||
[RequireComponent(typeof(Rigidbody2D))]
|
||||
[RequireComponent(typeof(Collider2D))]
|
||||
[RequireComponent(typeof(RespawnOnTriggerEnter))]
|
||||
public class Damageable : MonoBehaviour
|
||||
{
|
||||
animator = GetComponent<Animator>();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (damageSelfDebug)
|
||||
/// <summary>
|
||||
/// The force applied to the player when hit.
|
||||
/// </summary>
|
||||
public float force = 50f; // Force applied when hit
|
||||
|
||||
/// <summary>
|
||||
/// The current accumulated damage of the player.
|
||||
/// </summary>
|
||||
public float damage = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum damage the player can take before dying.
|
||||
/// </summary>
|
||||
public float maxDamage = 1000f; // Set max health
|
||||
|
||||
/// <summary>
|
||||
/// The number of lives the player has.
|
||||
/// </summary>
|
||||
public int lives = 0;
|
||||
|
||||
private Animator animator;
|
||||
|
||||
/// <summary>
|
||||
/// If true, applies damage to self for debugging purposes.
|
||||
/// </summary>
|
||||
public bool damageSelfDebug = false;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the player is currently dying.
|
||||
/// </summary>
|
||||
public bool dying = false;
|
||||
|
||||
/// <summary>
|
||||
/// Event triggered when the player is punched.
|
||||
/// </summary>
|
||||
public event System.Action<GameObject> OnPlayerPunched;
|
||||
|
||||
/// <summary>
|
||||
/// Unity Start method. Initializes the animator reference.
|
||||
/// </summary>
|
||||
private void Start()
|
||||
{
|
||||
damageSelfDebug = false;
|
||||
Damage(gameObject);
|
||||
animator = GetComponent<Animator>();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTriggerEnter2D(Collider2D collision) // Calls Damage method when player is hit
|
||||
{
|
||||
if (collision.gameObject.CompareTag("Punch Hurtbox"))
|
||||
/// <summary>
|
||||
/// Unity Update method. Handles debug self-damage if enabled.
|
||||
/// </summary>
|
||||
private void Update()
|
||||
{
|
||||
Damage(collision.transform.parent.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void Damage(GameObject damageSource) // Damages player
|
||||
{
|
||||
if (dying || damageSource.CompareTag("Hat")) return; // Exclude hat from taking damage
|
||||
|
||||
float actualForce = damageSource.GetComponent<Damageable>().force;
|
||||
Block blockComponent = GetComponent<Block>();
|
||||
|
||||
GetComponentInChildren<UseItem>().DropItem(); // Drops hat if held
|
||||
|
||||
if (blockComponent != null && blockComponent.blocking)
|
||||
{
|
||||
if (blockComponent.IsParrying()) // Player receives damage if punching a parrying player
|
||||
if (damageSelfDebug)
|
||||
{
|
||||
damageSource.GetComponent<Damageable>().SuccessfulParry(gameObject, actualForce);
|
||||
AudioManager.Instance.PlaySound("Parry");
|
||||
return;
|
||||
damageSelfDebug = false;
|
||||
Damage(gameObject);
|
||||
}
|
||||
else // Player does less damage if punching a blocking player
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unity OnTriggerEnter2D method. Applies damage when colliding with a punch hurtbox.
|
||||
/// </summary>
|
||||
/// <param name="collision">The collider that entered the trigger.</param>
|
||||
private void OnTriggerEnter2D(Collider2D collision)
|
||||
{
|
||||
if (collision.gameObject.CompareTag("Punch Hurtbox"))
|
||||
{
|
||||
Damage(collision.transform.parent.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies damage to the player from a given damage source.
|
||||
/// Handles blocking, parrying, and force application.
|
||||
/// </summary>
|
||||
/// <param name="damageSource">The GameObject causing the damage.</param>
|
||||
private void Damage(GameObject damageSource)
|
||||
{
|
||||
if (dying || damageSource.CompareTag("Hat")) return; // Exclude hat from taking damage
|
||||
|
||||
float actualForce = damageSource.GetComponent<Damageable>().force;
|
||||
Block blockComponent = GetComponent<Block>();
|
||||
|
||||
GetComponentInChildren<UseItem>().DropItem(); // Drops hat if held
|
||||
|
||||
if (blockComponent != null && blockComponent.blocking)
|
||||
{
|
||||
if (blockComponent.IsParrying()) // Player receives damage if punching a parrying player
|
||||
{
|
||||
damageSource.GetComponent<Damageable>().SuccessfulParry(gameObject, actualForce);
|
||||
AudioManager.Instance.PlaySound("Parry");
|
||||
return;
|
||||
}
|
||||
else // Player does less damage if punching a blocking player
|
||||
{
|
||||
AudioManager.Instance.PlaySound("Punch");
|
||||
actualForce /= 4;
|
||||
GetComponent<Rigidbody2D>().AddForce(((transform.position - damageSource.transform.position).normalized + Vector3.up * 2) * actualForce, ForceMode2D.Force);
|
||||
}
|
||||
}
|
||||
else // Player does full damage to a non-blocking player
|
||||
{
|
||||
AudioManager.Instance.PlaySound("Punch");
|
||||
actualForce /= 4;
|
||||
GetComponent<Rigidbody2D>().AddForce(((transform.position - damageSource.transform.position).normalized + Vector3.up * 2) * actualForce, ForceMode2D.Force);
|
||||
GetComponent<Rigidbody2D>().AddForce(((transform.position - damageSource.transform.position).normalized + Vector3.up * 2) * actualForce * (1 + (damage / maxDamage) * 3), ForceMode2D.Force);
|
||||
}
|
||||
}
|
||||
else // Player does full damage to a non-blocking player
|
||||
{
|
||||
AudioManager.Instance.PlaySound("Punch");
|
||||
GetComponent<Rigidbody2D>().AddForce(((transform.position - damageSource.transform.position).normalized + Vector3.up * 2) * actualForce * (1 + (damage / maxDamage) * 3), ForceMode2D.Force);
|
||||
}
|
||||
damage += actualForce;
|
||||
damage = Mathf.Clamp(damage, 0f, maxDamage);
|
||||
if (damage >= maxDamage)
|
||||
{
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
public void Damage(float damage) // Adds damage to player when hit
|
||||
{
|
||||
//if (GameManager.Instance.gameOver) return; // Prevent damage after game is over
|
||||
|
||||
this.damage += damage;
|
||||
if (damage >= maxDamage)
|
||||
{
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
private void SuccessfulParry(GameObject damageSource, float force)
|
||||
{
|
||||
GetComponent<Rigidbody2D>().AddForce(((transform.position - damageSource.transform.position).normalized + Vector3.up * 2) * force, ForceMode2D.Force);
|
||||
damage += force;
|
||||
damage = Mathf.Clamp(damage, 0f, maxDamage);
|
||||
|
||||
if (damage >= maxDamage)
|
||||
{
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
private void Die() // Triggers death animation and sets player to dying state
|
||||
{
|
||||
if (GameManager.Instance != null && !GameManager.Instance.gameOver) // Prevent death after game is over
|
||||
{
|
||||
UseItem useItem = GetComponent<UseItem>();
|
||||
if (useItem != null)
|
||||
damage += actualForce;
|
||||
damage = Mathf.Clamp(damage, 0f, maxDamage);
|
||||
if (damage >= maxDamage)
|
||||
{
|
||||
useItem.DropItem(); // Ensure the player drops the item before the death animation
|
||||
Die();
|
||||
}
|
||||
animator.SetBool("die", true);
|
||||
dying = true;
|
||||
|
||||
AudioManager.Instance.PlaySound("Death Simple");
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleDeath() // Removes player from dying state after respawn
|
||||
{
|
||||
GameManager.Instance.PlayerDied(this);
|
||||
animator.SetBool("die", false);
|
||||
dying = false;
|
||||
}
|
||||
|
||||
public void Respawn() // Respawns player to the spawnPosition and resets damage/health bar
|
||||
{
|
||||
transform.position = GameManager.Instance.spawnPosition;
|
||||
if (TryGetComponent<Rigidbody2D>(out var rb))
|
||||
/// <summary>
|
||||
/// Adds a specified amount of damage to the player.
|
||||
/// </summary>
|
||||
/// <param name="damage">The amount of damage to add.</param>
|
||||
public void Damage(float damage)
|
||||
{
|
||||
rb.linearVelocity = Vector2.zero;
|
||||
rb.angularVelocity = 0f;
|
||||
}
|
||||
if (TryGetComponent<Damageable>(out var damageable))
|
||||
{
|
||||
damageable.ResetDamage();
|
||||
}
|
||||
}
|
||||
//if (GameManager.Instance.gameOver) return; // Prevent damage after game is over
|
||||
|
||||
public void ResetDamage()
|
||||
{
|
||||
damage = 0f;
|
||||
this.damage += damage;
|
||||
if (damage >= maxDamage)
|
||||
{
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the effects of a successful parry, applying force and damage.
|
||||
/// </summary>
|
||||
/// <param name="damageSource">The GameObject that was parried.</param>
|
||||
/// <param name="force">The force to apply.</param>
|
||||
private void SuccessfulParry(GameObject damageSource, float force)
|
||||
{
|
||||
GetComponent<Rigidbody2D>().AddForce(((transform.position - damageSource.transform.position).normalized + Vector3.up * 2) * force, ForceMode2D.Force);
|
||||
damage += force;
|
||||
damage = Mathf.Clamp(damage, 0f, maxDamage);
|
||||
|
||||
if (damage >= maxDamage)
|
||||
{
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the death animation and sets the player to the dying state.
|
||||
/// </summary>
|
||||
private void Die()
|
||||
{
|
||||
if (GameManager.Instance != null) //&& !GameManager.Instance.gameOver) // Prevent death after game is over
|
||||
{
|
||||
UseItem useItem = GetComponent<UseItem>();
|
||||
if (useItem != null)
|
||||
{
|
||||
useItem.DropItem(); // Ensure the player drops the item before the death animation
|
||||
}
|
||||
animator.SetBool("die", true);
|
||||
dying = true;
|
||||
|
||||
AudioManager.Instance.PlaySound("Death Simple");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles player state after death and resets dying state after respawn.
|
||||
/// </summary>
|
||||
public void HandleDeath()
|
||||
{
|
||||
print("Player " + gameObject.name + " died");
|
||||
GameManager.Instance.PlayerDied(this);
|
||||
animator.SetBool("die", false);
|
||||
dying = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Respawns the player at the spawn position and resets damage/health bar.
|
||||
/// </summary>
|
||||
public void Respawn()
|
||||
{
|
||||
transform.position = GameManager.Instance.spawnPosition;
|
||||
if (TryGetComponent<Rigidbody2D>(out var rb))
|
||||
{
|
||||
rb.linearVelocity = Vector2.zero;
|
||||
rb.angularVelocity = 0f;
|
||||
}
|
||||
if (TryGetComponent<Damageable>(out var damageable))
|
||||
{
|
||||
damageable.ResetDamage();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the player's damage to zero.
|
||||
/// </summary>
|
||||
public void ResetDamage()
|
||||
{
|
||||
damage = 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,262 +1,432 @@
|
||||
using System.Collections;
|
||||
using TMPro;
|
||||
using Unity.IO.LowLevel.Unsafe;
|
||||
using UnityEngine; using Game; using Music; using Player;
|
||||
using UnityEngine;
|
||||
using Game;
|
||||
using Music;
|
||||
using Player;
|
||||
using UnityEngine.InputSystem;
|
||||
namespace Player
|
||||
{
|
||||
|
||||
[RequireComponent(typeof(Rigidbody2D))]
|
||||
[RequireComponent(typeof(BoxCollider2D))]
|
||||
[RequireComponent(typeof(PlayerInput))]
|
||||
[RequireComponent(typeof(AnimationPlayer))]
|
||||
[RequireComponent(typeof(Punch))]
|
||||
public class PlayerMovement : MonoBehaviour
|
||||
{
|
||||
[Header("Ground Layers")]
|
||||
public LayerMask ground;
|
||||
|
||||
public TextMeshProUGUI playerText;
|
||||
|
||||
[Header("Movement")]
|
||||
public float walkSpeed;
|
||||
public float walkSpeedFactor = 1f; // Sets walk speed
|
||||
public float maxSpeed = 5f; // Sets max speed
|
||||
public float maxSpeedOverride;
|
||||
public float slowdownMultiplier = 10f; // Sets slow walk speed
|
||||
public float virtualAxisX;
|
||||
public float virtualButtonJump;
|
||||
public float virtualButtonJumpLastFrame;
|
||||
public float turnaroundMultiplier = 2; // Sets speed when turning around
|
||||
public float walkSmooth;
|
||||
public float secondsToFullSpeed;
|
||||
public float jumpSpeed;
|
||||
public float coyoteTime;
|
||||
public float jumpLenience;
|
||||
public float timeUnableToBeDeclaredNotJumping = 0.1f; // Jump threshold
|
||||
public float groundCheckDistance;
|
||||
|
||||
private Rigidbody2D body;
|
||||
private BoxCollider2D collide;
|
||||
private PlayerInput input;
|
||||
private AnimationPlayer animationPlayer;
|
||||
private Punch punch;
|
||||
private Damageable damageable;
|
||||
|
||||
private bool jumpInputStillValid = false;
|
||||
private bool canBeDeclaredNotJumping = true;
|
||||
private bool jumpPhysics;
|
||||
private bool jumping;
|
||||
private float lastTimeJumpPressed;
|
||||
private float lastTimeOnGround;
|
||||
|
||||
private Vector3 positionLastFrame;
|
||||
|
||||
void Start() // Sets up player components
|
||||
[RequireComponent(typeof(Rigidbody2D))]
|
||||
[RequireComponent(typeof(BoxCollider2D))]
|
||||
[RequireComponent(typeof(PlayerInput))]
|
||||
[RequireComponent(typeof(AnimationPlayer))]
|
||||
[RequireComponent(typeof(Punch))]
|
||||
public class PlayerMovement : MonoBehaviour
|
||||
{
|
||||
maxSpeedOverride = maxSpeed;
|
||||
GetComponent<RespawnOnTriggerEnter>().spawnPoint = transform.position;
|
||||
|
||||
body = GetComponent<Rigidbody2D>();
|
||||
collide = GetComponent<BoxCollider2D>();
|
||||
input = GetComponent<PlayerInput>();
|
||||
animationPlayer = GetComponent<AnimationPlayer>();
|
||||
punch = GetComponent<Punch>();
|
||||
damageable = GetComponent<Damageable>();
|
||||
/// <summary>
|
||||
/// Layers considered as ground for the player.
|
||||
/// </summary>
|
||||
[Header("Ground Layers")]
|
||||
public LayerMask ground;
|
||||
|
||||
playerText.text = input.playerIndex.ToString();
|
||||
}
|
||||
/// <summary>
|
||||
/// Reference to the player's UI text displaying player index.
|
||||
/// </summary>
|
||||
public TextMeshProUGUI playerText;
|
||||
|
||||
private void Update() // Updates player movement
|
||||
{
|
||||
if (GameManager.Instance != null && GameManager.Instance.gameOver) maxSpeed = 1f;
|
||||
if (damageable.dying) return;
|
||||
/// <summary>
|
||||
/// Base walk speed of the player.
|
||||
/// </summary>
|
||||
[Header("Movement")]
|
||||
public float walkSpeed;
|
||||
|
||||
Jump();
|
||||
/// <summary>
|
||||
/// Multiplier applied to walk speed.
|
||||
/// </summary>
|
||||
public float walkSpeedFactor = 1f;
|
||||
|
||||
UpdateVirtualAxis();
|
||||
}
|
||||
/// <summary>
|
||||
/// Maximum allowed horizontal speed for the player.
|
||||
/// </summary>
|
||||
public float maxSpeed = 5f;
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
JumpPhysics();
|
||||
/// <summary>
|
||||
/// Runtime override for the maximum speed.
|
||||
/// </summary>
|
||||
public float maxSpeedOverride;
|
||||
|
||||
HorizontalMovement();
|
||||
/// <summary>
|
||||
/// Multiplier for slowing down the player when exceeding max speed.
|
||||
/// </summary>
|
||||
public float slowdownMultiplier = 10f;
|
||||
|
||||
Land();
|
||||
}
|
||||
/// <summary>
|
||||
/// Current value of the horizontal movement axis.
|
||||
/// </summary>
|
||||
public float virtualAxisX;
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
Animate();
|
||||
}
|
||||
/// <summary>
|
||||
/// Current value of the jump button (pressed or not).
|
||||
/// </summary>
|
||||
public float virtualButtonJump;
|
||||
|
||||
private void Animate() // Sets player animation
|
||||
{
|
||||
if (!IsPhysicallyGrounded())
|
||||
animationPlayer.SetState(AnimationPlayer.AnimationState.Jump);
|
||||
else
|
||||
/// <summary>
|
||||
/// Value of the jump button in the previous frame.
|
||||
/// </summary>
|
||||
public float virtualButtonJumpLastFrame;
|
||||
|
||||
/// <summary>
|
||||
/// Multiplier applied when turning around to adjust speed.
|
||||
/// </summary>
|
||||
public float turnaroundMultiplier = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Smoothing factor for walking movement.
|
||||
/// </summary>
|
||||
public float walkSmooth;
|
||||
|
||||
/// <summary>
|
||||
/// Time in seconds to reach full speed from rest.
|
||||
/// </summary>
|
||||
public float secondsToFullSpeed;
|
||||
|
||||
/// <summary>
|
||||
/// Force applied when jumping.
|
||||
/// </summary>
|
||||
public float jumpSpeed;
|
||||
|
||||
/// <summary>
|
||||
/// Time window after leaving ground where jump is still allowed (coyote time).
|
||||
/// </summary>
|
||||
public float coyoteTime;
|
||||
|
||||
/// <summary>
|
||||
/// Time window after pressing jump where jump is still buffered.
|
||||
/// </summary>
|
||||
public float jumpLenience;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum time before the player can be declared as not jumping.
|
||||
/// </summary>
|
||||
public float timeUnableToBeDeclaredNotJumping = 0.1f;
|
||||
|
||||
/// <summary>
|
||||
/// Distance to check below the player for ground detection.
|
||||
/// </summary>
|
||||
public float groundCheckDistance;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the Rigidbody2D component.
|
||||
/// </summary>
|
||||
private Rigidbody2D body;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the BoxCollider2D component.
|
||||
/// </summary>
|
||||
private BoxCollider2D collide;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the PlayerInput component.
|
||||
/// </summary>
|
||||
private PlayerInput input;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the AnimationPlayer component.
|
||||
/// </summary>
|
||||
private AnimationPlayer animationPlayer;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the Punch component.
|
||||
/// </summary>
|
||||
private Punch punch;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the Damageable component.
|
||||
/// </summary>
|
||||
private Damageable damageable;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the jump input is still valid for buffered jumps.
|
||||
/// </summary>
|
||||
private bool jumpInputStillValid = false;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the player can be declared as not jumping.
|
||||
/// </summary>
|
||||
private bool canBeDeclaredNotJumping = true;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if jump physics should be applied this frame.
|
||||
/// </summary>
|
||||
private bool jumpPhysics;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the player is currently jumping.
|
||||
/// </summary>
|
||||
private bool jumping;
|
||||
|
||||
/// <summary>
|
||||
/// The last time the jump button was pressed.
|
||||
/// </summary>
|
||||
private float lastTimeJumpPressed;
|
||||
|
||||
/// <summary>
|
||||
/// The last time the player was on the ground.
|
||||
/// </summary>
|
||||
private float lastTimeOnGround;
|
||||
|
||||
/// <summary>
|
||||
/// The player's position in the previous frame.
|
||||
/// </summary>
|
||||
private Vector3 positionLastFrame;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes player components and sets up initial values.
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
if (Mathf.Abs(virtualAxisX) >= 0.05f)
|
||||
animationPlayer.SetState(GameManager.Instance.gameOver ? AnimationPlayer.AnimationState.Walk : AnimationPlayer.AnimationState.Run);
|
||||
maxSpeedOverride = maxSpeed;
|
||||
GetComponent<RespawnOnTriggerEnter>().spawnPoint = transform.position;
|
||||
|
||||
body = GetComponent<Rigidbody2D>();
|
||||
collide = GetComponent<BoxCollider2D>();
|
||||
input = GetComponent<PlayerInput>();
|
||||
animationPlayer = GetComponent<AnimationPlayer>();
|
||||
punch = GetComponent<Punch>();
|
||||
damageable = GetComponent<Damageable>();
|
||||
|
||||
playerText.text = input.playerIndex.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles per-frame updates for player movement and jump input.
|
||||
/// </summary>
|
||||
private void Update()
|
||||
{
|
||||
if (GameManager.Instance != null && GameManager.Instance.gameOver) maxSpeed = 1f;
|
||||
UpdateVirtualAxis();
|
||||
if (damageable.dying) return;
|
||||
Jump();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles physics-based updates for jumping and horizontal movement.
|
||||
/// </summary>
|
||||
private void FixedUpdate()
|
||||
{
|
||||
JumpPhysics();
|
||||
HorizontalMovement();
|
||||
Land();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles late frame updates, such as animation.
|
||||
/// </summary>
|
||||
private void LateUpdate()
|
||||
{
|
||||
Animate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the player's animation state based on movement and grounded status.
|
||||
/// </summary>
|
||||
private void Animate()
|
||||
{
|
||||
if (!IsPhysicallyGrounded())
|
||||
animationPlayer.SetState(AnimationPlayer.AnimationState.Jump);
|
||||
else
|
||||
animationPlayer.SetState(AnimationPlayer.AnimationState.Idle);
|
||||
}
|
||||
|
||||
if (true)
|
||||
{
|
||||
if (virtualAxisX < -0.01f)
|
||||
animationPlayer.backwards = true;
|
||||
else if (virtualAxisX > 0.01f)
|
||||
animationPlayer.backwards = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (body.linearVelocityX < -0.1f)
|
||||
animationPlayer.backwards = true;
|
||||
else if (body.linearVelocityX > 0.1f)
|
||||
animationPlayer.backwards = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void Land() // Stops jumping when player lands
|
||||
{
|
||||
if (body.linearVelocity.y >= 0f) return;
|
||||
|
||||
if (IsPhysicallyGrounded())
|
||||
{
|
||||
if (canBeDeclaredNotJumping)
|
||||
{
|
||||
jumping = false;
|
||||
if (Mathf.Abs(virtualAxisX) >= 0.05f)
|
||||
animationPlayer.SetState(GameManager.Instance.gameOver ? AnimationPlayer.AnimationState.Walk : AnimationPlayer.AnimationState.Run);
|
||||
else
|
||||
animationPlayer.SetState(AnimationPlayer.AnimationState.Idle);
|
||||
}
|
||||
|
||||
if (true)
|
||||
{
|
||||
if (virtualAxisX < -0.01f)
|
||||
animationPlayer.backwards = true;
|
||||
else if (virtualAxisX > 0.01f)
|
||||
animationPlayer.backwards = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (body.linearVelocityX < -0.1f)
|
||||
animationPlayer.backwards = true;
|
||||
else if (body.linearVelocityX > 0.1f)
|
||||
animationPlayer.backwards = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Jump() // Player jumps when 'jump' is pressed
|
||||
{
|
||||
if (virtualButtonJumpLastFrame == 1f)
|
||||
/// <summary>
|
||||
/// Handles logic for landing and stopping the jump state when grounded.
|
||||
/// </summary>
|
||||
private void Land()
|
||||
{
|
||||
jumpInputStillValid = true;
|
||||
lastTimeJumpPressed = Time.time;
|
||||
}
|
||||
if (body.linearVelocity.y >= 0f) return;
|
||||
|
||||
bool isBasicallyGrounded = IsBasicallyGrounded();
|
||||
if ((virtualButtonJumpLastFrame == 1f && isBasicallyGrounded && jumping == false) // Coyote Jump: Must have jump pressed this frame and be grounded in last time frame and not be actually jumping.
|
||||
|| (jumpInputStillValid && Time.time - lastTimeJumpPressed <= jumpLenience && IsPhysicallyGrounded())) // Buffered Jump: Must have pressed jump in the last time frame and be jumping
|
||||
{
|
||||
AudioManager.Instance.PlaySound("Jump");
|
||||
jumpPhysics = true;
|
||||
jumping = true;
|
||||
jumpInputStillValid = false;
|
||||
StartCoroutine(NotJumpingDelay());
|
||||
}
|
||||
}
|
||||
|
||||
private void JumpPhysics() // Applies jump physics
|
||||
{
|
||||
if (jumpPhysics)
|
||||
{
|
||||
if (!GetComponent<Block>().blocking)
|
||||
if (IsPhysicallyGrounded())
|
||||
{
|
||||
if (body.linearVelocity.y < 0 || !IsPhysicallyGrounded()) body.linearVelocity = new Vector2(body.linearVelocity.x, 0);
|
||||
body.AddForce(Vector2.up * jumpSpeed, ForceMode2D.Impulse);
|
||||
if (Mathf.Abs(body.linearVelocityX) > maxSpeed)
|
||||
if (canBeDeclaredNotJumping)
|
||||
{
|
||||
body.linearVelocity = new Vector2(Mathf.Sign(body.linearVelocityX) * maxSpeed, body.linearVelocity.y);
|
||||
jumping = false;
|
||||
}
|
||||
}
|
||||
jumpPhysics = false;
|
||||
}
|
||||
|
||||
if (!IsPhysicallyGrounded() && !(virtualButtonJump == 1f))
|
||||
body.AddForce(Vector2.down * jumpSpeed);
|
||||
}
|
||||
|
||||
private IEnumerator NotJumpingDelay() // Sets jump threshold
|
||||
{
|
||||
canBeDeclaredNotJumping = false;
|
||||
yield return new WaitUntil(() => !IsBasicallyGrounded());
|
||||
canBeDeclaredNotJumping = true;
|
||||
}
|
||||
|
||||
private void HorizontalMovement() // Sets player horizontal movement
|
||||
{
|
||||
float temporaryMax = IsPhysicallyGrounded() ? maxSpeedOverride : Mathf.Infinity;
|
||||
float temporarySlowdown = IsPhysicallyGrounded() ? slowdownMultiplier : 1;
|
||||
|
||||
if (!GetComponent<Block>().blocking && (Mathf.Abs(body.linearVelocityX) <= maxSpeed || Mathf.Sign(body.linearVelocityX) != Mathf.Sign(virtualAxisX)))
|
||||
/// <summary>
|
||||
/// Handles jump input and determines if a jump should be triggered.
|
||||
/// </summary>
|
||||
private void Jump()
|
||||
{
|
||||
body.AddForce(new Vector2(virtualAxisX * walkSpeed * walkSpeedFactor, 0), ForceMode2D.Force);
|
||||
if (virtualButtonJumpLastFrame == 1f)
|
||||
{
|
||||
jumpInputStillValid = true;
|
||||
lastTimeJumpPressed = Time.time;
|
||||
}
|
||||
|
||||
bool isBasicallyGrounded = IsBasicallyGrounded();
|
||||
if ((virtualButtonJumpLastFrame == 1f && isBasicallyGrounded && jumping == false)
|
||||
|| (jumpInputStillValid && Time.time - lastTimeJumpPressed <= jumpLenience && IsPhysicallyGrounded()))
|
||||
{
|
||||
AudioManager.Instance.PlaySound("Jump");
|
||||
jumpPhysics = true;
|
||||
jumping = true;
|
||||
jumpInputStillValid = false;
|
||||
StartCoroutine(NotJumpingDelay());
|
||||
}
|
||||
}
|
||||
|
||||
if (Mathf.Abs(body.linearVelocityX) >= temporaryMax)
|
||||
/// <summary>
|
||||
/// Applies jump physics and forces to the player.
|
||||
/// </summary>
|
||||
private void JumpPhysics()
|
||||
{
|
||||
body.AddForce(new Vector2(-Mathf.Sign(body.linearVelocityX) * (Mathf.Abs(body.linearVelocityX) - temporaryMax) * temporarySlowdown, 0));
|
||||
if (jumpPhysics)
|
||||
{
|
||||
if (!GetComponent<Block>().blocking)
|
||||
{
|
||||
if (body.linearVelocity.y < 0 || !IsPhysicallyGrounded()) body.linearVelocity = new Vector2(body.linearVelocity.x, 0);
|
||||
body.AddForce(Vector2.up * jumpSpeed, ForceMode2D.Impulse);
|
||||
if (Mathf.Abs(body.linearVelocityX) > maxSpeed)
|
||||
{
|
||||
body.linearVelocity = new Vector2(Mathf.Sign(body.linearVelocityX) * maxSpeed, body.linearVelocity.y);
|
||||
}
|
||||
}
|
||||
jumpPhysics = false;
|
||||
}
|
||||
|
||||
if (!IsPhysicallyGrounded() && !(virtualButtonJump == 1f))
|
||||
body.AddForce(Vector2.down * jumpSpeed);
|
||||
}
|
||||
|
||||
if (transform.position == positionLastFrame && (input.actions.FindAction("Move").ReadValue<Vector2>().x == 0))
|
||||
/// <summary>
|
||||
/// Coroutine that delays the ability to declare the player as not jumping.
|
||||
/// </summary>
|
||||
private IEnumerator NotJumpingDelay()
|
||||
{
|
||||
virtualAxisX = 0;
|
||||
canBeDeclaredNotJumping = false;
|
||||
yield return new WaitUntil(() => !IsBasicallyGrounded());
|
||||
canBeDeclaredNotJumping = true;
|
||||
}
|
||||
|
||||
if (GetComponent<Block>().blocking)
|
||||
/// <summary>
|
||||
/// Handles horizontal movement, including acceleration, deceleration, and blocking.
|
||||
/// </summary>
|
||||
private void HorizontalMovement()
|
||||
{
|
||||
body.AddForce(new Vector2(-body.linearVelocityX * 0.8f, 0), ForceMode2D.Force);
|
||||
float temporaryMax = IsPhysicallyGrounded() ? maxSpeedOverride : Mathf.Infinity;
|
||||
float temporarySlowdown = IsPhysicallyGrounded() ? slowdownMultiplier : 1;
|
||||
|
||||
if (!GetComponent<Block>().blocking && (Mathf.Abs(body.linearVelocityX) <= maxSpeed || Mathf.Sign(body.linearVelocityX) != Mathf.Sign(virtualAxisX)))
|
||||
{
|
||||
body.AddForce(new Vector2(virtualAxisX * walkSpeed * walkSpeedFactor, 0), ForceMode2D.Force);
|
||||
}
|
||||
|
||||
if (Mathf.Abs(body.linearVelocityX) >= temporaryMax)
|
||||
{
|
||||
body.AddForce(new Vector2(-Mathf.Sign(body.linearVelocityX) * (Mathf.Abs(body.linearVelocityX) - temporaryMax) * temporarySlowdown, 0));
|
||||
}
|
||||
|
||||
if (transform.position == positionLastFrame && (input.actions.FindAction("Move").ReadValue<Vector2>().x == 0))
|
||||
{
|
||||
virtualAxisX = 0;
|
||||
}
|
||||
|
||||
if (GetComponent<Block>().blocking)
|
||||
{
|
||||
body.AddForce(new Vector2(-body.linearVelocityX * 0.8f, 0), ForceMode2D.Force);
|
||||
}
|
||||
|
||||
positionLastFrame = transform.position;
|
||||
}
|
||||
|
||||
positionLastFrame = transform.position;
|
||||
}
|
||||
|
||||
private void UpdateVirtualAxis() // Updates virtual axis
|
||||
{
|
||||
virtualButtonJump = input.actions.FindAction("Action").ReadValue<float>();
|
||||
virtualButtonJumpLastFrame = input.actions.FindAction("Action").WasPressedThisFrame() ? 1 : 0;
|
||||
|
||||
virtualAxisX = input.actions.FindAction("Move").ReadValue<Vector2>().x;
|
||||
return;
|
||||
}
|
||||
|
||||
public bool IsBasicallyGrounded() // Checks if player is on land within a threshold
|
||||
{
|
||||
if (IsPhysicallyGrounded())
|
||||
/// <summary>
|
||||
/// Updates the virtual axis and button values from input actions.
|
||||
/// </summary>
|
||||
private void UpdateVirtualAxis()
|
||||
{
|
||||
lastTimeOnGround = Time.time;
|
||||
virtualButtonJump = input.actions.FindAction("Action").ReadValue<float>();
|
||||
virtualButtonJumpLastFrame = input.actions.FindAction("Action").WasPressedThisFrame() ? 1 : 0;
|
||||
|
||||
virtualAxisX = input.actions.FindAction("Move").ReadValue<Vector2>().x;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Time.time - lastTimeOnGround < coyoteTime)
|
||||
/// <summary>
|
||||
/// Checks if the player is considered grounded, including coyote time.
|
||||
/// </summary>
|
||||
/// <returns>True if the player is basically grounded, otherwise false.</returns>
|
||||
public bool IsBasicallyGrounded()
|
||||
{
|
||||
return true;
|
||||
if (IsPhysicallyGrounded())
|
||||
{
|
||||
lastTimeOnGround = Time.time;
|
||||
}
|
||||
|
||||
if (Time.time - lastTimeOnGround < coyoteTime)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsPhysicallyGrounded() // Checks if player is on land
|
||||
{
|
||||
RaycastHit2D leftCheck = Physics2D.Raycast(GetPointInBoxCollider(collide, -1, -1), Vector2.down, groundCheckDistance, ground);
|
||||
RaycastHit2D rightCheck = Physics2D.Raycast(GetPointInBoxCollider(collide, 1, -1), Vector2.down, groundCheckDistance, ground);
|
||||
RaycastHit2D midCheck = Physics2D.Raycast(GetPointInBoxCollider(collide, 0, -1), Vector2.down, groundCheckDistance, ground);
|
||||
|
||||
if (leftCheck || rightCheck || midCheck)
|
||||
/// <summary>
|
||||
/// Checks if the player is physically touching the ground using raycasts.
|
||||
/// </summary>
|
||||
/// <returns>True if the player is physically grounded, otherwise false.</returns>
|
||||
public bool IsPhysicallyGrounded()
|
||||
{
|
||||
return true;
|
||||
RaycastHit2D leftCheck = Physics2D.Raycast(GetPointInBoxCollider(collide, -1, -1), Vector2.down, groundCheckDistance, ground);
|
||||
RaycastHit2D rightCheck = Physics2D.Raycast(GetPointInBoxCollider(collide, 1, -1), Vector2.down, groundCheckDistance, ground);
|
||||
RaycastHit2D midCheck = Physics2D.Raycast(GetPointInBoxCollider(collide, 0, -1), Vector2.down, groundCheckDistance, ground);
|
||||
|
||||
if (leftCheck || rightCheck || midCheck)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets a point on the BoxCollider2D based on horizontal and vertical multipliers.
|
||||
/// </summary>
|
||||
/// <param name="boxCollider2D">The BoxCollider2D to use.</param>
|
||||
/// <param name="horizontal">Horizontal offset (-1 for left, 1 for right, 0 for center).</param>
|
||||
/// <param name="vertical">Vertical offset (-1 for bottom, 1 for top, 0 for center).</param>
|
||||
/// <returns>The calculated point in world space.</returns>
|
||||
public Vector2 GetPointInBoxCollider(BoxCollider2D boxCollider2D, float horizontal, float vertical)
|
||||
{
|
||||
return new Vector2
|
||||
(
|
||||
boxCollider2D.bounds.center.x + (horizontal * boxCollider2D.bounds.extents.x),
|
||||
boxCollider2D.bounds.center.y + (vertical * boxCollider2D.bounds.extents.y)
|
||||
);
|
||||
}
|
||||
|
||||
public Vector2 GetPointInBoxCollider(BoxCollider2D boxCollider2D, float horizontal, float vertical)
|
||||
{
|
||||
return new Vector2
|
||||
(
|
||||
boxCollider2D.bounds.center.x + (horizontal * boxCollider2D.bounds.extents.x),
|
||||
boxCollider2D.bounds.center.y + (vertical * boxCollider2D.bounds.extents.y)
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Stops the player's velocity if grounded, removing inertia.
|
||||
/// </summary>
|
||||
public void StopVelocity()
|
||||
{
|
||||
if (IsPhysicallyGrounded()) body.linearVelocity = Vector2.zero;
|
||||
}
|
||||
|
||||
public void StopVelocity() // Stops inertia when landed
|
||||
{
|
||||
if (IsPhysicallyGrounded()) body.linearVelocity = Vector2.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,101 +1,105 @@
|
||||
using System.Collections;
|
||||
using UnityEngine; using Game; using Music; using Player;
|
||||
using UnityEngine;
|
||||
using Game;
|
||||
using Music;
|
||||
using Player;
|
||||
namespace Player
|
||||
{
|
||||
|
||||
public class UseItem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private string itemTag;
|
||||
private GameObject heldItem;
|
||||
private bool isHoldingItem = false;
|
||||
private float holdStartTime;
|
||||
public float holdTime;
|
||||
private Damageable damageable;
|
||||
|
||||
[SerializeField] public Transform head;
|
||||
|
||||
private void Start()
|
||||
public class UseItem : MonoBehaviour
|
||||
{
|
||||
damageable = GetComponent<Damageable>();
|
||||
}
|
||||
[SerializeField] private string itemTag;
|
||||
private GameObject heldItem;
|
||||
private bool isHoldingItem = false;
|
||||
private float holdStartTime;
|
||||
public float holdTime;
|
||||
private Damageable damageable;
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (isHoldingItem)
|
||||
[SerializeField] public Transform head;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Keeps hat on the player's head
|
||||
heldItem.transform.localPosition = Vector3.zero;
|
||||
if (GameManager.gameMode == GameManager.GameMode.keepAway)
|
||||
damageable = GetComponent<Damageable>();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (isHoldingItem)
|
||||
{
|
||||
// Adds time to the player's leaderboard standing
|
||||
holdTime += Time.deltaTime;
|
||||
GameManager.Instance.UpdatePlayerHoldTime(gameObject, holdTime);
|
||||
// Keeps hat on the player's head
|
||||
heldItem.transform.localPosition = Vector3.zero;
|
||||
if (GameManager.gameMode == GameManager.GameMode.keepAway)
|
||||
{
|
||||
// Adds time to the player's leaderboard standing
|
||||
holdTime += Time.deltaTime;
|
||||
GameManager.Instance.UpdatePlayerHoldTime(gameObject, holdTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCollisionEnter2D(Collision2D collision) // Player automatically picks up hat when touching it
|
||||
{
|
||||
if (collision.gameObject.CompareTag("Hat") && !isHoldingItem && !damageable.dying)
|
||||
private void OnCollisionEnter2D(Collision2D collision) // Player automatically picks up hat when touching it
|
||||
{
|
||||
PickUpItem(collision.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public void PickUpItem(GameObject item) // Player picks up hat and starts hold counter
|
||||
{
|
||||
if (damageable.dying) return; // Prevent picking up items if the player is dying
|
||||
if (HatRespawn.canBePickedUp == false) return; // Prevent picking up items if they are not interactable
|
||||
|
||||
heldItem = item;
|
||||
isHoldingItem = true;
|
||||
holdStartTime = Time.time;
|
||||
item.GetComponent<Collider2D>().enabled = false;
|
||||
item.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Static;
|
||||
item.GetComponent<HatRespawn>().Interact();
|
||||
item.transform.parent = head;
|
||||
item.transform.localRotation = Quaternion.identity;
|
||||
item.transform.localPosition = Vector3.zero;
|
||||
if (!GameManager.playerHoldTimes.ContainsKey(gameObject))
|
||||
{
|
||||
GameManager.playerHoldTimes[gameObject] = 0f;
|
||||
}
|
||||
AudioManager.Instance.PlaySound("Pickup Hat");
|
||||
GameManager.Instance.StopCoroutine("MoveHatToWinner");
|
||||
}
|
||||
|
||||
public void DropItem() // Player drops hat when hit
|
||||
{
|
||||
if (GameManager.Instance.gameOver) return; // Prevent dropping items if the game is over
|
||||
|
||||
if (isHoldingItem)
|
||||
{
|
||||
heldItem.GetComponent<Collider2D>().enabled = true;
|
||||
HatRespawn.canBePickedUp = false;
|
||||
StartCoroutine(WaitForInteractability());
|
||||
heldItem.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Dynamic;
|
||||
heldItem.GetComponent<Rigidbody2D>().AddForce(Vector2.up * Random.Range(10f, 30f) + Vector2.right * Random.Range(-10, 10), ForceMode2D.Impulse);
|
||||
heldItem.GetComponent<Rigidbody2D>().AddTorque(Random.Range(-5, 5), ForceMode2D.Impulse);
|
||||
heldItem.GetComponent<HatRespawn>().OnHatDropped();
|
||||
heldItem.transform.parent = GameManager.Instance.transform;
|
||||
heldItem = null;
|
||||
isHoldingItem = false;
|
||||
if (GameManager.playerHoldTimes.ContainsKey(gameObject))
|
||||
if (collision.gameObject.CompareTag("Hat") && !isHoldingItem && !damageable.dying)
|
||||
{
|
||||
GameManager.playerHoldTimes.Remove(gameObject);
|
||||
PickUpItem(collision.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator WaitForInteractability()
|
||||
{
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
HatRespawn.canBePickedUp = true;
|
||||
}
|
||||
public void PickUpItem(GameObject item) // Player picks up hat and starts hold counter
|
||||
{
|
||||
if (damageable.dying) return; // Prevent picking up items if the player is dying
|
||||
if (HatRespawn.canBePickedUp == false) return; // Prevent picking up items if they are not interactable
|
||||
|
||||
public bool IsHoldingItem()
|
||||
{
|
||||
return isHoldingItem;
|
||||
heldItem = item;
|
||||
isHoldingItem = true;
|
||||
holdStartTime = Time.time;
|
||||
item.GetComponent<Collider2D>().enabled = false;
|
||||
item.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Static;
|
||||
item.GetComponent<HatRespawn>().Interact();
|
||||
item.transform.parent = head;
|
||||
item.transform.localRotation = Quaternion.identity;
|
||||
item.transform.localPosition = Vector3.zero;
|
||||
item.transform.GetChild(0).transform.localPosition = item.GetComponent<HatRespawn>().initialSubhatPosition;
|
||||
if (!GameManager.playerHoldTimes.ContainsKey(gameObject))
|
||||
{
|
||||
GameManager.playerHoldTimes[gameObject] = 0f;
|
||||
}
|
||||
AudioManager.Instance.PlaySound("Pickup Hat");
|
||||
GameManager.Instance.StopCoroutine("MoveHatToWinner");
|
||||
}
|
||||
|
||||
public void DropItem() // Player drops hat when hit
|
||||
{
|
||||
if (GameManager.Instance.gameOver) return; // Prevent dropping items if the game is over
|
||||
|
||||
if (isHoldingItem)
|
||||
{
|
||||
heldItem.GetComponent<Collider2D>().enabled = true;
|
||||
HatRespawn.canBePickedUp = false;
|
||||
StartCoroutine(WaitForInteractability());
|
||||
heldItem.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Dynamic;
|
||||
heldItem.GetComponent<Rigidbody2D>().AddForce(Vector2.up * Random.Range(10f, 30f) + Vector2.right * Random.Range(-10, 10), ForceMode2D.Impulse);
|
||||
heldItem.GetComponent<Rigidbody2D>().AddTorque(Random.Range(-5, 5), ForceMode2D.Impulse);
|
||||
heldItem.GetComponent<HatRespawn>().OnHatDropped();
|
||||
heldItem.transform.parent = GameManager.Instance.transform;
|
||||
heldItem = null;
|
||||
isHoldingItem = false;
|
||||
if (GameManager.playerHoldTimes.ContainsKey(gameObject))
|
||||
{
|
||||
GameManager.playerHoldTimes.Remove(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator WaitForInteractability()
|
||||
{
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
HatRespawn.canBePickedUp = true;
|
||||
}
|
||||
|
||||
public bool IsHoldingItem()
|
||||
{
|
||||
return isHoldingItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user