Sprite Renderer를 사용하는 상황에서 뭔가 발산하는 이펙트를 사용한다면 어떻게 하는 게 좋을까 생각하면서 파티클 시스템과 오브젝트를 직접 제어하는 방법 두 가지를 사용해 보았다.
있는 리소소 가지고 대충 테스트만 하려고 만들다 보니 별로 이뻐 보이진 않는다.
이러한 상황에서는 오브젝트를 가지고 직접 제어하는 게 나은 방식인 거 같다.
실제로 사용한다면 풀링을 해서 쓰겠지만 그럼에도 상당히 많은 오브젝트를 뿜어낸다면 파티클을 쓰는 게 적합하다고 보인다.
상황에 맞게 잘 조율하는 게 필요하다.
위에서 사용한 코드
using UnityEngine;
public class Coin : MonoBehaviour
{
private const float power = 10f;
private void OnEnable()
{
transform.position = Vector3.zero;
ApplyForce();
}
private void ApplyForce()
{
var rb = GetComponent<Rigidbody2D>();
float randomHorizontal = Random.Range(-1f, 1f); // -1 to 1 for left/right
Vector2 direction = new Vector2(randomHorizontal, 1f).normalized;
rb.AddForce(direction * power, ForceMode2D.Impulse);
}
}
using UnityEngine;
public class Coin : MonoBehaviour
{
private const float power = 10f;
private void OnEnable()
{
transform.position = Vector3.zero;
ApplyForce();
}
private void ApplyForce()
{
var rb = GetComponent<Rigidbody2D>();
float randomHorizontal = Random.Range(-1f, 1f); // -1 to 1 for left/right
Vector2 direction = new Vector2(randomHorizontal, 1f).normalized;
rb.AddForce(direction * power, ForceMode2D.Impulse);
}
}
대충 동전이 뿜어지는 듯한 모습을 중점으로 만들었다.
Coin 간에는 충돌처리하면 초기 한 위치에 모여있을 때 서로 부딪혀서 Physics2D > Layer Collision Matrix를 꺼두었다.
바닥에 충돌 후 튕기는 것과 미끄러지는 정도는 Phsics Material로 조절한다 (Friction 마찰력, Bounciness 탄성력)
UI Effect
위 내용들은 겸사겸사로 같이 정리한 내용이고 이 글을 쓰기 시작한 이유는 이 부분 때문이었다.
상황은 대충 이렇다.
간단한 퍼즐 게임을 만드는 중에 스프라이트 렌더러를 쓰기에는 귀찮은 부분들이 있어서 간단하게 만들려고 UI를 베이스로 해서 게임 로직들을 만들었고 그렇게 진행하다 보니 효과를 추가하는 과정에서 물리적인 부분을 사용할 수 없어 직접 위치를 이동시켜서 유사하게 재현할 수밖에 없었다.
UI Animation
using UnityEngine;
public class UICoinMaster : MonoBehaviour
{
[SerializeField] UICoin[] uiCoins;
bool isOn = false;
public void OnClick_UICoinMaster()
{
if (isOn)
{
foreach( var coin in uiCoins)
{
coin.gameObject.SetActive(false);
}
isOn = false;
}
else
{
foreach (var coin in uiCoins)
{
coin.gameObject.SetActive(true);
}
isOn = true;
}
}
}
using UnityEngine;
public class UICoin : MonoBehaviour
{
[SerializeField] private float initialForce = 10f;
[SerializeField] private float gravity = 9.8f;
[SerializeField] private float bounceForce = 0.5f;
[SerializeField] private bool isMoving = false;
private RectTransform rect;
private Vector2 velocity;
private Vector2 originPos;
private void Awake()
{
rect = GetComponent<RectTransform>();
originPos = rect.position;
}
private void OnEnable()
{
ApplyPower();
}
private void OnDisable()
{
rect.position = originPos;
}
private void ApplyPower()
{
float randomX = Random.Range(-1f, 1f);
velocity = new Vector2(randomX, 1f).normalized * initialForce;
isMoving = true;
}
private void Update()
{
if (!isMoving) return;
velocity.y -= gravity * Time.deltaTime;
rect.anchoredPosition += velocity * Time.deltaTime;
if (rect.anchoredPosition.y < 0)
{
rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, 0);
velocity.y = -velocity.y * bounceForce;
velocity.x *= 0.8f;
if (Mathf.Abs(velocity.y) < 0.1f)
{
isMoving = false;
}
}
}
}
UI 크기에 맞춰서 값들을 적절하게 세팅하면 그럴듯해 보인다. 구현하는 데는 크게 무리가 없지만 UI 가지고 이래도 되나 싶은 생각이 들기도 한다.
개인적으로는 필요한 기능만 직접 구현해서 쓰는 걸 선호하는 편이라 잘 쓰진 않지만 위처럼 UI를 제어하는 데는 DoTween을 사용하는 게 더 간단하고 다양한 동작들도 처리할 수 있을 것이다.
UI Particle System
한 번쯤은 'UI위에 파티클 뿌리기'에 대해서 많은 고민과 탐구를 해보았을 것이다. 이 경우 나는 주로 카메라의 렌더링 모드를 Screen Space - Camera로 세팅해서 파티클을 보이게 하는 방법을 사용했다. 그런데 이 방법은 원하는 파티클을 사용할 때나 좌표계를 다룰 때 은근히 귀찮고 까로운면이 있었다.