상세 컨텐츠

본문 제목

[개발일지] 유니티 3D 서바이벌 게임: 활 쏘기 시스템 구현

카테고리 없음

by 강자이 2024. 6. 11. 00:59

본문

서론

유니티로 3D 서바이벌 게임을 개발하는 과정에서 활 쏘기 시스템을 구현했습니다. 플레이어가 활을 조준하고 발사하는 애니메이션을 자연스럽게 연동시키는 작업이 주요 목표였습니다. 이번 개발일지에서는 활 쏘기 시스템의 구현 과정과 핵심 코드를 공유하려 합니다.

 

 

개발 내용

클래스 및 변수 선언

먼저 활 쏘기 시스템의 핵심이 되는 BowInputSystem 클래스를 선언하고 필요한 변수들을 정의했습니다.

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Numerics;
using UnityEngine;
using Vector3 = UnityEngine.Vector3;

public class BowInputSystem : MonoBehaviour
{
    PlayerAnimController _playerAnimController;
    CameraController _cameraController;

    [System.Serializable]
    public class InputSettings
    {
        public string aim = "Fire2";
        public string fire = "Fire1";
    }

    [SerializeField]
    public InputSettings input;

    [Header("Aiming Settings")]
    Ray ray;
    RaycastHit hit;
    public LayerMask aimLayers;

    [Header("Spine Settings")]
    public Transform spine;
    public Vector3 spineOffset;

    [Header("Head Rotation Settings")]
    public float lookAtPoint = 2.8f;

    public Bow bowScript;
    public bool testAim;
    public bool isAiming;

    bool hitDetected;

 

  • PlayerAnimController와 CameraController는 각각 플레이어의 애니메이션과 카메라 컨트롤을 담당합니다.
  • InputSettings 클래스는 조준과 발사 입력을 정의합니다.
  • aimLayers는 조준할 수 있는 레이어를 설정합니다.
  • spine와 spineOffset은 플레이어의 척추 본 설정을 위한 변수입니다.
  • lookAtPoint는 플레이어의 시선 방향을 조절합니다.
  • bowScript는 활과 관련된 기능을 관리합니다.
  • testAim과 isAiming은 테스트용 및 현재 조준 상태를 나타내는 불리언 변수입니다.

 

 

Start 메서드

Start 메서드는 스크립트가 처음 실행될 때 호출됩니다. 여기서 주요 컴포넌트를 초기화합니다.

 

private void Start()
{
    _playerAnimController = GetComponent<PlayerAnimController>();
    _cameraController = GetComponentInChildren<CameraController>();
}

 

Update 메서드

Update 메서드는 매 프레임 호출되며, 여기서 조준 및 발사 상태를 업데이트합니다.

 

private void Update()
{
    UpdateAim();

    if (testAim)
        isAiming = true;

    if (isAiming)
    {
        Pull();
        Aim();
        bowScript.EquipBow();
        
        _playerAnimController.PullString(Input.GetButton(input.fire));

        if (Input.GetButtonUp(input.fire))
        {
            _playerAnimController.FireArrow();

            if (hitDetected)
            {
                bowScript.Fire(hit.point);
            }
            else
            {
                bowScript.Fire(ray.GetPoint(300f));
            }
        }
    }
    else
    {
        bowScript.UnEquipBow();
        bowScript.RemoveCrosshair();
        DisableArrow();
        Release();
    }
}

 

  • UpdateAim 메서드를 호출하여 현재 조준 상태를 갱신합니다.
  • 조준 중일 때 (isAiming == true), 활 당기기(Pull), 조준(Aim), 활 장착(EquipBow) 등의 동작을 수행합니다.
  • 발사 버튼(input.fire)이 눌렸을 때, 애니메이션을 업데이트하고 화살을 발사합니다.
  • 조준하지 않을 때는 활 비장착(UnEquipBow), 조준점 제거(RemoveCrosshair), 화살 비활성화(DisableArrow), 활 줄 놓기(Release) 등의 동작을 수행합니다.

 

 

UpdateAim 메서드

UpdateAim 메서드는 현재 조준 상태를 업데이트합니다.

 

public void UpdateAim()
{
    isAiming = Input.GetButton(input.aim);
    _playerAnimController.Aim(isAiming);
}

 

  • 조준 버튼(input.aim)이 눌렸는지 확인하고, 조준 상태를 업데이트합니다.
  • PlayerAnimController의 Aim 메서드를 호출하여 애니메이션을 조정합니다.

 

 

Aim 메서드

Aim 메서드는 카메라를 통해 조준을 처리합니다.

 

private void Aim()
{
    Vector3 camPosition = Camera.main.transform.position;
    Vector3 dir = _cameraController.mainCam.transform.forward;
    ray = new Ray(camPosition, dir);

    if (Physics.Raycast(ray, out hit, 500f, aimLayers))
    {
        hitDetected = true;
        Debug.DrawLine(ray.origin, hit.point, Color.green);
        bowScript.ShowCrosshair(hit.point);
    }
    else
    {
        hitDetected = false;
        bowScript.RemoveCrosshair();
    }
}

 

  • 카메라 위치와 방향을 기준으로 레이를 발사합니다.
  • 레이가 목표물에 맞으면 hitDetected를 true로 설정하고, 크로스헤어를 표시합니다.
  • 맞지 않으면 hitDetected를 false로 설정하고, 크로스헤어를 제거합니다.

 

 

 

기타 메서드

다양한 활 관련 동작을 처리하는 메서드들입니다.

public void Pull()
{
    bowScript.PullString();
}

public void EnableArrow()
{
    bowScript.PickArrow();
}

public void DisableArrow()
{
    bowScript.DisableArrow();
}

public void Release()
{
    bowScript.ReleaseString();
}
  • Pull: 활 줄을 당기는 동작을 처리합니다.
  • EnableArrow: 화살을 준비합니다.
  • DisableArrow: 화살을 비활성화합니다.
  • Release: 활 줄을 놓는 동작을 처리합니다.

 

 

결론

활 쏘기 시스템을 구현함으로써 플레이어가 활을 조준하고 발사하는 동작을 자연스럽게 연결할 수 있었습니다. 이를 통해 게임의 몰입감을 높일 수 있었고, 캐릭터 애니메이션과 게임플레이가 더욱 일체화되었습니다. 이 글이 유니티로 게임을 개발하는 다른 분들께 도움이 되길 바랍니다. 감사합니다.

 
 

댓글 영역