[Unit] Player character and movement > [Tutorial] Create Input Actions for player character movement

  1. 이미지 기본 속성 설정
  • Sprite Mode: Multiple (하나의 파일을 여러 조각으로 쪼개기 위해)
  • Pixels Per Unit (PPU): 100 (게임 내 크기 단위 표준 확인)
  • Mesh Type: Full Rect (가장 중요!)

    이유: 파티클은 사각형 평면에서 돌아가야 하므로, 투명한 여백을 최대한 잘라내는 ‘Tight’ 대신 ‘Full Rect’를 써야 이미지가 찌그러지지 않고 비율이 유지됩니다. 2. 스프라이트 쪼개기 (Slice)

  • 버튼 클릭: Apply 적용 후 Sprite Editor 실행
  • 작업: Slice 메뉴 -> Type: Grid By Cell Count 선택
  • 설정: Column(열): 4, Row(행): 4 입력
  • 결과: 전체 이미지가 4x4 (총 16칸)의 격자로 균일하게 잘립니다

  1. 기본 생성 및 이름 변경
  • Hierarchy(계층 구조) 창 > 마우스 우클릭 > Effect > Particle System 선택
  • Inspector(인스펙터) 창 최상단 > 이름 수정: SmokeEffect
    1. 이미지 소스 연결 (Texture Sheet Animation)

    파티클의 모양을 ‘기본 사각형’에서 ‘연기 스프라이트’로 교체하는 단계입니다.

  • Inspector > Particle System 컴포넌트 > Texture Sheet Animation 모듈 체크 및 확장
  • Mode: Sprites로 변경
  • (+) 버튼: 클릭하여 슬롯 2개 생성
  • Sprite 슬롯: ParticleSpriteAtlas_0 및 ParticleSpriteAtlas_1 할당
    1. 무작위 모양 설정 (Start Frame)

    나오는 연기마다 모양이 다르게 섞여 나오도록 설정합니다.

  • Inspector > Particle System 컴포넌트 > Texture Sheet Animation 모듈
  • Start Frame: 우측 화살표 클릭 > Random Between Two Constants 선택
  • 값 입력: 0 과 2 (생성 시 0번 혹은 1번 이미지 중 하나를 무작위 선택)
    1. 애니메이션 고정 (Frame over Time)

    연기가 날아가면서 모양이 변하지 않고 처음 뽑힌 모양을 유지하게 합니다.

  • Inspector > Particle System 컴포넌트
  • Frame over Time: 우측 곡선(Curve) 또는 상자 클릭
  • 곡선 편집기(하단): 오른쪽 끝에 있는 점(키프레임) 마우스 우클릭 > Delete Key 선택
  • 결과: 수평선 형태가 되어 시간이 지나도 이미지가 바뀌지 않음
    1. 방출 각도 조절 (Angle)
  • 위치: Inspector > Particle System 컴포넌트 > Shape

  • Angle 5로 설정: 파티클이 퍼지는 범위를 좁혀서 연기가 직선에 가깝게 올라가도록 만듭니다.
    1. 방출 지점 밀집 (Radius)
  • Radius 0으로 설정: 넓은 원 영역이 아니라 정확히 한 점에서 파티클이 생성됩니다.

🔍 파티클 시스템에 무작위성을 더 추가

위치: Inspector > Particle System

  1. 수명 설정 (Start Lifetime)

    연기가 사라지는 시간을 무작위로 설정하여 소멸 지점을 다르게 합니다.

  • 속성: Start Lifetime -> 우측 화살표 -> Random Between Two Constants
  • 설정 값: 1.5 와 3
  • 효과: 어떤 연기는 빨리 사라지고, 어떤 연기는 더 멀리까지 날아갑니다.
    1. 속도 설정 (Start Speed)

    연기가 올라가는 속도에 변화를 줍니다.

  • 속성: Start Speed -> 우측 화살표 -> Random Between Two Constants
  • 설정 값: 0.5 와 1
  • 효과: 연기 덩어리들이 서로 다른 속도로 솟아올라 더 역동적으로 보입니다.
    1. 크기 설정 (Start Size)

    연기 입자의 크기를 불규칙하게 만듭니다.

  • 속성: Start Size -> 우측 화살표 -> Random Between Two Constants
  • 설정 값: 0.3 과 0.5
  • 효과: 큰 연기와 작은 연기가 섞여 나와 획일적인 느낌이 사라집니다.

