본문 바로가기
유니티

[유니티] #3 광부 타이쿤 게임 만들기 (애니메이터, 프로퍼티)

by 디버그러 2025. 1. 13.

 

▲ Filp X 체크
▲ Scale -1 값 입력

 

이제 애니메이션을 만들어볼 차례다.

광부가 땅을 파고 다시 돌아올 때는 좌우반전이 일어나야 하는데

위의 사진과 같이 Filp X에 체크하면 삽을 빼고 캐릭터만 좌우반전 하게 된다.

부모와 자식이 같이 회전하려면 Scale의 X값을 -1로 바꿔야 한다.

 

 

 

BaseMiner 스크립트에 RotateMiner 함수를 선언한다.

direction이 1이라면 원래대로 오른쪽을 보고, 1이 아니라면 좌우반전하여 왼쪽을 보게 된다.

 

 

 

선언한 RotateMiner 함수를 코루틴과 DepositGold 함수에 추가한다.

 

 

 

기본 애니메이션은 Idle로 지정하고 Any State에서 Mining와 Walking 애니메이션으로 연결한다.

파라미터로 Trigger를 추가해 Mining과 Walking을 만든다.

 

 

 

Mining과 Walking 애니메이션의 Conditions에 각각 파라미터를 넣는다.

 

 

 

_animator 변수를 만든다.

_는 프라이빗 멤버 변수라는 뜻으로 프로퍼티나 지역 변수와 구분을 위해 쓰인다.

필수적이지는 않으며 코딩 스타일마다 다르다.

 

 

 

보통 애니메이션을 연결할 때 _animator.SetTrigger("mining"); 이런 식으로 쓰곤 하는데
애니메이션이 여러 군데 쓰인다면 실수할 확률이 올라간다.

 

miningAnimationParametor 변수를 만들고 StringToHash 함수를 통해 Id를 부여받았다.

이 Id가 담긴 변수를 SetTrigger 안에 넣어주면 실수를 방지할 수 있다.

 

 

 

moveMiner를 virtual 함수로 바꾸고 자식 스크립트에서 override 한다.

base. 을 붙이면 기본 메서드를 호출한다.

 

 

 

walkingAnimationParametor 변수도 똑같이 선언해 주고 SetTrigger에 넣어준다.

여기까지 하면 기본적인 광부 움직임은 완료됐다.

 

 

플레이하고 M키를 누르면 광부가 계속 움직이며 채굴한다.

 

 

 

새로운 Shaft 스크립트를 만들었다.

SerializeField로 프리팹 변수와 위치 변수를 선언했다.

헤더를 통해 구분해 주면 인스펙터에서 알아보기 쉽다.

 

 

 

ShaftMiner 캐릭터는 Prefabs 폴더에 넣고 프리팹으로 만든 뒤 씬에서 삭제한다.

 

 

 

Shaft 오브젝트에 Shaft 스크립트를 추가하고 빈칸을 드래그 앤 드롭으로 채워준다.

 

여기서 MinerPrefab이 GameObject 클래스든 ShaftMiner 클래스든 상관없다.

프리팹은 완성형 템플릿이기 때문에 어떤 클래스로 참조하더라도 모든 요소가 함께 복제되고 동작한다.

 

 

 

Shaft 스크립트에 CreateMiner 함수를 선언하고 Start 메서드에서 호출한다.

 

 

 

이 상태에서 실행하고 M키를 눌러보면 오류가 발생한다.

원인은 바로 프리팹이 씬 오브젝트에 대한 참조는 저장하지 않기 때문이다.

씬 오브젝트는 런타임에 동적으로 생성되고 관리되기에 씬 오브젝트와 프리팹은 별개다.

 

 

 

ShaftMiner 스크립트에 있는 Update 메서드와 SerializeField 변수는 삭제한다.

이제 M 버튼을 눌러야 움직이는 게 아니라 자동으로 움직이게 만들 것이고, 프리팹은 씬 오브젝트 참조가 불가하다.

해결 방법은 씬에 배치된 오브젝트의 스크립트에 변수를 추가하고 위치를 받아오는 것이다.

 

 

 

 

ShaftMiner 스크립트에 프로퍼티 CurrentShaft를 만든다.

Shaft 스크립트에서 초기화해준다.

 

 

 

이제 ShaftMiner 스크립트에서 변수 삭제로 인해 오류가 난 부분을 수정해 준다.

SerializeField 변수가 없어졌기에 프로퍼티를 통해 위치값을 가져온다.

 

private Shaft shaftScript; 라고 변수를 만들면 더 쉬운데 왜 굳이 프로퍼티 방식을 썼는지 찾아봤다.

초보 개발자는 프로퍼티보다 변수를 사용하는 방식이 직관적이지만 추후 유지보수를 위해서는 프로퍼티가 유리하다.

 

▲ 변수와 프로퍼티의 차이점
▲ 변수와 프로퍼티의 각 단점

 

유니티에서는 다른 스크립트의 변수를 가져올 때 프로퍼티를 사용하는 것이 권장되는 방식이며,
C# 프로그래밍 전반에서 강조되는 캡슐화 개념과 잘 맞아떨어진다.

 

<프로퍼티 장점>
- 직접 접근보다 안전한 데이터 관리 (public 변수에 직접 접근하면 실수로 값이 변경될 가능성↑)
- 추후 로직 추가에 유리
- 코드 가독성

 

유니티 엔진 내부의 많은 속성(Transform.position, Rigidbody.velocity)도 프로퍼티로 구현되어 있다.

결과적으로 유니티에서 중요한 변수는 private + 프로퍼티 방식으로 캡슐화하고

[SerializeField]를 통해 인스펙터에서 값 설정을 허용하는 편이 좋다.

 

 

 

실행해 보니 이번엔 NullReference 오류가 발생했다.

광부 인스턴스를 생성하고 moveMiner를 통해 바로 애니메이션을 실행한 게 원인이다.

자식 클래스인 ShaftMiner의 Start 메서드에서 Animator를 초기화했기 때문이다.

 

 

ShaftMiner 스크립트의 애니메이터 부분을 삭제하고 BaseMiner 스크립트로 옮겼다.

다른 광부를 만들 때 Animator 중복 방지 및 NullReference 오류 방지를 위해

부모 클래스 BaseMiner 스크립트의 Awake 메서드로 옮기는 것이다.

컴포넌트 초기화는 꼭 Awake 메서드에서 하는 것이 좋다.

 

 

 

강의 출처: #9 Update Animations and Rotation (Unity Tutorial | Tycoon idle game)