안녕하세요.😌
이번 글에서는 밋밋했던 게임 화면에 클릭 효과를 더해
조금 더 '게임스러운' 피드백을 주는 방법을 정리해 보았습니다.
원형 파티클, 폭죽 파티클, UI 등 다양한 후보를 고민했지만,
기본 Quad와 간단한 애니메이션만으로도 충분한 효과를 줄 수 있다고 판단했습니다.
먼저 애니메이션을 제작해 주었습니다.
(시간은 0.3초 / (0.5, 0.5, 0.5)의 스케일에서 (0, 0, 0)으로 줄어드는 효과)
애니메이션 끝 지점에는 ClickEventDisable 스크립트를 붙여,
Animation Event를 통해 자동 비활성화하도록 구성했습니다.
using UnityEngine;
public class ClickEventDisable : MonoBehaviour
{
public void OnAnimationEnd()
{
gameObject.SetActive(false);
}
}
다음은 마우스 클릭이 될 때 플레이어의 이동을 담당하는 "PlayerMovement" 스크립트에서 로직을 추가해 주었습니다.
추가된 로직은 다음과 같습니다.
using UnityEngine;
using UnityEngine.AI;
public class PlayerMovement : MonoBehaviour
{
[Header("Component")]
[SerializeField] private Animator playerAnim;
[SerializeField] private NavMeshAgent playerNav;
[Header("Setting Value")]
[SerializeField] private float playerNavRotateSpeed = 0.05f;
private float animationSmmothTime = 0.1f;
private float playerNavRotateVel = 0f;
[Header("Effect Settings")]
[SerializeField] private GameObject[] clickQuads;
[SerializeField] private Vector3 quadOffset = new Vector3(0, 0.1f, 0);
void Update()
{
AnimationController();
MoveController();
}
private void AnimationController()
{
float speed = playerNav.velocity.magnitude / playerNav.speed;
playerAnim.SetFloat("Speed", speed, animationSmmothTime, Time.deltaTime);
}
private void MoveController()
{
if (Input.GetMouseButtonDown(1))
{
RaycastHit hit;
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, Mathf.Infinity))
{
if (hit.collider.tag == "Ground")
{
playerNav.SetDestination(hit.point);
playerNav.stoppingDistance = 0f;
Quaternion rotationToLookat = Quaternion.LookRotation(hit.point - transform.position);
float rotationY = Mathf.SmoothDampAngle(
transform.eulerAngles.y, // 현재 y축 회전값
rotationToLookat.eulerAngles.y, // 목표 Y축 회전값
ref playerNavRotateVel, // 보정 값
playerNavRotateSpeed * (Time.deltaTime)); // 회전하는데 걸릴 시간
transform.eulerAngles = new Vector3(0, rotationY, 0);
ActivateClickQuad(hit.point + quadOffset);
}
}
}
}
private void ActivateClickQuad(Vector3 position)
{
foreach (var quad in clickQuads)
{
if (!quad.activeSelf)
{
quad.transform.position = position;
quad.SetActive(true);
return;
}
}
}
}
1. 클릭되면 생길 Quad 배열입니다. Instantiate / Destroy를 활용해 생성 / 파괴를 하는 방식이 비용이 크기에
(매번 메모리 할당과 해제가 발생하기 때문에 프레임 드롭도 생길 수 있습니다.)
간단한 Object Pooling 방식으로 활성화 / 비활성화를 해주기 위한 받아올 배열입니다.
[SerializeField] private GameObject[] clickQuads;
[SerializeField] private Vector3 quadOffset = new Vector3(0, 0.1f, 0);
2. 간단한 풀링 방식입니다. 배열을 순환하며 Quad가 비활성화일 때만 클릭된 위치에 활성화가 되게 하는 함수입니다.
(Quad에 붙어있는 애니메이션의 현재 속도가 0.3초 이기에, 아무리 빠르게 클릭해도 6개 이상을 넘어가 본 적이 없습니다. 여유롭게 10개의 Quad를 배열에 넣어 주었습니다.)
private void ActivateClickQuad(Vector3 position)
{
foreach (var quad in clickQuads)
{
if (!quad.activeSelf)
{
quad.transform.position = position;
quad.SetActive(true);
return;
}
}
}
3. 마지막으로 Ray에 맞은 콜라이더의 태그가 "Ground"일 때 플레이어의 이동 로직을 먼저 실행하며
맨 하단 부분에 추가를 해주었습니다.
ActivateClickQuad(hit.point + quadOffset);
감사합니다. 😁
왕년에 다이아2 까지 갔던 현란한 마우스 컨트롤...