๋ณธ๋ฌธ์œผ๋กœ ๋ฐ”๋กœ๊ฐ€๊ธฐ
728x90

 

 

 

ํ•™๊ต์—์„œ ์ผ์ฃผ์ผ๊ฐ„ ์ง„ํ–‰ํ–ˆ๋˜ ๊ฒŒ์ž„ ๊ต์œก ํŠน๊ฐ•์„ ๋“ฃ๊ณ , ์„ค ์—ฐํœด๋„ ๊ฒน์ณ์„œ ์ž‘์—… ์Šค์ผ€์ฅด์ด ๋‹ค์†Œ ๋ฐ€๋ ธ๋‹ค. ์„ค ์—ฐํœด๊ฐ€ ๋๋‚œ ํ›„์— ํšŒ์˜๋ฅผ ์ง„ํ–‰ํ–ˆ๊ณ , ํ”„๋กœ์ ํŠธ ์ข…๋ฃŒ์ผ์ธ 2์›” ๋ง๊นŒ์ง€ ์–ผ๋งˆ ๋‚จ์ง€ ์•Š์€ ํƒ“์— ์„ธ๋ถ€์ ์ธ ๋””ํ…Œ์ผ์€ ํฌ๊ธฐํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

 

์บ๋ฆญํ„ฐ๊ฐ€ ์ˆจ๋Š” ๋ชจ์…˜, ์ ์ด ์ฐพ๋Š” ์‹œ๋Š‰์„ ํ•˜๋Š” ๋ชจ์…˜, ๋ฌธ ์—ด๋ฆฌ๊ฑฐ๋‚˜ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๋ชจ์…˜ ๋“ฑ์ด ์žˆ์œผ๋ฉด ๊ฒŒ์ž„ ์™„์„ฑ๋„๋Š” ์˜ฌ๋ผ๊ฐ€์ง€๋งŒ ์‹œ๊ฐ„์ด ๋ถ€์กฑํ•˜๋‹ค. ๋””์ž์ด๋„ˆ ๋‹˜๋„ ํ•œ ๋ถ„๋ฐ–์— ์—†๋‹ค๋ณด๋‹ˆ UI์™€ ๋ฐฐ๊ฒฝ์ž‘์—…๋„ ํ•˜์…”์•ผ ํ•˜๋Š”๋ฐ ๊ทธ๊ฑฐ๊นŒ์ง€ ํ•  ์‹œ๊ฐ„์ด ์—†์œผ์‹ค ๊ฒƒ ๊ฐ™๋‹ค.

 

๊ทธ๋ž˜์„œ, ์šฐ์„  ๊ฒŒ์ž„ ํ”Œ๋ ˆ์ด์— ํ•„์ˆ˜์ ์ธ ์š”์†Œ๋“ค๋งŒ ๋จผ์ € ๋น ๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค. ์ €๋ฒˆ ๊ธ€์—์„œ ์ฃผ์ธ๊ณต ์บ๋ฆญํ„ฐ์˜ Idle, Walk ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ž‘์—…ํ–ˆ๋Š”๋ฐ, ๋‹ค์Œ ์• ๋‹ˆ๋ฉ”์ด์…˜์€ ๋‹ฌ๋ฆฌ๊ธฐ(Run)๋‹ค.

 

 

 

1. ๋‹ฌ๋ฆฌ๊ธฐ(Run) ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ œ์ž‘ํ•˜๊ธฐ

 

