개발일기

[Unity] Elin 본문

Project Review/Unity

[Unity] Elin

김조성준 2024. 4. 27. 22:27

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 색깔을 정하고 색칠하여 만들었습니다.

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