🔍 연기가 사라지는 디테일 추가

  1. 투명도 변화 설정 (Color over Lifetime)

    연기가 시작 때는 선명했다가, 사라지기 직전에는 투명하게 사라지도록 만듭니다.

  • Inspector > Particle System > Color over Lifetime 모듈 체크 및 확장
  • 속성: Color 상자 클릭 (그라디언트 편집기 열기)
  • 조작: 오른쪽 상단 마커(Alpha 마커) 클릭
  • Alpha 값: 0 으로 설정
    1. 크기 변화 설정 (Size over Lifetime)

    연기가 시작 때는 덩어리졌다가 서서히 작아지게 만듭니다.

  • Inspector > Particle System > Size over Lifetime 모듈 체크 및 확장
  • 속성: Size 상자(그래프) 클릭
  • 사전 설정(Preset): 하단 5번째 옵션 선택 (오른쪽 아래로 내려가는 곡선)
  • 조작: Ctrl(Cmd)을 누른 채 그래프의 점들을 드래그하여 곡선 모양 조절
  • 효과: 처음에는 설정한 크기(Start Size)로 시작했다가, 수명이 다할 때쯤 0이 되어 사라집니다.

🔍 SmokeEffect 프리팹 적용 및 배치 정리

  • SmokeEffect 게임 오브젝트를 기반으로 프리팹을 생성 하고 씬에 있는 기존 프리팹을 삭제합니다.
  • 프리팹 편집 모드에서 적 프리팹을 엽니다 .
  • 프로젝트 창 에서 SmokeEffect 프리팹을 클릭하고 드래그하여 계층 구조 창 에서 Enemy GameObject 위로 놓으면 SmokeEffect 프리팹이 Enemy GameObject 의 자식 GameObject가 됩니다 .
  • 씬 뷰 에서 도구 오버레이의 이동 도구를 선택하고 SmokeEffect 게임 오브젝트를 배치하여 연기가 Enemy 게임 오브젝트 의 위쪽에서 나오는 것처럼 보이도록 합니다 .
  • 인스펙터 창 에서 파티클 시스템 구성 요소의 기본 모듈 에 있는 시뮬레이션 공간 속성 드롭다운을 열고 월드를 선택합니다 .
    • Local : 파티클이 부모의 좌표계에 갇힘연기가 적 머리에 풀로 붙인 듯 따라다님.
    • World : 파티클이 생성 후 세계 좌표에 남음. 적이 움직이면 뒤에 연기 꼬리가 생김.

###🔍 적 스크립트 수정

using UnityEngine;

public class EnemyController : MonoBehaviour
{
  
    // Public variables
    public float speed;
    public bool vertical;
    public float changeTime = 3.0f;
    public bool isBroken { get { return broken; } }
    public ParticleSystem smokeParticleEffect;

    // Private variables
    Rigidbody2D rigidbody2d;
    Animator animator;
    float timer;
    int direction = 1;
    bool broken = true;

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        rigidbody2d = GetComponent<Rigidbody2D>();
        animator = GetComponent<Animator>();
        timer = changeTime;
    }

    // Update is called every frame
    void Update()
    {
        timer -= Time.deltaTime;

        if (timer < 0)
        {
            direction = -direction;
            timer = changeTime;
        }
    }

    // FixedUpdate has the same call rate as the physics system
    void FixedUpdate()
    {
        if (!broken)
        {
            return;
        }

        Vector2 position = rigidbody2d.position;

        if (vertical)
        {
            position.y = position.y + speed * direction * Time.deltaTime;
            animator.SetFloat("Move X", 0); // "Move X"라는 변수 값을 0으로 만듦
            animator.SetFloat("Move Y", direction);
        }
        else
        {
            position.x = position.x + speed * direction * Time.deltaTime;
            animator.SetFloat("Move X", direction);
            animator.SetFloat("Move Y", 0);
        }
        
        rigidbody2d.MovePosition(position);
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        PlayerController player = other.gameObject.GetComponent<PlayerController>();

        if (player != null)
        {
            player.ChangeHealth(-1);
        }
    }

    public void Fix()
    {
        broken = false;
        // 적 게임 오브젝트를 물리 시스템의 충돌 시뮬레이션에서 제외.
        // 투사체가 더 이상 적과 충돌하지 않으며 적 캐릭터에게 피해를 못 주게 됨.
        rigidbody2d.simulated = false;
        animator.SetTrigger("Fixed");
        smokeParticleEffect.Stop(); // 고친 후 연기 안 남
    }
}

Hierarchy 창 에서 SmokeEffect 자식 GameObject를 클릭하고 드래그하여 Smoke Effect 속성 위로 가져다 놓습니다.


📌 출처: [Unity Learn] 2D Adventure: Robot Repair