๊ฑท๊ธฐ(Walk)๋ฅผ ํ•œ ๋ฒˆ ๋งŒ๋“ค์–ด๋ดค๋˜ ํƒ“์ธ์ง€, ์ต์ˆ™ํ•ด์ ธ์„œ ๋‹ฌ๋ฆฌ๊ธฐ(Run) ๋ชจ์…˜์€ ๊ทธ๋ฆฌ ์˜ค๋ž˜ ๊ฑธ๋ฆฌ์ง€ ์•Š์•˜๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋‹ฌ๋ฆฌ๊ธฐ ๋ชจ์…˜์„ ํ”„๋ ˆ์ž„๋ณ„๋กœ ๋‚˜ํƒ€๋‚ธ ๊ทธ๋ฆผ์„ ์ฐธ๊ณ ํ•˜์—ฌ ๋งŒ๋“ค์–ด๋ดค๋‹ค. 2D Bone Animation์˜ ํ•œ๊ณ„๋กœ ์™ผ์† ๋ชจ์–‘์€ ์–ด์ฉ”์ˆ˜๊ฐ€ ์—†์—ˆ๋‹ค.

 

0 ํ”„๋ ˆ์ž„

 

5 ํ”„๋ ˆ์ž„

 

10 ํ”„๋ ˆ์ž„

 

15 ํ”„๋ ˆ์ž„

 

20 ํ”„๋ ˆ์ž„

 

25 ํ”„๋ ˆ์ž„

 

30 ํ”„๋ ˆ์ž„

 

35 ํ”„๋ ˆ์ž„

 

40 ํ”„๋ ˆ์ž„

 

 

๋‹ฌ๋ฆฌ๊ธฐ ๋ชจ์…˜์ด๋‹ค๋ณด๋‹ˆ, ์กฐ๊ธˆ ๋น ๋ฅด๊ฒŒ ์›€์ง์—ฌ์•ผ ํ•˜๋ฏ€๋กœ 5 ํ”„๋ ˆ์ž„ ๋‹จ์œ„๋กœ ๊ตฌ์„ฑํ–ˆ๋‹ค. ๋‹ฌ๋ฆฌ๊ธฐ๋ฅผ ํ•  ๋•Œ ์ƒ์ฒด๋Š” ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ˆ™์—ฌ์ง€๋ฏ€๋กœ ์ˆ™์˜€๊ณ , ๋‹ค๋ฆฌ๊ฐ€ ๊ต์ฐจํ•˜๋ฉฐ ๋ฐ”๋‹ฅ์— ๋‹ฟ์ผ ๋•Œ๋งˆ๋‹ค ์ƒ์ฒด ๋ผˆ๋ฅผ ์›€์ง์—ฌ ๋ฐ˜๋™์„ ์คฌ๋‹ค. ์˜ค๋ฅธ์†์€ ํœด๋Œ€ํฐ์„ ์ฅ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋›ฐ๋ฉด์„œ ์˜ค๋Š” ๋ชธ์˜ ๋ฐ˜๋™์œผ๋กœ ์ธํ•œ ์•ฝ๊ฐ„์˜ ์›€์ง์ž„๋งŒ ์คฌ๋‹ค. ๋งŒ๋“œ๋Š”๋ฐ 30๋ถ„๋„ ์•ˆ ๊ฑธ๋ ธ๋˜ ๊ฒƒ ๊ฐ™๋‹ค.

 

๋‹ฌ๋ฆฌ๊ธฐ ์• ๋‹ˆ๋ฉ”์ด์…˜

 

 

์• ๋‹ˆ๋ฉ”์ดํ„ฐ ๊ตฌ์กฐ ๋ณ€๊ฒฝ (Blend Tree ์‚ฌ์šฉ)

 

Idle, Walk, Run ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์ƒ๊ฒผ๋‹ค๋ณด๋‹ˆ, ๊ธฐ์กด ๋ฐฉ๋ฒ•๋Œ€๋กœ๋Š” ๋ณต์žกํ•˜๊ณ  ๋‹ค๋ฃจ๊ธฐ ํž˜๋“ค ๊ฒƒ ๊ฐ™์•˜๋‹ค. ๊ทธ๋ž˜์„œ ๋ธ”๋ Œ๋“œ ํŠธ๋ฆฌ(Blend Tree)๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์„œ "Move"๋ผ๊ณ  ์ด๋ฆ„์„ ์ง€์–ด์คฌ๋‹ค.

 

