๐ŸŽฎ2D ์• ๋‹ˆ๋ฉ”์ด์…˜ + Blend Tree - ์œ ๋‹ˆํ‹ฐ ๊ตฌํ˜„

VIN'Spellsยท2025๋…„ 12์›” 2์ผ

์œ ๋‹ˆํ‹ฐ6

๋ชฉ๋ก ๋ณด๊ธฐ
12/12

์ด์ „ ์บ๋ฆญํ„ฐ ์ด๋™๊ตฌํ˜„์— ์ด์–ด์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ ์šฉ ๋ฐฉ๋ฒ•์ด๋‹ค.

์ด๋ฒˆ์—๋„ YHJ๋‹˜์ด ์ œ์ž‘ํ•˜์‹  ์—์…‹์„ ์‚ฌ์šฉํ•œ๋‹ค.


๐Ÿ”ฎ์• ๋‹ˆ๋ฉ”์ด์…˜ ํด๋ฆฝ ๋งŒ๋“ค๊ธฐ

์‚ฌ์‹ค ์ค€๋น„๋œ ์• ์…‹๋งŒ ์žˆ๋‹ค๋ฉด ๊ฐ„๋‹จํ•œ๋ฐ ์šฐ์„  ์• ๋‹ˆ๋ฉ”์ด์…˜์œผ๋กœ ๋ณ€ํ™”๋  ์—ฐ์†๋œ ์Šคํ”„๋ผ์ดํŠธ๋ฅผ ์ „์ฒด ์„ ํƒํ•ด์ค€๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋“œ๋ž˜๊ทธํ•ด์„œ Hierarchy ์”ฌ์— ์˜ฌ๋ฆฌ๋ฉด

์ด๋Ÿฐ ์ฐฝ์ด ๋œจ๋Š”๋ฐ ์›ํ•˜๋Š” ์ด๋ฆ„๊ณผ ์ €์žฅ ์œ„์น˜๋ฅผ ์„ค์ •ํ•ด์ฃผ๊ณ  ๋งŒ๋“ค์–ด์ฃผ๋ฉด ๋œ๋‹ค.


๐Ÿ”ฎ์ปจํŠธ๋กค๋Ÿฌ ๋งŒ๋“ค๊ธฐ

์š”๋Ÿฐ ๋ฐฉ๋ฒ•์œผ๋กœ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ๋ฉด

์ด๋Ÿฐ ํ™”๋ฉด์ด ์ƒ์„ฑ๋˜๋Š”๋ฐ

์šฐ์„  ํŒŒ๋ผ๋ฏธํ„ฐ ๋ถ€ํ„ฐ ์•Œ์•„๋ณด์ž

์™ผ์ชฝ ์œ„ +๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๋„ค๊ฐ€์ง€ ํƒ€์ž…์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ
์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ณ€์ˆ˜ ๋А๋‚Œ์œผ๋กœ ์ƒ๊ฐํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

์Šคํฌ๋ฆฝํŠธ์—์„œ ๊ฐ’์„ ์ „๋‹ฌํ•ด์„œ ์›ํ•˜๋Š” ์กฐ๊ฑด์— ์›ํ•˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ž‘๋™ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š”๋ฐ Float, Int, Bool์€ ๊ธฐ๋ณธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์šฉ๋„์™€ ๊ฐ™๊ณ 

Trigger๋Š” ๋‹ค๋ฅธ ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค๊ณผ ๋‹ค๋ฅด๊ฒŒ ํ•œ๋ฒˆ ์‹ ํ˜ธ๋ฅผ์ฃผ๋ฉด ํ•œ๋ฒˆ๋งŒ ๋ฐ˜์‘ํ•œ๋‹ค.

์ด์ œ ์ƒํƒœ๋ฅผ ๋งŒ๋“ค์–ด ์• ๋‹ˆ๋ฉ”์ด์…˜ ํด๋ฆฝ์„ ์ž…ํžˆ๊ฑฐ๋‚˜ ์—ฐ๊ฒฐํ•˜๋ฉด ๋˜๋Š”๋ฐ

