Chapter 2-7. 무기 : 마우스 회전에 따른 무기 흔들림

Date:     Updated:

카테고리:

태그:

인프런에 있는 케이디님의 [유니티 3D] 실전! 생존게임 만들기 - Advanced 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click


Chapter 2. 무기

무기 흔들림 구현하기

📜WeaponSway.cs

Holder에 붙여 준다.

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

public class WeaponSway : MonoBehaviour
{
    private Vector3 originPos;  // 기존 위치. 원래 위치 값으로 돌아가기 위해 보존.
    private Vector3 currentPos;  // 현재 위치. 계속 계산해나가며 업데이트 할 것.

    [SerializeField]
    private Vector3 limitPos;  // 정조준이 아닐 때 무기가 최대 얼만큼까지 흔들릴 수 있는지.
    [SerializeField]
    private Vector3 fineSightLimitPos;  // 정조준 할 때 무기가 최대 얼만큼까지 흔들릴 수 있는지.
    [SerializeField]
    private Vector3 smoothSway;  // 총이 흔들릴 때 부드럽게 흔들리는 정도.

    [SerializeField]
    private GunController theGunController;  // 📜GunController.cs 의 isFineSightMode 를 받아 오기 위해. 정조준 상태 여부에 따라 흔들림 정도가 다르므로 알아야 함.

    void Start()
    {
        originPos = this.transform.localPosition;
        currentPos = originPos;
    }

    void Update()
    {
        TrySway();
    }

    private void TrySway()
    {
        if (Input.GetAxisRaw("Mouse X") != 0 || Input.GetAxisRaw("Mouse Y") != 0)
            Swaying();
        else
            BackToOriginPos();
    }

    private void Swaying()
    {
        float _moveX = Input.GetAxisRaw("Mouse X");  // -1.0 혹은 0.0 혹은 1.0
        float _moveY = Input.GetAxisRaw("Mouse Y");  // -1.0 혹은 0.0 혹은 1.0

        if(!theGunController.isFineSightMode)
        {
            currentPos.Set(Mathf.Clamp(Mathf.Lerp(currentPos.x, -_moveX, smoothSway.x), -limitPos.x, limitPos.x),
                        Mathf.Clamp(Mathf.Lerp(currentPos.y, -_moveY, smoothSway.y), -limitPos.y, limitPos.y),
                        originPos.z);
        }
        else
        {
            currentPos.Set(Mathf.Clamp(Mathf.Lerp(currentPos.x, -_moveX, smoothSway.x), -fineSightLimitPos.x, fineSightLimitPos.x),
                        Mathf.Clamp(Mathf.Lerp(currentPos.y, -_moveY, smoothSway.y), -fineSightLimitPos.y, fineSightLimitPos.y),
                        originPos.z);
        }

        transform.localPosition = currentPos;
    }

