미로스 - 1.유저캐릭터의 일반적 동작과 전투 동작에 대한 반응요소 설계(예: 전투 모션 등) / 캐릭터 상새 정보창 포함
- 100 powerun
- 2024년 11월 27일
- 3분 분량
최종 수정일: 2월 20일

위는 인게임 에서 확인할 수 있는 플레이어의 스탯창입니다. 스탯창은 Tab키를 통해 여닫을 수 있습니다.

메뉴창을 여닫는 함수로 매번 탭키를 누를 때마다 Managers에서 관리하는 _openMenu의 상태가 매번 바뀌게 됩니다. 이 함수는 메뉴창이 연속적으로 열리거나, 열려있지 않은데에도 열리는 걸 방지해줍니다.

플레이어의 스탯은 PlayerController스크립트 내에 있으며 플레이어 게임 오브젝트 내에 포함되어 있습니다.
플레이어는 기본적으로 스테미너를 가지고 있고, 스테미너는 공격이나 점프와 같은 동작에서 요구되며 만일 스테미너가 없을 시 동작할 수 없게 됩니다. 만약 플레이어가 스테미너가 요구되는 동작을 하면 아래의 코루틴 함수가 작동하며 플레이어의 스테미너를 소모시킨 뒤 일정 시간 후 재생시켜 줍니다.
public void AttackButton()
{
Managers.Object.Player._attack += 5;
_currentGrade++;
Managers.Game.Gold -= _needGold;
_needGold = _currentGrade * 20;
RefreshUI();
}
public void HPButton()
{
Managers.Object.Player._maxHp += 10;
_currentGrade++;
Managers.Game.Gold -= _needGold;
_needGold = _currentGrade * 20;
RefreshUI();
}
public void DefenseButton()
{
Managers.Object.Player._defense += 2;
_currentGrade++;
Managers.Game.Gold -= _needGold;
_needGold = _currentGrade * 20;ur
RefreshUI();
}
public void MoveSpeedButton()
{
// 6.1 -> 61.xxxxx -> 61 ->
Managers.Object.Player._moveSpeed += 0.1f;
Managers.Object.Player._moveSpeed = (float)Math.Round(Managers.Object.Player._moveSpeed, 1);
_currentGrade++;
Managers.Game.Gold -= _needGold;
_needGold = _currentGrade * 20;
RefreshUI();
}
스테이터스 화면을 보면 플레이어의 스탯을 올릴 수 있는 버튼이 존재하는데 위의 함수들을 버튼에 할당시키고 할당된 버튼을 통해 활성화 시켜줍니다.
public void AttackButton()
{
Managers.Object.Player._attack += 5;
_currentGrade++;
Managers.Game.Gold -= _needGold;
_needGold = _currentGrade * 20;
RefreshUI();
}
공격력을 강화시하는 버튼을 예시로 풀어서 설명하자면 Managers 안에 오브젝트로 되어 있는 플레이어의 공격력을 5씩 추가하고 이 게임에서는 다크소울 식의 레벨을 따라가는 구조이기에, 매번 업그래이드마다 요구하는_CurrentGrade가 1씩 늘어나게 됩니다. 필요 골드 사용량의 경우는 동일한 스크립트 내에 존재하는 _needGold만큼 감소시키는데 needGold는 강화가 한번 진행될 때마다 20씩 증가하게 됩니다.
public void RefreshUI()
{
_goldText.text = $"{Managers.Game.Gold}";
_characterStatAttackText.text = $"{Managers.Object.Player._attack}";
_characterStatHpText.text = $"{Managers.Object.Player._maxHp}";
_characterStatDefenseText.text = $"{Managers.Object.Player._defense}";
_characterStatMoveSpeedText.text = $"{Managers.Object.Player._moveSpeed,2}";
_needGoldText.text = $"{_needGold}";
ButtonUpdate();
}
이후 위의 함수를 통해 바뀐 스탯을 실시간으로 확인시키기 위해 정보를 다시 불러오게 합니다.
캐릭터의 공격은 총 3개의 동작으로 이루어집니다.
1타, 2타, 3타로 되여있고 동작은 크게 다른점은 없지만 이팩트에 차별이 존재합니다.
3타를 끝내고 나면 다시 1타부터 다시 시작하게 되고 공격을 계속해서 클릭할 시 스테미너가 다 닮기 전까진 공격을 수행할 수 있습니다.
void OnAttack1Event()
{
GameObject go = Managers.Resource.Instantiate("Particle/Player/Attack1Particle", transform, false);
go.transform.position = transform.position;
go.transform.localScale = new Vector3(transform.localScale.x * go.transform.localScale.x, go.transform.localScale.y, 0);
_stamina -= _staminaDecreaseRate;
UIManager.UI.UI_GameScene.UI_HUD.GetComponent<UI_HUD>().RefreshUI();
}
void OnAttack2Event()
{
GameObject go = Managers.Resource.Instantiate("Particle/Player/Attack2Particle", transform, false);
go.transform.position = transform.position;
go.transform.localScale = new Vector3(transform.localScale.x * go.transform.localScale.x, go.transform.localScale.y, 0);
_stamina -= _staminaDecreaseRate;
UIManager.UI.UI_GameScene.UI_HUD.GetComponent<UI_HUD>().RefreshUI();
}
void OnAttack3Event()
{
GameObject go = Managers.Resource.Instantiate("Particle/Player/Attack3Particle", transform, false);
go.transform.position = transform.position;
go.transform.localScale = new Vector3(transform.localScale.x * go.transform.localScale.x, go.transform.localScale.y, 0);
_stamina -= _staminaDecreaseRate;
UIManager.UI.UI_GameScene.UI_HUD.GetComponent<UI_HUD>().RefreshUI();
}
공격 시 나타나는 이펙트는 위의 함수를 통해 활성화됩니다.
공격 시 에셋 내에 존재하는 파티클의 정보를 불러오고 플레이어의 포지션과 크기에 맞게 위치값과 스케일을 맞춰줍니다. 그리고 공격을 수행할 때마다 UI를 Refresh를 하는데 최적화를 위해 Refresh가 Update내에 존재하는 것이 아닌 특정 상황에서만 움직이게 만들었습니다.
void InputMove()
{
_moveDir = Vector3.zero;
if (Input.GetKey(KeyCode.A))
{
_moveDir = Vector3.left;
transform.localScale = new Vector3(1, 1, 1);
if (_rigid.velocity.normalized.y != 0)
_playerState = Define.PlayerState.Jump;
else
_playerState = Define.PlayerState.Run;
}
else if (Input.GetKey(KeyCode.D))
{
_moveDir = Vector3.right;
transform.localScale = new Vector3(-1, 1, 1);
if (_rigid.velocity.normalized.y != 0)
_playerState = Define.PlayerState.Jump;
else
_playerState = Define.PlayerState.Run;
}
else
{
_playerState = Define.PlayerState.Idle;
}
}
플레이어는 특정 Key 입력 시 이동하게 되고, 이동은 transfrom을 통해 새로운 백터3값을 받아 움직입니다. 만약 플레이어의 정규화 시킨 y값이 증가하게 된다면 점프를 한 것으로 간주하게 됩니다.
void InputJump()
{
if (_isGround && _rigid.velocity.y <= 0) // ground위에 있을때 점프 카운트 초기화
{
_curJumpCount = _maxJumpCount; // _curJumpCount 점프카운트를 _maxJumpCount로 설정
}
if (_curJumpCount > 0 && Input.GetKeyDown(KeyCode.W))
{
_rigid.velocity = Vector2.zero;
_rigid.AddForce(Vector2.up * _jumpForce, ForceMode2D.Impulse);
_curJumpCount--;
_playerState = Define.PlayerState.Jump;
}
}
점프는 총 2단 점프로 구성돼 있습니다.
첫 점프 시 위의 땅에 위치해 있는지 확인하는 bool과 y값이 증가했는지 확인하는 값보다 0이 크거나 같다면 점프 카운트를 초기화시켜 2단 점프를 가능하게 만들고 만약 w가 입력되고 점프 카운트가 남아있다면 AddForce를 통해 점프를 취하게 만든 뒤 점프 카운트를 줄입니다. 만약 여기에서 2번의 점프를 모두 입력했다면 점프는 더 이상 수행할 수 없게 됩니다.
마지막으로 플레이어의 상태를 Jump 상태로 고정시켜줍니다.
Comments