공격 횟수 제한 추가

공중에서 공격 가능한 횟수 밑 대시 횟수 설정했습니다.
This commit is contained in:
백민승_crow 2026-01-27 21:21:34 +09:00
parent 7a232074c1
commit 197b100af0
2 changed files with 143 additions and 212 deletions

View File

@ -135,13 +135,29 @@ PrefabInstance:
propertyPath: m_FlipY propertyPath: m_FlipY
value: 0 value: 0
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 1665208702870125763, guid: ae58a5fa402b1d941b0878d356d1389d, type: 3}
propertyPath: m_Size.x
value: 0.88
objectReference: {fileID: 0}
- target: {fileID: 1888074432508430436, guid: ae58a5fa402b1d941b0878d356d1389d, type: 3} - target: {fileID: 1888074432508430436, guid: ae58a5fa402b1d941b0878d356d1389d, type: 3}
propertyPath: data propertyPath: data
value: value:
objectReference: {fileID: 11400000, guid: a5edb67c4940a4e4692478c7267fc1f8, type: 2} objectReference: {fileID: 11400000, guid: a5edb67c4940a4e4692478c7267fc1f8, type: 2}
- target: {fileID: 2556996269222904179, guid: ae58a5fa402b1d941b0878d356d1389d, type: 3}
propertyPath: m_Constraints
value: 4
objectReference: {fileID: 0}
- target: {fileID: 2556996269222904179, guid: ae58a5fa402b1d941b0878d356d1389d, type: 3}
propertyPath: m_Interpolate
value: 1
objectReference: {fileID: 0}
- target: {fileID: 2556996269222904179, guid: ae58a5fa402b1d941b0878d356d1389d, type: 3} - target: {fileID: 2556996269222904179, guid: ae58a5fa402b1d941b0878d356d1389d, type: 3}
propertyPath: m_GravityScale propertyPath: m_GravityScale
value: 3 value: 6
objectReference: {fileID: 0}
- target: {fileID: 2556996269222904179, guid: ae58a5fa402b1d941b0878d356d1389d, type: 3}
propertyPath: m_CollisionDetection
value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 4539706167822133972, guid: ae58a5fa402b1d941b0878d356d1389d, type: 3} - target: {fileID: 4539706167822133972, guid: ae58a5fa402b1d941b0878d356d1389d, type: 3}
propertyPath: m_LocalPosition.x propertyPath: m_LocalPosition.x
@ -564,28 +580,17 @@ MonoBehaviour:
m_EditorClassIdentifier: Assembly-CSharp::Player m_EditorClassIdentifier: Assembly-CSharp::Player
currentHp: 0 currentHp: 0
maxHp: 10 maxHp: 10
maxJumpCount: 1
moveSpeed: 9 moveSpeed: 9
jumpSpeed: 5 jumpSpeed: 18.7
attackSlowDuration: 0.5
airMoveMultiplier: 0.4
fallSpeedClamp: -3
attackCooldown: 0.4
dashTime: 0.2 dashTime: 0.2
dashDistance: 5 dashDistance: 5
comboAttackSizes: attackBoxSize: {x: 1, y: 1}
- {x: 1.5, y: 1}
- {x: 2, y: 1.5}
- {x: 3, y: 2}
enemyLayer: enemyLayer:
serializedVersion: 2 serializedVersion: 2
m_Bits: 64 m_Bits: 64
obstacleLayer:
serializedVersion: 2
m_Bits: 8
groundLayer: groundLayer:
serializedVersion: 2 serializedVersion: 2
m_Bits: 72 m_Bits: 8
--- !u!1 &1840358743 --- !u!1 &1840358743
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@ -1,5 +1,7 @@
using System.Collections; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine; using UnityEngine;
using UnityEngine.InputSystem; using UnityEngine.InputSystem;
@ -7,85 +9,62 @@ public class Player : MonoBehaviour
{ {
private Rigidbody2D _rigidbody; private Rigidbody2D _rigidbody;
[SerializeField] int currentHp; [SerializeField] private int currentHp;
private int currentJumpCount; [SerializeField] private int maxHp = 10;
private int comboStep;
private Vector2 inputVector;
private bool isGrounded; private bool isGrounded;
private bool isJumpedOnAir = false;
private bool isDashing; private bool isDashing;
private bool isAirAttackSlow;
private bool pendingAirAttackSlow;
private float attackSlowTimer;
private float attackCooldownTimer;
private List<GameObject> dashHitEnemies = new List<GameObject>(); private List<GameObject> dashHitEnemies = new List<GameObject>();
[SerializeField] private int maxHp = 100; [SerializeField] private int maxAttackTime = 3;
[SerializeField] private int maxJumpCount = 1; [SerializeField] private int maxDashTime = 1;
private int currentAttackTime = 0;
private int currentDashTime = 0;
[SerializeField] private float moveSpeed = 9f; [SerializeField] private float moveSpeed = 9f;
[SerializeField] private float jumpSpeed = 18.2f; [SerializeField] private float jumpSpeed = 18.2f;
[SerializeField] private float attackSlowDuration = 0.5f;
[SerializeField] private float airMoveMultiplier = 0.4f;
[SerializeField] private float fallSpeedClamp = -3f;
[SerializeField] private float attackCooldown = 0.4f;
[SerializeField] private float dashTime = 0.5f; [SerializeField] private float dashTime = 0.5f;
[SerializeField] private float dashDistance = 5f; [SerializeField] private float dashDistance = 5f;
[SerializeField] private Vector2[] comboAttackSizes = private Vector2 inputVector;
{
new Vector2(1.5f, 1f), [SerializeField] private Vector2 attackBoxSize = new Vector2(2f, 1f);
new Vector2(2f, 1.5f),
new Vector2(3f, 2f)
};
[SerializeField] private LayerMask enemyLayer; [SerializeField] private LayerMask enemyLayer;
[SerializeField] private LayerMask obstacleLayer;
[SerializeField] private LayerMask groundLayer; [SerializeField] private LayerMask groundLayer;
private void Start() private void Start()
{ {
_rigidbody = GetComponent<Rigidbody2D>(); _rigidbody = gameObject.GetComponent<Rigidbody2D>();
currentHp = maxHp;
currentJumpCount = maxJumpCount;
} }
private void Update() public void Jump()
{ {
if (attackCooldownTimer > 0f) if (isGrounded || !isJumpedOnAir)
attackCooldownTimer -= Time.deltaTime;
if (isAirAttackSlow)
{ {
attackSlowTimer -= Time.deltaTime; if (!isGrounded)
if (attackSlowTimer <= 0f)
{ {
isAirAttackSlow = false; isJumpedOnAir = true;
pendingAirAttackSlow = false;
} }
_rigidbody.linearVelocity = new Vector2(_rigidbody.linearVelocity.x, 0);
_rigidbody.AddForce(Vector2.up * jumpSpeed, ForceMode2D.Impulse);
} }
} }
private void FixedUpdate() public void MoveUpdate()
{ {
if (pendingAirAttackSlow && _rigidbody.linearVelocity.y < 0f) if (!isDashing)
{ {
pendingAirAttackSlow = false; _rigidbody.linearVelocity = new Vector2(inputVector.x * moveSpeed, _rigidbody.linearVelocity.y);
isAirAttackSlow = true;
attackSlowTimer = attackSlowDuration; if (inputVector.x != 0)
} {
transform.localScale = new Vector3(Mathf.Sign(inputVector.x), 1, 1);
if (isAirAttackSlow && _rigidbody.linearVelocity.y < fallSpeedClamp) }
{
_rigidbody.linearVelocity = new Vector2(
_rigidbody.linearVelocity.x,
fallSpeedClamp
);
} }
} }
@ -94,167 +73,114 @@ public class Player : MonoBehaviour
inputVector = value.Get<Vector2>(); inputVector = value.Get<Vector2>();
} }
public void MoveUpdate()
{
if (isDashing) return;
float multiplier = isAirAttackSlow ? airMoveMultiplier : 1f;
_rigidbody.linearVelocity = new Vector2(
inputVector.x * moveSpeed * multiplier,
_rigidbody.linearVelocity.y
);
}
public void Jump()
{
if (currentJumpCount <= 0) return;
currentJumpCount--;
_rigidbody.linearVelocity = new Vector2(_rigidbody.linearVelocity.x, 0f);
_rigidbody.AddForce(Vector2.up * jumpSpeed, ForceMode2D.Impulse);
}
public void NormalAttack() public void NormalAttack()
{ {
if (isDashing) return; if (currentAttackTime < maxAttackTime)
if (attackCooldownTimer > 0f) return;
attackCooldownTimer = attackCooldown;
Vector2 boxSize = comboAttackSizes[comboStep];
float dir = inputVector.x != 0 ? Mathf.Sign(inputVector.x) : Mathf.Sign(transform.localScale.x);
Vector2 origin = (Vector2)transform.position + new Vector2(dir * boxSize.x, 0f);
Collider2D[] enemies = Physics2D.OverlapBoxAll(origin, boxSize, 0f, enemyLayer);
foreach (Collider2D enemy in enemies)
{ {
Vector2 toEnemy = (enemy.transform.position - transform.position).normalized; if (!isGrounded)
float dist = Vector2.Distance(transform.position, enemy.transform.position);
if (!Physics2D.Raycast(transform.position, toEnemy, dist, obstacleLayer))
{ {
enemy.GetComponent<Entity>()?.TakeDamage(10); Debug.Log($"{currentAttackTime + 1} / {maxAttackTime}");
currentAttackTime++;
} }
}
Debug.Log("Attack");
comboStep = (comboStep + 1) % comboAttackSizes.Length; float dir = transform.localScale.x;
Vector2 direction = new Vector2(dir, 0);
if (!isGrounded) Vector2 originPosition = (Vector2)transform.position + (direction * 1);
{
if (_rigidbody.linearVelocity.y < 0f) Collider2D[] enemise = Physics2D.OverlapBoxAll(originPosition, attackBoxSize, 0, enemyLayer);
if (enemise.Length > 0)
{ {
isAirAttackSlow = true; foreach (Collider2D enemy in enemise)
attackSlowTimer = attackSlowDuration; {
} enemy.gameObject.GetComponent<Entity>().TakeDamage(10);
else }
{ }
pendingAirAttackSlow = true;
}
} }
} }
public void DashAttack()
{
if (isDashing) return;
StartCoroutine(DashPlayerRoutine());
}
private IEnumerator DashPlayerRoutine()
{
isDashing = true;
isAirAttackSlow = false;
pendingAirAttackSlow = false;
attackSlowTimer = 0f;
attackCooldownTimer = 0f;
_rigidbody.linearVelocity = Vector2.zero;
dashHitEnemies.Clear();
Vector2 direction = inputVector.normalized;
if (direction == Vector2.zero)
direction = new Vector2(Mathf.Sign(transform.localScale.x), 0f);
if (isGrounded && direction.y < 0)
direction.y = 0f;
Vector2 startPos = _rigidbody.position;
Vector2 targetPos = startPos + direction * dashDistance;
float timer = 0f;
while (timer < dashTime)
{
timer += Time.deltaTime;
float t = timer / dashTime;
_rigidbody.MovePosition(Vector2.Lerp(startPos, targetPos, t));
yield return null;
}
isDashing = false;
}
public void AttackOnDash(Collider2D collision)
{
if ((enemyLayer.value & (1 << collision.gameObject.layer)) == 0) return;
if (dashHitEnemies.Contains(collision.gameObject)) return;
dashHitEnemies.Add(collision.gameObject);
collision.GetComponent<Entity>()?.TakeDamage(10);
}
public void CheckGround() public void CheckGround()
{ {
isGrounded = Physics2D.Raycast(transform.position, Vector2.down, 1.25f, groundLayer); isGrounded = Physics2D.Raycast(transform.position, Vector2.down, 1.25f, groundLayer);
if (isGrounded) if (isGrounded)
{ {
currentJumpCount = maxJumpCount; isJumpedOnAir = false;
isAirAttackSlow = false; currentAttackTime = 0;
pendingAirAttackSlow = false; currentDashTime = 0;
attackSlowTimer = 0f;
} }
} }
public void Heal(int value) public void DashAttack()
{ {
if (value <= 0) return; if (isDashing) return;
if (currentDashTime < maxDashTime)
currentHp += value;
if (currentHp > maxHp)
currentHp = maxHp;
}
public void TakeDamage(int damage)
{
currentHp -= damage;
if (currentHp <= 0)
Destroy(gameObject);
}
public bool IsDashing()
{
return isDashing;
}
private void OnDrawGizmos()
{
if (comboAttackSizes == null || comboAttackSizes.Length == 0) return;
Gizmos.color = Color.red;
int stepIndex = (comboStep < comboAttackSizes.Length) ? comboStep : 0;
Vector2 boxSize = comboAttackSizes[stepIndex];
float dir = Mathf.Sign(transform.localScale.x);
if (Application.isPlaying && inputVector.x != 0)
{ {
dir = Mathf.Sign(inputVector.x); currentDashTime++;
StartCoroutine(DashPlayerRoutine());
}
}
private IEnumerator DashPlayerRoutine()
{
isDashing = true;
_rigidbody.linearVelocity = Vector2.zero;
dashHitEnemies.Clear();
Vector2 direction = inputVector.normalized;
if (direction == Vector2.zero)
{
direction = new Vector2(transform.localScale.x, 0);
} }
Vector2 origin = (Vector2)transform.position + new Vector2(dir * boxSize.x, 0f); if (isGrounded && direction.y < 0)
Gizmos.DrawWireCube(origin, boxSize); {
direction.y = 0;
if (direction.x != 0) direction.x = Mathf.Sign(direction.x);
}
Vector2 startPos = _rigidbody.position;
Vector2 targetPos = startPos + (direction.normalized * dashDistance);
float dashTimer = 0f;
while (dashTimer < dashTime)
{
dashTimer += Time.deltaTime;
float t = dashTimer / dashTime;
_rigidbody.MovePosition(Vector2.Lerp(startPos, targetPos, t));
yield return null;
}
isDashing = false;
} }
}
public void AttackOnDash(Collider2D collision)
{
if ((enemyLayer.value & (1 << collision.gameObject.layer)) > 0)
{
if (!dashHitEnemies.Contains(collision.gameObject))
{
dashHitEnemies.Add(collision.gameObject);
collision.gameObject.GetComponent<Entity>().TakeDamage(10);
}
}
}
public bool IsDashing() { return isDashing; }
public void Heal(int heal)
{
if (heal < 0) return;
currentHp += heal;
if (currentHp > maxHp) currentHp = maxHp;
}
public void TakeDamage(int playerAttackDamage)
{
currentHp -= playerAttackDamage;
if (currentHp <= 0)
{
currentHp = 0;
Destroy(gameObject);
}
}
}