์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์•„๋ฌด๊ฒƒ๋„ ์—†๋Š” ๋ฐฐ๊ฒฝ์— ๋งˆ์šฐ์Šค ์šฐํด๋ฆญ(๋งฅ ํŠธ๋ž™ํŒจ๋“œ๋Š” ๋‘์†๊ฐ€๋ฝ ํด๋ฆญ ํŽธ์˜์ƒ ์•ž์œผ๋กœ ์šฐํด๋ฆญ์œผ๋กœ ํ†ต์ผ)ํ•ด์ฃผ์–ด Empty๋ฅผ ๋งŒ๋“ค๋ฉด ๋น„์–ด์žˆ๋Š” ์ƒํƒœ๊ฐ€ ๋งŒ๋“ค์–ด์ง„๋‹ค.

๋˜๋Š” ํ”„๋กœ์ ํŠธ์—์„œ ์—์…‹ ํŒŒ์ผ์„ ๋ฐ”๋กœ ํ™”๋ฉด์— ์˜ฌ๋ฆฌ๋ฉด ํด๋ฆฝ์ด ๋“ค์–ด๊ฐ€ ์žˆ๋Š” ์ƒํƒœ๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.


์ด๋ ‡๊ฒŒ ์ƒํƒœ๋“ค์„ ๋…ธ๊ฐ€๋‹ค๋ฅผ ํ†ตํ•ด ๋‹ค ๋งŒ๋“ค์—ˆ๋‹ค๋ฉด ์ด์ œ ์ด๋™๊ฒฝ๋กœ๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ์–ด์•ผํ•˜๋Š”๋ฐ

์‹œ์ž‘ํ•˜๊ณ  ์‹ถ์€ ์ƒํƒœ์—์„œ ๋งˆ์šฐ์Šค ์šฐํด๋ฆญ์„ ํ†ตํ•ด

Make Transition์„ ํด๋ฆญํ•œ๋’ค ์ด๋™ ๋ชฉ์ ์ง€ ์ƒํƒœ์— ํด๋ฆญํ•ด์ฃผ๋ฉด ํ™”๋ฉด๊ณผ ๊ฐ™์ด ๊ธธ์ด ๋งŒ๋“ค์–ด ์ง„๋‹ค.

Transition์„ ํด๋ฆญํ•ด ๋‚˜์˜ค๋Š” inspector์—์„œ ์„ค์ •ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ conditions์—์„œ ์กฐ์ •ํ•˜์—ฌ ์ด๋™์กฐ๊ฑด์„ ๋งŒ๋“ค์–ด ์ฃผ๋ฉด ๋œ๋‹ค.

Has Exit Time์ด ์ฒดํฌ๋˜์–ด์žˆ์œผ๋ฉด ์ง„ํ–‰์ค‘์ธ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋๋‚ ๋•Œ๊นŒ์ง€ ์ƒํƒœ๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š๋Š”๋‹ค.

์œ„ ์ž‘์—…์„ ๋ฐ˜๋ณตํ•ด์„œ ๋งŒ๋“ค์–ด ์ฃผ๋ฉด


๊ทน๋‹จ์ ์ด๊ธด ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋ชจ์–‘์ด ๋‚˜์˜ค๋Š”๋ฐ ๊ทธ๋ƒฅ ๋ณด๊ธฐ๋งŒํ•ด๋„ ๋ณต์žกํ•˜๊ณ  ๋น„ํšจ์œจ์ ์ธ๊ฒƒ์ด ๋А๊ปด์ง€๋Š”๋ฐ ์ด๋•Œ ์ œ๋ชฉ์— ์žˆ๋Š” ๋ธ”๋žœ๋“œ ํŠธ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊น”๋”ํ•˜๊ฒŒ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.


๐Ÿ”ฎBlend Tree

'์„ž๋‹ค'๋ผ๋Š” Blend์˜ ๋œป์ฒ˜๋Ÿผ ํ•œ ์ƒํƒœ์—์„œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ด์šฉํ•ด์„œ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์— ๋”ฐ๋ผ ์„ž์–ด ์žฌ์ƒํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

