개발일기
[Unity] Elin 본문
1. Link
깃허브 주소 : https://github.com/kimchosungjun/Remake_Elin.git
GitHub - kimchosungjun/Remake_Elin
Contribute to kimchosungjun/Remake_Elin development by creating an account on GitHub.
github.com
플레이 영상 : https://www.youtube.com/watch?v=uvz9pNH-8NE
2. 구현한 기능
1) 플레이어 조작 (좌/우 이동, 점프, 구르기, 벽 점프)
플레이의 행동을 구현하기 위해 상태머신을 만들었습니다. 플레이어의 상태는 현재 상태에 들어올때 실행되는 Enter, 현재 상태를 유지할 때 계속 실행되는 Update, 현재 상태를 탈출하는 Exit 메서드로 구성되어 있으며, 플레이어의 상태를 관리하는 StateMachine과 Controller 그리고 Rigidbody에 대한 정보를 받는 생성자를 선언하였습니다.
public class PlayerState
{
protected PlayerStateMachine stateMachine;
protected PlayerController player;
protected Rigidbody2D rb;
protected float xInput;
private string animBoolName;
protected float stateTimer=0.4f;
public PlayerState(PlayerController _player, PlayerStateMachine _stateMachine, string _animBoolName)
{
this.player = _player;
this.stateMachine = _stateMachine;
this.animBoolName = _animBoolName;
rb = player.rb;
}
public virtual void Enter() { player.anim.SetBool(animBoolName, true); }
public virtual void Exit() { player.anim.SetBool(animBoolName, false); }
public virtual void Update()
{
stateTimer -= Time.deltaTime;
if (player.CanMove)
xInput = Input.GetAxisRaw("Horizontal");
else
xInput = 0;
player.anim.SetFloat("yVelocity", rb.velocity.y);
}
}
플레이어의 상태를 초기화하거나 변경시킬 때 호출하는 상태머신은 다음과 같이 작성했습니다.
public class PlayerStateMachine
{
public PlayerState currentState { get; private set; }
public void Initialize(PlayerState _startState)
{
currentState = _startState;
currentState.Enter();
}
public void ChangeState(PlayerState _changeState)
{
currentState.Exit();
currentState = _changeState;
currentState.Enter();
}
}
위에서 선언한 상태와 상태머신을 PlayerController에 선언하여 관리합니다.
// PlayerController의 Awake
void Awake()
{
stateMachine = new PlayerStateMachine();
state = new PlayerState[(int)PlayerStateNames.Max + 1];
state[(int)PlayerStateNames.Idle] = new PlayerIdleState(this, stateMachine, "Idle");
state[(int)PlayerStateNames.Move] = new PlayerMoveState(this, stateMachine, "Move");
state[(int)PlayerStateNames.Jump] = new PlayerJumpState(this, stateMachine, "Jump");
state[(int)PlayerStateNames.Air] = new PlayerAirState(this, stateMachine, "Jump");
state[(int)PlayerStateNames.Roll] = new PlayerRollState(this, stateMachine, "Roll");
state[(int)PlayerStateNames.Wall] = new PlayerWallState(this, stateMachine, "Wall");
state[(int)PlayerStateNames.WallJump] = new PlayerWallJumpState(this, stateMachine, "Jump");
}
// 각 상태마다 PlayerState를 상속받는 상태를 작성 (PlayerGroundState는 PlayerState의 자식)
public class PlayerIdleState : PlayerGroundState
{
public PlayerIdleState(PlayerController _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName) { }
public override void Enter()
{
base.Enter();
}
public override void Exit()
{
base.Exit();
}
public override void Update()
{
base.Update();
player.SetVelocity(xInput * player.moveSpeed, rb.velocity.y);
if (xInput != 0)
stateMachine.ChangeState(player.state[(int)PlayerStateNames.Move]);
}
}
상태머신에서 상태를 변경할때, Enter와 Exit에 해당 상태 애니메이션에 대한 진입과 탈출을 관리합니다.
상태에 진입할 때, 해당 상태에 대한 애니메이션을 True로 설정하여 실행하고 반대로 탈출할 땐 False로 설정하여 종료.

2) Yarn Spinner를 이용한 대화 시스템 구현
Dialogue Runner에 다음과 같이 메서드를 연결시키면 대화 도중에 이벤트를 발생시킬 수 있습니다.
public DialogueRunner runner;
public void Init()
{
runner = GameObject.FindWithTag("Runner").GetComponent<DialogueRunner>();
runner.onDialogueStart.AddListener(() => { CloseAllUI(); });
runner.onDialogueComplete.AddListener(() => { GameManager.PlayerM.ControllPlayer(true); OpenAllUI(); });
runner.AddCommandHandler<string>("StartConversation", StartConversation);
}
public void StartConversation(string _dialogueName)
{
if (runner.IsDialogueRunning)
return;
GameManager.PlayerM.ControllPlayer(false);
runner.StartDialogue(_dialogueName);
}
Yarn Spinner는 아래 텍스트와 같은 형식의 대화 파일을 만들면 대화를 실행 할 수 있습니다.
Dialogue Runner에 추가한 Event는 <<"메서드이름",매개변수>>를 통해 호출합니다.
title: TutorialHuman
tags:
---
?? : (아무것도 보이지 않는다.. 여기는 어디지??)
덜그럭 덜그럭 거리던 소리가 멈춘다..
인간B : 자 이제 일해보자고.
인간A : 오케이! 얼른 해치우고 퇴근하자고.
쾅..! 쾅..! (우지끈..)
?? : (윽.. )
인간A : 매일 이 많은 슬라임들이 어디서 나오는걸까?
인간B : 나도 잘은 모르지만, 들리는 소문이 있어.
인간A : 소문??
인간B : 왕가에서 비밀리에 하는 실험이 있다는데.. 그 실험의 부산물이라더군.
인간A : 흠.. 어떤 실험인지는 모르겠지만, 좀만 적당히 했으면 좋겠구만.
인간B : 그렇긴해. 매일 이렇게 버리는것도 힘들어.
둔탁한 소리가 멎는다..
인간B : 이제 어느정도 마무리 된거 같은데 퇴근하고 밥먹으러 가시게나.
인간A : 오늘 저녁은 뭘 먹는게 좋을거 같나??
인간들의 목소리가 멀어져간다.
<<IsFadeIn true>>
===
3) 디자인
Piskel을 이용하여 직접 캐릭터를 도트로 찍어봤습니다. 아트 직군이 아니기에 세세한 표현을 하기 힘들어 2~3 프레임만 변하도록 도트를 찍어봤습니다.


UI는 포토샵을 이용하여 도형을 그리고 색조합을 참고하여 UI 색깔을 정하고 색칠하여 만들었습니다.

'Project Review > Unity' 카테고리의 다른 글
[Unity] 2D Shooting (0) | 2025.05.14 |
---|---|
[Unity] IDEAL 중간 빌드 (0) | 2024.05.13 |
[Unity] Tower Defence (0) | 2024.04.22 |
[Unity] Toy Rush (0) | 2023.10.16 |