먼저 핵심 내용에 대해 알아보자!
Player → MainSprite 밑에 Create Empty, 이름을 WeaponPivot이라 하자.
이후 무기 스프라이트를 WeaponPivot의 하위에 넣어준다.
이후, 좌표값을 적절하게 조절하고, 크기를 캐릭터에게 맞춰준 뒤에 Order in Layer는 6으로 설정한다(Player가 5이기 때문에)
그런 다음에 WeaponPivot 하위에 Create Empty, 이름을 BulletSpawnPoint라 한다.
BulletSpawnPoint 의 X 값은 무기보다 살짝 더 앞으로 나오도록 설정한다(활에서 화살이 발사될 것이기 때문!)
이후 Entities 파일 밑에 TopDownAimRotation.cs를 생성한다.
public class TopDownAimRotation : MonoBehaviour
{
// 무기 스프라이트
[SerializeField] private SpriteRenderer armRenderer;
// Weapon Pivot : 무기의 기준점. Pivot을 중심으로 무기가 회전되게 된다.
[SerializeField] private Transform armPivot;
// 캐릭터 스프라이트
[SerializeField] private SpriteRenderer characterRenderer;
// TopDownCharacterController → PlayerInputController에서 이벤트를 가져오기 위한 controller
private TopDownCharacterController _controller;
private void Awake()
{
_controller = GetComponent<TopDownCharacterController>();
}
// Start is called before the first frame update
void Start()
{
// OnLook 구독하기
_controller.OnLookEvent += OnAim;
}
// OnLook이 호출될 때마다(마우스의 방향이 바뀔 때마다)
private void OnAim(Vector2 newAimDirection)
{
// 캐릭터의 몸과 화살을 회전시킨다(마우스 방향으로)
RotateArm(newAimDirection);
}
private void RotateArm(Vector2 direction)
{
// Mathf.Atan2(direction.y, direction.x)을 수행하면, 라디안 값이 나오게 된다(Pie 값. 0 ~ 3.14...)
// 이후, Mathf.Rad2Deg를 곱하면 앞에서 나온 라디안 값을 0 ~ 180도(각도) 사이의 값으로 바꿔준다.
// 이를 통해 라디안 값을 각도로 변경하여 rotZ를 오일러 각도로 사용할 수 있게 된다.
float rotZ = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
// rotZ의 각도의 절대값이 90도가 넘어가게 되면
armRenderer.flipY = Mathf.Abs(rotZ) > 90f;
// 플레이어 스프라이트를 좌우 반전 시킨다.
characterRenderer.flipX = armRenderer.flipY;
// 무기 또한 회전 시킨다.
armPivot.rotation = Quaternion.Euler(0, 0, rotZ);
}
}
이후 Player에게 TopDownAimRotation 스크립트를 추가하고, 다음과 같이 게임 오브젝트들을 스크립트에 연결시켜준다.