    private void BackToOriginPos()
    {
        currentPos = Vector3.Lerp(currentPos, originPos, smoothSway.x);
        transform.localPosition = currentPos;
    }
}

  • 무기를 들고 있을 때나 맨손일 때 마우스 회전에 따라 총과 손의 위치에 자연스러운 흔들림을 준다. !
    • 마우스를 👈 방향으로 움직여 화면을 왼쪽으로 회전하면, 무기와 손은 원래 위치로부터 👉 오른쪽 방향으로 살짝 쏠리게 하고
    • 마우스를 👉 방향으로 움직여 화면을 오른쪽으로 회전하면, 무기와 손은 원래 위치로부터 👈 왼쪽 방향으로 살짝 쏠리게 하고
    • 마우스를 👆 방향으로 움직여 화면을 위로 회전하면, 무기와 손은 원래 위치로부터 👇 아래쪽 방향으로 살짝 쏠리게 하고
    • 마우스를 👇 방향으로 움직여 화면을 아래로 회전하면, 무기와 손은 원래 위치로부터 👆 위쪽 방향으로 살짝 쏠리게 한다.
  • 정조준일 땐 덜 쏠리게 하고, 정조준이 아닐 땐 더 쏠리게 한다.
    • 정조준땐 움직임이 덜하고 정확해야 하니까.


  • Start()
    • orginiPos에 원래 위치 보존
      • 이 스크립트가 붙을 HolderPlayer에 붙음으로서 Player 기준으로 (0, 0, 0) 원점을 위치로 가진다. (LocalPosition)
      • 따라서 orginiPos에 Vector3.zero 값이 저장될 것이다.
    • currentPosorginiPos에서 시작
  • Update()
    • 매 프레임마다 마우스 회전에 따른 총, 무기에 흔들림을 주거나 마우스 움직임이 없다면 원상복귀 하는 일을 수행하는 TrySway() 함수 실행
  • TrySway()
    • 마우스 움직임에 변화가 있다면 총, 무기에 흔들림을 주는 Swaying() 함수 실행
      if (Input.GetAxisRaw("Mouse X") != 0 || Input.GetAxisRaw("Mouse Y") != 0)
          Swaying();
      
    • 마우스 움직임에 변화가 없다면 흔들림으로 인해 변화되었던 총, 무기의 위치를 originPos로 원상 복귀하는 BackToOriginPos() 함수 실행
      else
          BackToOriginPos();
      
  • Swaying()
    • 총이나 손이 너무 이동해서 화면 밖을 벗어나면 안되니까, 정조준이 아닌 상태일 땐 limitPos만큼만(delta) 이동하게 하였다.
      • currentPos Vector3 업데이트
        • X 값
          • Mathf.Lerp(currentPos.x, -_moveX, smoothSway.x) 값이되
            • currentPos.x에서 -_moveX까지 smoothSway.x 비율로 보간한 값
            • -_moveX 이렇게 음수인 이유
              • 마우스를 왼쪽으로 움직이면 팔은 반대 방향인 오른쪽으로 쏠리게 하고, 마우스를 오른쪽으로 움직이면 팔은 반대 방향인 왼쪽으로 쏠리게 하는게 자연스러우니까.
            • -_moveX는 어차피 -1, 1 둘 중 하나이므로 currentPos.x는 보간이 끝나면 -1, 1에 근접해진다.
              • Holder는 부모인 Player 기준으로 원점이 원래 위치니까 흔들려 봤자 원래 위치로부터 최대 거리 1 정도 만큼만 쏠리게 만들어준 것이다.
          • 단, [-limitPos.x, limitPos.x] 범위를 넘지 않도록 막아 주었다.
            • 너무 쏠려서 화면에서 사라지는 것을 방지하고자.
              • 예를 들어 limitPos.x가 0.2 값이라면 currentPos.x는 -1, 1 둘 중 하나인 -_moveX에 근접하는 것을 목표로 하되 0.2 를 넘지 않게 하므로 Holder는 부모인 Player 기준으로 원점이 원래 위치니까 흔들려 봤자 원래 위치로부터 최대 거리 0.2 정도 만큼만 쏠리게 하는 것과 같다.
        • Y 값
          • Mathf.Lerp(currentPos.y, -_moveY, smoothSway.y) 값이되
          • 단, [-limitPos.y, limitPos.y] 범위를 넘지 않도록 막아 주었다.
        • Z 값
          • 마우스 회전으로 Z 값에 변화를 주는건 없으니 그대로 원래 위치 Z 값을 따름. originPos.z
    • 정조준 상태일 땐 범위를 [-fineSightLimitPos, fineSightLimitPos] 으로 해주면 되고 그 외는 동일
    • 현재 위치를 위에서 설정한 currentPos로 업데이트. Holder 오브젝트의 로컬 위치가(플레이어 기준에서의 위치가) currentPos로 바뀐다.
  • BackToOriginPos()
    • currentPos을 원래 위치인 originPos로 계속해서 smoothSway.x만큼 보간해나간다.
      • 그냥 비율로는 아무거나 smoothSway.x로 선택했다.
    • 현재 위치를 위에서 설정한 currentPos로 업데이트.


image

위 같은 설정대로라면 예를 들어 정조준이 아닐 때 마우스를 아래로 움직이게 되면 총은 0.05 비율로 보간되어가며 원래 위치로부터 위로 0.1 만큼 떨어진 위치로 무기(손 혹은 총)가 이동하게 된다.



🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

댓글남기기