๊ฐ Idle ๊ณผ Walk ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์ƒํ•˜์ขŒ์šฐ๋กœ ๋‚˜๋ˆ„์–ด์ ธ ์žˆ์œผ๋‹ˆ ์บ๋ฆญํ„ฐ๊ฐ€ ํ–ฅํ•˜๋Š” x๊ฐ’y๊ฐ’(3D์—์„  ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ)์„ ๋ฐ›์•„์™€ ๋ฐฉํ–ฅ์œผ๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ •ํ•˜๊ฒŒ ํ•ด์ฃผ๋ ค๊ณ  ํ•œ๋‹ค.

์ปจํŠธ๋กค๋Ÿฌ ๋ฐฐ๊ฒฝ์—์„œ Create State -> From New Blend Tree๋กœ ์ƒ์„ฑํ•ด์ค€๋‹ค.

์ƒํ•˜์ขŒ์šฐ๋ฅผ ์กฐ์ ˆํ•  X์™€Y,๊ทธ๋ฆฌ๊ณ  Idle๊ณผ Walk๋ฅผ ์กฐ์ ˆํ•  speed๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์„ค์ •ํ•ด์ค€๋‹ค.

๊ทธ ๋’ค Blend Tree ์ธ์ŠคํŽ™ํ„ฐ์ฐฝ์—์„œ Motion์— ์žˆ๋Š” Blend Tree๋กœ ๋“ค์–ด๊ฐ„๋‹ค.

์‚ฌ์šฉํ•  ์šฉ๋„์— ๋”ฐ๋ผ Blend Type์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ

  • 1D - ํŒŒ๋ผ๋ฏธํ„ฐ 1๊ฐœ
  • 2D Simple Directional - ํŒŒ๋ผ๋ฏธํ„ฐ 2๊ฐœ,๋ฐฉํ–ฅ๋งŒ ๊ณ ๋ฅด๋Š” ๊ฒฝ์šฐ
  • 2D Freeform Directional - ํŒŒ๋ผ๋ฏธํ„ฐ 2๊ฐœ, ๊ฐ๋„ ๊ธฐ๋ฐ˜ ๋ฐฉํ–ฅ
  • 2D Freeform Cartesian - ํŒŒ๋ผ๋ฏธํ„ฐ 2๊ฐœ, X/Y ์ขŒํ‘œ๊ธฐ๋ฐ˜
  • Direct - ๊ฐ ๋ชจ์…˜๋งˆ๋‹ค ๊ฐ€์ค‘์น˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ง์ ‘ ์„ค์ •

์ด๋ผ๋Š” ํŠน์ง•์ด ์žˆ์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ 2๊ฐœ๋กœ ๋ฐฉํ–ฅ๋งŒ ์„ค์ •ํ•˜๋‹ˆ 2D Simple Directional์‚ฌ์šฉํ•œ๋‹ค.(๋‹ค๋ฅธ 2D๋ฅผ ์„ค์ •ํ•ด๋„ ๋™์ž‘์€ ๋˜‘๊ฐ™์ด ์ž˜ํ•œ๋‹ค)

4๊ฐœ์˜ ๋ชจ์…˜์ด ์žˆ์œผ๋‹ˆ Motion์—์„œ +๋ฅผ 4๋ฒˆ ๋ˆŒ๋Ÿฌ์„œ ์ถ”๊ฐ€ํ•ด์ฃผ๊ณ 
๊ฐ๊ฐ x,y๊ฐ’์„ ์„ค์ •ํ•œ ๋’ค ํ•ด๋‹นํ•˜๋Š” ์œ„์น˜์— ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋„ฃ์–ด์ค€๋‹ค.

์—ฌ๊ธฐ๊นŒ์ง€ ํ•ด์ฃผ์—ˆ๋‹ค๋ฉด ์ด์ œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ†ตํ•ด ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.


๐Ÿ”ฎ์• ๋‹ˆ๋ฉ”์ด์…˜ ์Šคํฌ๋ฆฝํŠธ

๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ๋Š”

  • ์• ๋‹ˆ๋ฉ”์ดํ„ฐ ์ปดํฌ๋„ŒํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ
  • ์›€์ง์ž„์„ ๊ณ„์† ์ €์žฅํ•ด ๋ฐ”๋ผ๋ณด๋Š” ๋ฐฉํ–ฅ ๊ฐ€์ ธ์˜ค๊ธฐ
  • ์• ๋‹ˆ๋ฉ”์ดํ„ฐ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ ๋„˜๊ฒจ์ฃผ๊ธฐ

