유니티/게임 프로젝트

간단한 2D RPG 프로젝트 - (1) BaseController

monstro 2024. 11. 20. 17:12
728x90
반응형

이번 포스트에서는 유니티 엔진을 사용하여 간단한 2D RPG의 구성요소를 만들어보겠습니다.

2D는 기본적으로 3D에 비해 구성이나 설계가 단순하기에 부담없이 사용할 수 있는 코드로 구성해보았습니다.

 

1) BaseController

RPG게임에는 플레이어가 조종하는 캐릭터와 그렇지 않은 캐릭터가 존재합니다.

그러나 2개의 요소 모두 공통적인 기능을 수행해야 하는 경우가 있습니다.

이런 상황에서 상속을 통해 공통적인 기능은 부모가, 개별적인 기능을 따로 구현하는 것이 좋습니다.

따라서 부모의 역할을 수행하는 BaseController를 만들어보겠습니다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BaseController : MonoBehaviour
{
    // 애니메이션 연출과 물리 적용을 위한 컴포넌트
    protected Animator animator;
    protected Rigidbody2D rigidbody;

    // Flip(=방향전환)을 위해 필요한 함수
    protected bool bIsFacingRight = true;
    protected int facingDirection = 1;
	
    // 땅과 벽을 확인하기 위한 요소들
    [Header("Collision Settings")]
    [SerializeField]
    protected float distanceToCheckGround;
    [SerializeField]
    protected Transform groundCheckPoint;
    protected bool bIsGrounded = true;
    [Space]
    [SerializeField]
    protected float distanceToCheckWall;
    [SerializeField]
    protected Transform wallCheckPoint;
    protected bool bIsFaicingWall = false;    

    protected virtual void Start()
    {
        animator = GetComponentInChildren<Animator>();
        rigidbody = GetComponent<Rigidbody2D>();

        // 플레이어의 경우 벽을 확인할 필요는 없으므로 자기자신을 벽확인지점으로 설정
        if (wallCheckPoint == null)
            wallCheckPoint = gameObject.transform;
    }

    // 매 프레임마다 땅과 벽을 확인
    protected virtual void Update()
    {
        CheckIsGrounded();
        CheckIsFacingWall();
    }

    // 땅을 향해 Raycast를 하여 땅을 딛고 있는지 확인
    protected virtual void CheckIsGrounded()
    {
        bIsGrounded = Physics2D.Raycast(groundCheckPoint.position, Vector2.down, distanceToCheckGround, LayerMask.GetMask("Ground"));
    }

    // 벽을 향해 Raycast를 하여 벽을 보고 있는지 확인
    protected virtual void CheckIsFacingWall()
    { 
        bIsFaicingWall = Physics2D.Raycast(wallCheckPoint.position, Vector2.right, distanceToCheckWall, LayerMask.GetMask("Ground"));
    }

    // Flip의 경우, 오른쪽을 보고 있으면 왼쪽으로 반대로 왼쪽을 보고 있으면 오른쪽을 봐야 하므로
    // 매 프레임마다 값을 역전시킴
    protected virtual void Flip()
    {
        facingDirection *= -1;
        bIsFacingRight = !bIsFacingRight;
        gameObject.transform.Rotate(0, 180, 0);
    }

    // 몬스터가 아닌 플레이어는 입력에 따라 방향 전환을 해야 하므로 Flip을 2개로 쪼갬
    protected virtual void DoFlip()
    {
        if (rigidbody.velocity.x > 0 && !bIsFacingRight)
            Flip();
        else if (rigidbody.velocity.x < 0 && bIsFacingRight)
            Flip();
    }

    // groundCheckPoint와 wallCheckPoint를 확인하기 위한 디버그 함수
    protected virtual void OnDrawGizmos()
    {
        Gizmos.DrawLine(
            gameObject.transform.position,
            new Vector3(
                groundCheckPoint.position.x,
                groundCheckPoint.position.y - distanceToCheckGround)
        );

        Gizmos.DrawLine(
            gameObject.transform.position,
            new Vector3(
                wallCheckPoint.position.x + distanceToCheckWall * facingDirection,
                wallCheckPoint.position.y - distanceToCheckWall)
        );
    }
}

 

코드는 위와 같습니다.

간단하게 정리하자면

지형지물을 Raycast로 확인하는 코드와 방향을 전환하는 코드 그리고 컴포넌트를 가져오는 코드는

BaseController에서 수행합니다.

 

이제 BaseController에서 상속된 PlayerController를 만들어보겠습니다.

 

728x90
반응형