๊ธฐ์กด ์• ๋‹ˆ๋ฉ”์ด์…˜๋“ค ๊ตฌ์กฐ๋Š” ์‚ญ์ œํ•˜๊ณ , ๋ธ”๋ Œ๋“œ ํŠธ๋ฆฌ๋ฅผ ์ƒ์„ฑ

 

๊ทธ๋ฆฌ๊ณ , Float ํƒ€์ž…์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๊ณ , "Move"๋ผ๊ณ  ์ด๋ฆ„์„ ์ง€์—ˆ๋‹ค. ์ด Move ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์ด 0์ผ ๋• "Idle", 0.5์ผ ๋• "Walk", 1์ผ ๋• "Run"์œผ๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ „ํ™˜์ด ์ผ์–ด๋‚˜๋„๋ก ๊ตฌ์„ฑํ–ˆ๋‹ค.

 

Move ๋ธ”๋ Œ๋“œ ํŠธ๋ฆฌ ๋‚ด๋ถ€ ๊ตฌ์„ฑ ๋ชจ์Šต

 

Move ๋ธ”๋ Œ๋“œ ํŠธ๋ฆฌ Inspector

 

Automate Thresholds ์˜ต์…˜์„ ์ฒดํฌ ํ•ด์ œํ•˜๊ณ , ๊ฐ Threshold ๊ฐ’์— ๊ณ„ํšํ–ˆ๋˜ ๊ฐ’๋“ค์„ ๋„ฃ์—ˆ๋‹ค. ์ด์ œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ์ผ๋งŒ ๋‚จ์•˜๋‹ค.

 

 

 

2. ์Šคํฌ๋ฆฝํŠธ(Script) ์ˆ˜์ •ํ•˜๊ธฐ

 

  • ์™ผ์ชฝ ์‰ฌํ”„ํŠธ(Left Shift)์™€ ๋ฐฉํ–ฅํ‚ค ์ž…๋ ฅ์ด ์žˆ๋‹ค๋ฉด, ๋‹ฌ๋ฆฌ๊ธฐ(Run)
  • ์™ผ์ชฝ ์‰ฌํ”„ํŠธ(Left Shift) ์ž…๋ ฅ์€ ์—†์ง€๋งŒ ๋ฐฉํ–ฅํ‚ค ์ž…๋ ฅ์ด ์žˆ๋‹ค๋ฉด ๊ฑท๊ธฐ(Walk)
  • ๋‘ ์ž…๋ ฅ ๋ชจ๋‘ ์—†๋‹ค๋ฉด ๊ฐ€๋งŒํžˆ ์žˆ๊ธฐ(Idle)

 

ํ˜„์žฌ ๋‹ฌ๋ฆฌ๋Š” ์ƒํƒœ์ธ์ง€๋ฅผ ์ฒดํฌํ•˜๊ธฐ ์œ„ํ•ด boolean ๋ณ€์ˆ˜๋ฅผ ํ•˜๋‚˜ ์ถ”๊ฐ€ํ–ˆ๋‹ค.

private bool isRunning;

 

Update() ํ•จ์ˆ˜์—์„œ ์™ผ์ชฝ ์‰ฌํ”„ํŠธ์— ๋Œ€ํ•œ ์ž…๋ ฅ์„ ๋ฐ›์•˜๋‹ค.

void Update()
{
   walkDirection = Input.GetAxisRaw("Horizontal");
   isRunning = Input.GetButton("Run");    // ์ถ”๊ฐ€
}

 

๋ฌผ๋ก , Input Manager์—์„œ Run ๋ฒ„ํŠผ์— ๋Œ€ํ•œ ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์คฌ๋‹ค. ๊ทธ ๋ถ€๋ถ„์€ ๋ฐ‘์— "๋”๋ณด๊ธฐ" ํด๋ฆญ

๋”๋ณด๊ธฐ

Unity Editor์˜ ์™ผ์ชฝ ์ƒ๋‹จ Edit → Project Settings → Input Manager → Run ํ•„๋“œ ์ถ”๊ฐ€

 

 

 