์ˆœ์„œ๋Œ€๋กœ ์ง„ํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

์ด๋Ÿฐ์‹์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ›์•„์™€ ์ฃผ๊ณ 

์ด๋Ÿฐ ์‹์œผ๋กœ ์—…๋ฐ์ดํŠธ ํ•จ์ˆ˜์—์„œ ์ธํ’‹์ด ์žˆ์œผ๋ฉด ๋งˆ์ง€๋ง‰ ๋ฐฉํ–ฅ์„ ๊ฐ€์ ธ์™€ ์ €์žฅํ•ด์ค€๋‹ค.

๋Œ€๊ฐ์„  ๋ณด์ •์€ ๊ตฌํ˜„ํ• ๋•Œ ๊ฐ™์€ 1์˜ ํž˜์ผ๋•Œ ๋™์‹œ์— ๋‘๊ฐœ๋ฅผ ๋ˆŒ๋Ÿฌ ๋Œ€๊ฐ์„ ์„ ๋งŒ๋“ค๋ฉด ๊ฐ’์ด ๋ฃจํŠธ2๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ผ์ •ํ•œ ์†๋„์œ ์ง€๋ฅผ ์œ„ํ•ด์„œ ์„ค์ •ํ•ด์ค€๋‹ค.

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์—…๋ฐ์ดํŠธ ํ•จ์ˆ˜๋‚ด์—์„œ ์ด๋Ÿฐ์‹์œผ๋กœ ์• ๋‹ˆ๋ฉ”์ดํ„ฐํ•œํ…Œ ๊ฐ’์„ ์ „๋‹ฌํ•ด์ฃผ๋ฉด ๋์ด๋‹ค.


๋ฌผ๋ก  ์• ๋‹ˆ๋ฉ”์ดํ„ฐ ์ปจํŠธ๋กค๋Ÿฌ์— ์•ž์„œ ๋งŒ๋“  ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋„ฃ์–ด์ค˜์•ผํ•œ๋‹ค.

๐Ÿ”ฎ๊ฒฐ๊ณผ ๋ฐ ์ „์ฒด ์ฝ”๋“œ

using UnityEngine;
using UnityEngine.InputSystem;
public class chmove : MonoBehaviour
{
    public float moveSpeed = 4f;

    public InputAction moveAction;

    Rigidbody2D rb;
    Animator anim;

    Vector2 input;
    Vector2 lastDir = Vector2.down; // ์ •์ง€ ์‹œ ๋ฐ”๋ผ๋ณผ ๊ธฐ๋ณธ ๋ฐฉํ–ฅ

    void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
        anim = GetComponent<Animator>();
    }

    void OnEnable()
    {
        moveAction.Enable();
    }

    void OnDisable()
    {
        moveAction.Disable();
    }

    void Update()
    {
        // ์ƒˆ Input System์—์„œ Vector2 ์ฝ๊ธฐ
        input = moveAction.ReadValue<Vector2>();

        // ๋Œ€๊ฐ์„  ๋ณด์ •
        if (input.sqrMagnitude > 1f)
            input.Normalize();

        // ๋งˆ์ง€๋ง‰ ๋ฐ”๋ผ๋ณด๋Š” ๋ฐฉํ–ฅ ์œ ์ง€(4๋ฐฉํ–ฅ ๊ธฐ์ค€)
        Vector2 dir = lastDir;
        if (input.sqrMagnitude > 0.0001f)
        {
            if (Mathf.Abs(input.x) > Mathf.Abs(input.y))
                dir = new Vector2(Mathf.Sign(input.x), 0f);
            else
                dir = new Vector2(0f, Mathf.Sign(input.y));

            lastDir = dir;
        }

        // ์• ๋‹ˆ๋ฉ”์ดํ„ฐ ํŒŒ๋ผ๋ฏธํ„ฐ
        anim.SetFloat("Movex", lastDir.x);
        anim.SetFloat("Movey", lastDir.y);
        anim.SetFloat("speed", input.sqrMagnitude);
    }

    void FixedUpdate()
    {
        rb.linearVelocity = input * moveSpeed;
    }
}

๋!

0๊ฐœ์˜ ๋Œ“๊ธ€