
오늘 학습 키워드
최종 팀 프로젝트
오늘 학습 한 내용을 나만의 언어로 정리하기
섬단에 큰 문제가 생김
-
섬단이 벽을 뚫어버림;
-
시도 1 - 이전위치를 기억해서 그것과의 거리가 너무 짧으면 그냥 Idle로 넘기게 함
public void LogicUpdate(PlayerController player)
{
animRunningTime += Time.deltaTime;
float t = animRunningTime / attackAnimationLength;
if (animRunningTime > 0.2f)
{
prePos = curPos;
curPos = player.transform.position;
if (Vector2.Distance(prePos, curPos) < 0.001f)
{
player.PlayerMove.rb.velocity = Vector2.zero;
if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();
else player.ChangeState<FallState>();
return;
}
}
// 선형 보간하는 포지션을 만들어서 거기로 MovePosition
Vector2 newPos = Vector2.MoveTowards(startPos, targetPos, t * specialAttackSpeed);
player.PlayerMove.rb.MovePosition(newPos);
/*if (player.PlayerMove.isWallTouched)
{ player.PlayerMove.rb.velocity = Vector2.zero; if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>(); else player.ChangeState<FallState>(); return; }*/
if (Vector2.Distance(newPos, targetPos) < 0.01f)
{
player.PlayerMove.rb.velocity = Vector2.zero;
if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();
else player.ChangeState<FallState>();
return;
}
if (Time.time - startStateTime > startAttackTime)
{
AnimatorStateInfo curAnimInfo = player.PlayerAnimator.animator.GetCurrentAnimatorStateInfo(0);
if (curAnimInfo.IsName("SpecialAttack"))
{
float animTime = curAnimInfo.normalizedTime;
if (animTime >= 1.0f)
{
if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();
else player.ChangeState<FallState>();
return;
}
}
if (animRunningTime >= attackAnimationLength)
{
if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();
else player.ChangeState<FallState>();
return;
}
}
}-
시도 1 : 실패!
-
시도 2 : (챗지피티의 도움) 이동하려는 위치로 선을 그어서 벽에 닿으면 그 직전까지만 움직이게
public void LogicUpdate(PlayerController player)
{
animRunningTime += Time.deltaTime;
float t = animRunningTime / attackAnimationLength;
Vector2 newPos = Vector2.MoveTowards(startPos, targetPos, t * specialAttackSpeed);
curPos = player.transform.position;
Vector2 direction = (newPos - curPos).normalized;
float distance = Vector2.Distance(curPos, newPos);
RaycastHit2D hit =
Physics2D.Raycast(player.transform.position, direction, distance, player.PlayerMove.groundMask);
if (hit.collider != null)
{
player.PlayerMove.rb.MovePosition(hit.point - direction * 0.01f);
if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();
else player.ChangeState<FallState>();
return;
}
// 선형 보간하는 포지션을 만들어서 거기로 MovePosition player.PlayerMove.rb.MovePosition(newPos);
if (Vector2.Distance(newPos, targetPos) < 0.01f)
{
player.PlayerMove.rb.velocity = Vector2.zero;
if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();
else player.ChangeState<FallState>();
return;
}
if (Time.time - startStateTime > startAttackTime)
{
AnimatorStateInfo curAnimInfo = player.PlayerAnimator.animator.GetCurrentAnimatorStateInfo(0);
if (curAnimInfo.IsName("SpecialAttack"))
{
float animTime = curAnimInfo.normalizedTime;
if (animTime >= 1.0f)
{
if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();
else player.ChangeState<FallState>();
return;
}
}
if (animRunningTime >= attackAnimationLength)
{
if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();
else player.ChangeState<FallState>();
return;
}
}
}- 시도 2 : 성공!
패링 만들기