๊ธฐ์กด์— ์žˆ์—ˆ๋˜ Walk() ํ•จ์ˆ˜๋ฅผ ์‚ญ์ œํ•˜๊ณ , Move() ํ•จ์ˆ˜๋กœ ํ†ตํ•ฉํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ , ์•ฝ๊ฐ„์˜ ๋ฆฌํŒฉํ† ๋ง ๊ณผ์ •์„ ๊ฑฐ์ณค๋‹ค.

   void FixedUpdate()
    {
        bool hasControl = !Mathf.Approximately(walkDirection, 0f);
        TurnOtherSide(hasControl);
        Move(hasControl);
    }

    private void Move(bool hasControl)   // 0f : Idle, 0.5f : Walk, 1f : Run
    {
        if (hasControl && isRunning)
        {
            animator.SetFloat("Move", 1f);
            _rigidBody.velocity = new Vector2(walkDirection * walkSpeed * 2f,
                                              _rigidBody.velocity.y);
            return;
        }

        float walkValue = (hasControl && !isRunning) ? 0.5f : 0f;
        animator.SetFloat("Move", walkValue);
        _rigidBody.velocity = new Vector2(walkDirection * walkSpeed, _rigidBody.velocity.y);
    }

 

์ด๋ ‡๊ฒŒ ํ•จ์œผ๋กœ์จ, ๋‹ฌ๋ฆฌ๊ธฐ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ œ์ž‘ ๋ฐ ์ ์šฉ์ด ์™„๋ฃŒ๋˜์—ˆ๋‹ค. ๋นจ๋ฆฌ ์ ํ”„๋ž‘ ์ƒํ˜ธ์ž‘์šฉ ํ•˜๋Ÿฌ ๊ฐ€์•ผ๊ฒ ๋‹ค...

 

๋‹ฌ๋ฆฌ๊ธฐ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ ์šฉ ์™„๋ฃŒ

 

 

โœ๏ธ์ „์ฒด ์Šคํฌ๋ฆฝํŠธ

๋”๋ณด๊ธฐ
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SujiMoveController : MonoBehaviour
{

    public float walkSpeed;
    public Transform sujiTransform;

    private Animator animator;
    private Rigidbody2D _rigidBody;
    private float walkDirection;
    private float initScaleX;
    private bool isRunning;


    void Start()
    {
        _rigidBody = GetComponent<Rigidbody2D>();
        animator = GetComponentInChildren<Animator>();          
        initScaleX = sujiTransform.localScale.x;
    }

    void Update()
    {
        walkDirection = Input.GetAxisRaw("Horizontal");
        isRunning = Input.GetButton("Run");
    }

    void FixedUpdate()
    {
        bool hasControl = !Mathf.Approximately(walkDirection, 0f);
        TurnOtherSide(hasControl);
        Move(hasControl);
    }

    private void Move(bool hasControl)   // 0f : Idle, 0.5f : Walk, 1f : Run
    {
        if (hasControl && isRunning)
        {
            animator.SetFloat("Move", 1f);
            _rigidBody.velocity = new Vector2(walkDirection * walkSpeed * 2f,
                                              _rigidBody.velocity.y);  
            return;
        }

        float walkValue = (hasControl && !isRunning) ? 0.5f : 0f;
        animator.SetFloat("Move", walkValue);
        _rigidBody.velocity = new Vector2(walkDirection * walkSpeed, _rigidBody.velocity.y);
    }

    private void TurnOtherSide(bool hasControl)
    {
        if (!hasControl)
            return;

        var scaleX = sujiTransform.localScale.x;
        if (Mathf.Approximately(walkDirection * scaleX, initScaleX))
            return;

        var scaleY = sujiTransform.localScale.y;
        var scaleZ = sujiTransform.localScale.z;

        sujiTransform.localScale = new Vector3(-scaleX, scaleY, scaleZ);
    }
}

 

 

728x90
๋ฐ˜์‘ํ˜•