// AttackHitbox.cs
private void OnTriggerEnter2D(Collider2D other)
{
if (Player.PlayerAttack.isStartParry)
{
if (other.TryGetComponent(out ICountable countable))
{
Player.PlayerAttack.successParry = true;
countable?.CounterAttacked();
Debug.Log("플레이어 패링 성공");
}
return;
}
if (other.TryGetComponent<IDamagable>(out var damagable)
&& other.gameObject.layer == LayerMask.NameToLayer("Monster"))
{
damagable?.TakeDamage(Damage);
Debug.Log($"플레이어가 몬스터에게 {Damage} 만큼 데미지 줌");
}
}점프가 뭔가 어색함.
- AddForce로 하다 보니까 뭔가 어색한 문제가 있었음
- 그래서 MovePosition으로 해보는게 어떨까 라는 생각이 들어서 기존의 Jump 코드를 바꿔봄
public class JumpState : AirSubState
{
private float minWallHoldTime = 1f; // 이 초가 지나야 벽 짚기가 가능함
private float elapsedTime;
private float jumpAnimationLength;
private float jumpSpeed = 1.2f;
private float jumpDistance = 4f;
private Vector2 startPos;
private Vector2 targetPos;
private Vector2 newPos;
private Vector2 curPos;
private float t;
public override void Enter(PlayerController player)
{
base.Enter(player);
var moveInput = player.Inputs.Player.Move.ReadValue<Vector2>();
player.PlayerAnimator.SetTriggerAnimation(PlayerAnimID.Jump);
player.isLookLocked = true;
elapsedTime = 0f;
jumpAnimationLength =
player.PlayerAnimator.animator.runtimeAnimatorController
.animationClips.First(c => c.name == "Jump").length;
startPos = player.transform.position;
if (moveInput.x == 0)
{
targetPos = startPos + (Vector2.up * jumpDistance);
}
else
{
targetPos = startPos + ((new Vector2((moveInput.x < 0) ? -1f : 1f, 1f)).normalized * jumpDistance);
}
if (!player.PlayerMove.isGroundJump) player.PlayerMove.isGroundJump = true;
}
public override void HandleInput(PlayerController player)
{
elapsedTime += Time.deltaTime;
var moveInput = player.Inputs.Player.Move.ReadValue<Vector2>();
if (player.Inputs.Player.Jump.triggered)
{
if(!player.PlayerMove.isDoubleJump)
{
player.ChangeState<DoubleJumpState>();
return;
}
}
if (player.PlayerMove.isWallTouched && elapsedTime >= minWallHoldTime)
{
player.ChangeState<WallHoldState>();
return;
}
if (player.Inputs.Player.NormalAttack.triggered && moveInput.y < 0)
{
player.isLookLocked = true;
player.ChangeState<DownAttackState>();
return;
}
if (player.Inputs.Player.NormalAttack.triggered && !player.PlayerAttack.HasJumpAttack)
{
player.isLookLocked = true;
player.ChangeState<NormalJumpAttackState>();
return;
}
if (player.Inputs.Player.SpecialAttack.triggered)
{
player.isLookLocked = false;
player.ChangeState<SpecialAttackState>();
return;
}
if (player.Inputs.Player.Dodge.triggered)
{
player.ChangeState<DodgeState>();
return;
}
if (player.Inputs.Player.Parry.triggered)
{
player.ChangeState<StartParryState>();
return;
}
}
public override void LogicUpdate(PlayerController player)
{
t = elapsedTime / jumpAnimationLength;
newPos = Vector2.Lerp(startPos, targetPos, t * jumpSpeed);
curPos = player.transform.position;
// 현재 위치에서 이동할 위치만큼 선 하나 그어서, 그게 벽에 닿으면 벽 끝에까지만 가고 상태 바뀌게함
Vector2 direction = (newPos - curPos).normalized;
float distance = Vector2.Distance(curPos, newPos);
RaycastHit2D hit =
Physics2D.Raycast(player.transform.position, direction, distance, player.PlayerMove.groundMask);
if (hit.collider != null)
{
player.PlayerMove.rb.MovePosition(hit.point - direction * 0.01f);
player.ChangeState<FallState>();
return;
}
player.PlayerMove.rb.MovePosition(newPos);
if (Vector2.Distance(newPos, targetPos) < 0.01f)
{
player.PlayerMove.rb.velocity = Vector2.zero;
player.ChangeState<FallState>();
return;
}
if (!player.PlayerMove.isGroundJump)
{
player.PlayerMove.isGroundJump = true;
return;
}
player.PlayerMove.Move();
if (player.PlayerMove.rb.velocity.y < 0)
{
player.ChangeState<FallState>();
return;
}
}
public override void Exit(PlayerController player)
{
base.Exit(player);
player.isLookLocked = false;
}
}- 이랬더니 1단 점프는 자연스러운데 2단 점프는 어색함. (2단 점프도 이렇게 바꿨음)
- 그래서 2단 점프만 AddForce를 해볼까 고민 중
- 그러다가 그냥 1-2단 점프는 AddForce를 하고 벽점프를 바꿔보기로 함
// WallJumpState.cs
public class WallJumpState : AirSubState
{
private float wallJumpStartTime;
private float wallHoldAbleTime = 0.5f;
private float startFallTime = 0.2f;
private float animRunningTime = 0f;
private float wallJumpAnimationLength;
private float wallJumpSpeed = 5f;
private float wallJumpDistance = 8f;
private Vector2 wallJumpDirection;
private Vector2 startPos;
private Vector2 targetPos;
private Vector2 newPos;
private Vector2 curPos;
private float t;
public override void Enter(PlayerController player)
{
base.Enter(player);
// Debug.Log("벽점!");
// 벽점할 때에는 벽 반대방향 봐야됨
player.PlayerMove.ForceLook(!player.PlayerMove.lastWallIsLeft);
player.isLookLocked = true;
// 벽점했으니까 강제로 벽 터치 취소
player.PlayerAnimator.ClearBool(); // WallHold 끄려고
player.PlayerMove.isWallTouched = false;
player.PlayerAnimator.SetTriggerAnimation(PlayerAnimID.WallJump);
wallJumpStartTime = Time.time;
animRunningTime = 0f;
/*player.PlayerMove.WallJump();*/
wallJumpAnimationLength =
player.PlayerAnimator.animator.runtimeAnimatorController
.animationClips.First(c => c.name == "WallJump").length;
wallJumpDirection = new Vector2((player.PlayerMove.lastWallIsLeft ? 1.5f : -1.5f),1f).normalized;
startPos = player.transform.position;
targetPos = startPos + (wallJumpDirection * wallJumpDistance);
}
public override void HandleInput(PlayerController player)
{
//if (player.Inputs.Player.Move.ReadValue<Vector2>().x != 0)
//{ // player.PlayerMove.Move(); // return; //}
var moveInputs = player.Inputs.Player.Move.ReadValue<Vector2>();
if (player.Inputs.Player.Jump.triggered && !player.PlayerMove.isDoubleJump)
{
player.ChangeState<DoubleJumpState>();
return;
}
if(Time.time - wallJumpStartTime > wallHoldAbleTime && player.PlayerMove.isWallTouched)
{
player.ChangeState<WallHoldState>();
return;
}
else
{
player.PlayerMove.isWallTouched = false;
}
if (player.Inputs.Player.NormalAttack.triggered && moveInputs.y < 0)
{
player.isLookLocked = true;
player.ChangeState<DownAttackState>();
return;
}
if (player.Inputs.Player.NormalAttack.triggered && !player.PlayerAttack.HasJumpAttack)
{
player.isLookLocked = true;
player.ChangeState<NormalJumpAttackState>();
return;
}
if (player.Inputs.Player.SpecialAttack.triggered)
{
player.isLookLocked = false;
player.ChangeState<SpecialAttackState>();
return;
}
if (player.Inputs.Player.Dodge.triggered)
{
player.ChangeState<DodgeState>();
return;
}
}
public override void LogicUpdate(PlayerController player)
{
animRunningTime += Time.deltaTime;
t = animRunningTime / wallJumpAnimationLength;
newPos = Vector2.Lerp(startPos, targetPos, t);
curPos = player.transform.position;
// 현재 위치에서 이동할 위치만큼 선 하나 그어서, 그게 벽에 닿으면 벽 끝에까지만 가고 상태 바뀌게함
Vector2 direction = (newPos - curPos).normalized;
float distance = Vector2.Distance(curPos, newPos);
RaycastHit2D hit =
Physics2D.Raycast(player.transform.position, direction, distance, player.PlayerMove.groundMask);
if (hit.collider != null)
{
player.PlayerMove.rb.MovePosition(hit.point - direction * 0.01f);
if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();
else player.ChangeState<FallState>();
return;
}
player.PlayerMove.rb.MovePosition(newPos);
if (Vector2.Distance(newPos, targetPos) < 0.01f)
{
player.PlayerMove.rb.velocity = Vector2.zero;
if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();
else player.ChangeState<FallState>();
return;
}
/*
if (animRunningTime >= startFallTime) { if (player.PlayerMove.rb.velocity.y < 0) { player.ChangeState<FallState>(); return; } }*/
if (player.PlayerMove.isGrounded)
{
player.ChangeState<IdleState>();
return;
}
}
public override void Exit(PlayerController player)
{
base.Exit(player);
player.isLookLocked = false;
}
}학습하며 겪었던 문제점 & 에러
문제 1
- 문제&에러에 대한 정의
분명 클래스를 만들었는데 라이더에서 인식을 못하고 자동완성도 안되는 사태가 있었다
- 해결 방법
Preference > Registry Packages + Player Projects 체크 > Regenerate Project Files 했더니 해결됨