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

 

 

 

์˜ค๋žœ๋งŒ์— ๋‹ค์‹œ ์นด๋ก (Charon) ๊ฒŒ์ž„ ํ”„๋กœ์ ํŠธ ๊ธ€์„ ์˜ฌ๋ฆฌ๋Š” ๊ฒƒ ๊ฐ™๋„ค์š”. ๊ทธ๋™์•ˆ ์ด๊ฒƒ์ €๊ฒƒ ๋˜ ์—ด์‹ฌํžˆ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋น„๋ก ์ปดํ“จํ„ฐ๊ณตํ•™๊ณผ 4ํ•™๋…„์ด์ง€๋งŒ ํ•™๊ณผ MT๋ฅผ ๊ฐ€๋ณด๊ธฐ๋„ ํ•˜๊ณ , ์ถ”์„ ํ• ์ธ ์„ธ์ผ์„ ํ•˜๊ธธ๋ž˜ ์ธํ”„๋Ÿฐ์—์„œ ๊ฐ•์˜ 2๊ฐœ๋ฅผ ์‚ฌ์„œ ์กฐ๊ธˆ์”ฉ ๋ณด๊ธฐ๋„ ํ–ˆ์Šต๋‹ˆ๋‹ค. 

 

์ด์ œ ์Šฌ์Šฌ ์กธ์—… ์ž‘ํ’ˆ ๋ฐœํ‘œ ๊ธฐํ•œ๋„ ๋‹ค๊ฐ€์˜ค๋Š” ์ง€๋ผ, ๊ฐœ๋ฐœ ๊ณ„ํš ๋ฐ ๋ฒ”์œ„๋ฅผ ๋‹ค์‹œ ์žฌ์กฐ์ •ํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค๊ณ  ๋Š๊ปด ์ €๋ฒˆ ์ฃผ์— ํšŒ์˜๋ฅผ ์ง„ํ–‰ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ํ•œ๋™์•ˆ์€ ์นด๋ก (Charon) ํ”„๋กœ์ ํŠธ์™€ ์ฝ”๋”ฉํ…Œ์ŠคํŠธ ๊ฒŒ์‹œ๊ธ€์ด ์ฃผ๋ฅผ ์ด๋ฃจ๊ฒ ๋„ค์š”.

 

์ด๋ฒˆ ์ฃผ์— ์ œ๊ฐ€ ๋งก์€ ๊ฐœ๋ฐœ์€ ์บ๋ฆญํ„ฐ์˜ ๋Œ€์‹œ(Dash) ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ์‚ฌ์‹ค ์ €๋ฒˆ์— ์ด๋ฏธ ๊ตฌํ˜„ํ–ˆ๋˜ ๊ธฐ๋Šฅ์ด์ง€๋งŒ, ๋ฌธ์ œ์ ๋“ค์ด ๋งŽ์•˜๋˜ ๊ด€๊ณ„๋กœ ์ˆ˜์ •์„ ํ•ด ๋‚˜๊ฐ”์ง€์š”.

 

 

์ถ”๊ฐ€) 2023-11-24

๋ณธ ๊ธ€๊ณผ ๊ฐ™์ด ๋งŒ๋“  ๋Œ€์‹œ๋Š” ๋ถ€์ž์—ฐ์Šค๋Ÿฝ๊ธฐ ๋•Œ๋ฌธ์—, ๋ฆฌํŒฉํ† ๋ง์„ ์ง„ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ๋‚ด์šฉ์€ ๐Ÿ”—์—ฌ๊ธฐ์—์„œ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

1. ํ‚ค ๋ฐ”์ธ๋”ฉ๊ณผ ์ด๋ฒคํŠธ ํ•จ์ˆ˜ ๋“ฑ๋ก

 

๋Œ€์‹œ๋Š” ์ŠคํŽ˜์ด์Šค ๋ฐ”(Space bar)๋กœ ํ‚ค ์ž…๋ ฅ์„ ๋ฐ›์„ ๊ฒ๋‹ˆ๋‹ค. ActionInput์—์„œ ๋Œ€์‹œ์™€ ๊ด€๋ จ๋œ ํ‚ค ๋ฐ”์ธ๋”ฉ์„ ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

๋Œ€์‹œ ํ‚ค ๋ฐ”์ธ๋”ฉ

 

๊ทธ๋ฆฌ๊ณ  PlayerController ์Šคํฌ๋ฆฝํŠธ์— ์ž…๋ ฅ ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•  ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

public void OnDashInput(InputAction.CallbackContext context)
{
    if (context.performed)
    {
        ...
    }
}

 

๊ทธ๋ฆฌ๊ณ  ์บ๋ฆญํ„ฐ์— ๋ถ™์–ด ์žˆ๋Š” Player Input ์ปดํฌ๋„ŒํŠธ์—์„œ ์ด๋ฒคํŠธ ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

 

 

 


2. ๋ฐ์ดํ„ฐ ๊ณ„์‚ฐ๊ณผ ์ ์šฉ์˜ ๋ถ„๋ฆฌ (Refactoring)

 

์ด์ „์—๋Š” Move() ํ•จ์ˆ˜์—์„œ ๊ฒฝ์‚ฌ๋กœ์ธ์ง€ ์•„๋‹Œ์ง€๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ๋ฒกํ„ฐ๋ฅผ ๊ณ„์‚ฐํ•˜๊ณ  ๊ทธ ๊ฐ’์„ ์ ์šฉํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ฒฝ์‚ฌ๋กœ์—์„œ๋„ ๋Œ€์‹œ(Dash)๋ฅผ ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๊ธฐ์—, ๊ณ„์‚ฐ๋œ ๋ฒกํ„ฐ๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ €๋Š” Move() ํ•จ์ˆ˜์— ์žˆ๋˜ ๋ฒกํ„ฐ ๊ณ„์‚ฐ ๋ถ€๋ถ„์„ ๋–ผ์–ด์™€, ์ƒˆ๋กœ์šด ๋ฉ”์†Œ๋“œ๋กœ ๋งŒ๋“ค์–ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

protected PlayerState playerState;         // ์บ๋ฆญํ„ฐ์˜ ์ƒํƒœ
protected Vector3 inputDirection;          // ํ‚ค๋ณด๋“œ ์ž…๋ ฅ์œผ๋กœ ๋“ค์–ด์˜จ ์ด๋™ ๋ฐฉํ–ฅ
protected Vector3 calculatedDirection;     // ๊ฒฝ์‚ฌ ์ง€ํ˜• ๋“ฑ์„ ๊ณ„์‚ฐํ•œ ์ด๋™ ๋ฐฉํ–ฅ
protected Vector3 gravity;                 // ์ค‘๋ ฅ
private bool isOnSlope;
private bool isGrounded;


protected Vector3 GetDirection(float currentMoveSpeed)
{
    isOnSlope = IsOnSlope();
    isGrounded = IsGrounded();
    Vector3 calculatedDirection = 
                           CalculateNextFrameGroundAngle(currentMoveSpeed) < maxSlopeAngle ? 
                           inputDirection : Vector3.zero;

    calculatedDirection = (isGrounded && isOnSlope) ? 
    AdjustDirectionToSlope(calculatedDirection) : calculatedDirection.normalized;
    
    return calculatedDirection;
}


protected void ControlGravity()
{
    gravity = Vector3.down * Mathf.Abs(rigidBody.velocity.y);

    if (isGrounded && isOnSlope)
    {
        gravity = Vector3.zero;
        rigidBody.useGravity = false;
        return;
    }
    
    rigidBody.useGravity = true;
}
void Update()
{
    calculatedDirection = GetDirection(player.MoveSpeed * CONVERT_UNIT_VALUE);
    ControlGravity();
}

void FixedUpdate()
{
    Move(calculatedDirection, player.MoveSpeed * CONVERT_UNIT_VALUE);
}

 

๊ธฐ์กด์— ์žˆ๋˜ ๋ฉ”์†Œ๋“œ๋“ค์˜ ๋ณ€๊ฒฝ๋œ ๋ฒ„์ „์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋”๋ณด๊ธฐ
protected void Move(Vector3 moveDirection, float currentMoveSpeed)
{
    if (playerState != PlayerState.MOVE)
        return;

    float animationPlaySpeed = DEFAULT_ANIMATION_PLAYSPEED +
                               GetAnimationSyncWithMovement(currentMoveSpeed);
    LookAt(inputDirection);
    rigidBody.velocity = moveDirection * currentMoveSpeed + gravity;
    animator.SetFloat("Velocity", animationPlaySpeed);
}


public void OnMoveInput(InputAction.CallbackContext context)
{
    Vector2 input = context.ReadValue<Vector2>();
    inputDirection = new Vector3(input.x, 0f, input.y);
}


protected void LookAt(Vector3 direction)
{
    if (direction != Vector3.zero)
    {
        Quaternion targetAngle = Quaternion.LookRotation(direction);
        rigidBody.rotation = targetAngle;
    }
}

 

์œ„์™€ ๊ฐ™์ด ๊ณ„์‚ฐํ•˜๋Š” ๋ถ€๋ถ„๊ณผ ์‹ค์ œ๋กœ ์บ๋ฆญํ„ฐ ํ–‰๋™์— ์ ์šฉ๋˜๋Š” ๋ฉ”์†Œ๋“œ ๋ถ€๋ถ„์œผ๋กœ ๋ถ„๋ฆฌํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ, ๋Œ€์‹œ(Dash)์—์„œ๋„ ๊ณตํ†ต์ ์œผ๋กœ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋“ค์„ ์ค‘๋ณต ๊ณ„์‚ฐํ•  ํ•„์š”์—†์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ์ž…๋ ฅ ๋ฒกํ„ฐ๊ฐ€ inputDirection๊ณผ calculatedDirection ์ด๋ ‡๊ฒŒ ๋‘ ๊ฐœ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

calculatedDirection์€ ๊ฒฝ์‚ฌ๋กœ ๋“ฑ์—์„œ ํˆฌ์˜๋œ ๋ฒกํ„ฐ์ผ ์ˆ˜ ์žˆ๊ธฐ์—, ์บ๋ฆญํ„ฐ๊ฐ€ ๋ฐ”๋ผ๋ณด๋Š” ๋ฐฉํ–ฅ์„ ํ•ด๋‹น ๋ฒกํ„ฐ๋กœ ํ•˜๊ฒŒ ๋˜๋ฉด ๋ถˆํ•„์š”ํ•œ ํšŒ์ „์„ ํ•˜๊ฒŒ ๋˜๋Š” ๋“ฑ์˜ ์•Œ ์ˆ˜ ์—†๋Š” ๋™์ž‘์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์›๋ณธ ๋ฒกํ„ฐ๋ฅผ ๋ณด์กดํ•ด๋‘๋Š” ๊ฒƒ์ด ์ข‹๊ฒ ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

 

 


3. ์ฝ”๋ฃจํ‹ด(Coroutine)์„ ์ด์šฉํ•˜์—ฌ ๋Œ€์‹œ ๊ธฐ๋Šฅ ๋งŒ๋“ค๊ธฐ

 

์šฐ์„  enum์„ ์ด์šฉํ•˜์—ฌ, ์บ๋ฆญํ„ฐ์˜ ์—ฌ๋Ÿฌ ์ƒํƒœ๋“ค์„ ์ •์˜ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

public enum PlayerState
{
    MOVE,       // ํ‰์ƒ ์‹œ ์ƒํƒœ(Idle ๋ฐ Move๊ฐ€ ๊ฐ€๋Šฅ)
    DASH,       // ๋Œ€์‹œ ์ƒํƒœ
    NDASH,      // N๋‹จ ๋Œ€์‹œ๊ฐ€ ๊ฐ€๋Šฅํ•  ๊ฒฝ์šฐ์˜ ์ƒํƒœ
}

protected PlayerState playerState;

 

๊ทธ๋ฆฌ๊ณ  ๋Œ€์‹œ์™€ ๊ด€๋ จ๋œ ๋ณ€์ˆ˜๋“ค์„ ์„ ์–ธํ•˜์˜€๋Š”๋ฐ, ๊ฝค๋‚˜ ๋งŽ๋”๊ตฐ์š”..

[Header("๋Œ€์‹œ(Dash) ์˜ต์…˜")]
//[Header("์ฃผ์˜) DashForwardRollTime + DashReInputTime = 0.4์ดˆ๋ฅผ ์ง€์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค.")]
[SerializeField, Tooltip("๋Œ€์‹œ(Dash)์˜ ํž˜์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ’์ž…๋‹ˆ๋‹ค.")]
protected float dashPower;

[SerializeField, Tooltip("๋Œ€์‹œ(Dash) ์•ž๊ตฌ๋ฅด๊ธฐ ๋ชจ์…˜ ์‹œ๊ฐ„")]
protected float dashForwardRollTime;
    
[SerializeField, Tooltip("๋Œ€์‹œ(Dash) ์‹œ์ž‘ ํ›„, ๋‹ค์‹œ ๋Œ€์‹œ ์ž…๋ ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์‹œ๊ฐ„")]
protected float dashReInputTime;
    
[SerializeField, Tooltip("๋Œ€์‹œ(Dash) ํ›„, ๊ฒฝ์ง ์‹œ๊ฐ„")]
protected float dashTetanyTime;
    
[SerializeField, Tooltip("๋Œ€์‹œ(Dash) ์žฌ์‚ฌ์šฉ ๋Œ€๊ธฐ์‹œ๊ฐ„")]
protected float dashCoolTime;

private WaitForSeconds DASH_FORWARD_ROLL_TIME;
private WaitForSeconds DASH_RE_INPUT_TIME;
private WaitForSeconds DASH_TETANY_TIME;
private Coroutine dashCoroutine;
private Coroutine dashCoolTimeCoroutine;
private int currentDashCount;

 

 

 

์šฐ์„  ํ‚ค ์ž…๋ ฅ์„ ๋ฐ›๋Š” ๋ถ€๋ถ„๋ถ€ํ„ฐ ์ž‘์—…์„ ๋“ค์–ด๊ฐ€๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

public void OnDashInput(InputAction.CallbackContext context)
{
    if (context.performed)
    {
        bool isAvailableDash = 
        playerState != PlayerState.DASH && currentDashCount < player.DashCount && isGrounded;

        if (isAvailableDash)
        {
            playerState = PlayerState.DASH;
            currentDashCount++;

            if (dashCoroutine != null && dashCoolTimeCoroutine != null)
            {
                StopCoroutine(dashCoroutine);
                StopCoroutine(dashCoolTimeCoroutine);
            }

            dashCoroutine = StartCoroutine(DashCoroutine());
        }
    }
}

 

์–ด๋ ค์šด ์ฝ”๋“œ๋Š” ์•„๋‹ ๊ฑฐ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ N๋‹จ ๋Œ€์‹œ๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ƒํ™ฉ์ด๋ผ๋ฉด, ๋‹ค์‹œ ํ‚ค ์žฌ์ž…๋ ฅ์„ ๋ฐ›์•˜์„ ๋•Œ ์ฝ”๋ฃจํ‹ด์„ ์ค‘์ง€ํ•˜๊ณ  ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ์ด๊ฒ ๋„ค์š”.

 

์ด์ œ ์‹ค์งˆ์ ์ธ ๋กœ์ง์ด ๋“ค์–ด์žˆ๋Š” ์ฝ”๋ฃจํ‹ด ๋ถ€๋ถ„์„ ๋ณผ ๊ฑด๋ฐ, ๊ทธ ์ „์— ์• ๋‹ˆ๋ฉ”์ด์…˜๊ณผ ๊ด€๋ จํ•˜์—ฌ ์„ธํŒ…์ด ๊ถ๊ธˆํ•˜์‹  ๋ถ„์€ ์•„๋ž˜์— ๋”๋ณด๊ธฐ๋ž€์— ๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€ ์‚ฌ์šฉํ•œ ๋Œ€์‹œ ๋ชจ์…˜์€ ๐Ÿ”—์•ž๊ตฌ๋ฅด๊ธฐ์ด๊ตฌ์š”.

 

๋”๋ณด๊ธฐ
  • Dash(Trigger) ๋ณ€์ˆ˜์™€ IsDashing(Bool) ๋งค๊ฐœ๋ณ€์ˆ˜ ์ถ”๊ฐ€

 

  • FBX ํŒŒ์ผ ๋ฆฌ๊น… ๋ฐ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์„ค์ •

 

  • Move  →  Dash ํŠธ๋žœ์ง€์…˜

 

  • Dash  →  Dash ํŠธ๋žœ์ง€์…˜ (N๋‹จ ๋Œ€์‹œ๋ฅผ ์œ„ํ•ด ํ•„์š”)

 

  • Dash  →  Move ํŠธ๋žœ์ง€์…˜

 

*์• ๋‹ˆ๋ฉ”์ดํ„ฐ ์ปดํฌ๋„ŒํŠธ์˜ Apply Root Motion ๋ถ€๋ถ„์„ ์ฒดํฌ ํ•ด์ œ ํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

 

์ €๋Š” RigidBody.velocity์˜ ์†๋„๊ฐ’์„ ์ˆœ๊ฐ„์ ์œผ๋กœ ์กฐ์ •ํ•˜์—ฌ ๋น ๋ฅด๊ฒŒ ์ด๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

rigidBody.velocity = dashDirection * dashPower; ๋ถ€๋ถ„์— ์ด๋™์†๋„๋„ ๊ณฑํ•ด์ค˜์•ผ ์บ๋ฆญํ„ฐ ์ด๋™์†๋„์— ๋”ฐ๋ผ ๋Œ€์‹œ ๊ฑฐ๋ฆฌ๊ฐ€ ์œ ๋™์ ์œผ๋กœ ๋ณ€ํ• ํ…๋ฐ, ๊ทธ ๋ถ€๋ถ„์„ ๋นผ๋จน์—ˆ๋„ค์š”.

void Start()
{
    DASH_FORWARD_ROLL_TIME = new WaitForSeconds(dashForwardRollTime);
    DASH_RE_INPUT_TIME = new WaitForSeconds(dashReInputTime);
    DASH_TETANY_TIME = new WaitForSeconds(dashTetanyTime);
}

private IEnumerator DashCoroutine()
{
    Vector3 LookAtDirection = (inputDirection == Vector3.zero) ? transform.forward : inputDirection;
    Vector3 dashDirection = (calculatedDirection == Vector3.zero) ? transform.forward : calculatedDirection;

    animator.SetFloat("Velocity", 0f);         // Move ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์žฌ์ƒ๋˜๋ฉด ์•ˆ ๋˜๋ฏ€๋กœ 0์œผ๋กœ
    animator.SetBool("IsDashing", true);
    animator.SetTrigger("Dash");
    LookAt(LookAtDirection);
    rigidBody.velocity = dashDirection * dashPower;

    yield return DASH_FORWARD_ROLL_TIME;       // ๋Œ€์‹œ ์•ž๊ตฌ๋ฅด๊ธฐ ๋ชจ์…˜ ์‹œ๊ฐ„
    playerState = (player.DashCount > 1 && currentDashCount < player.DashCount) ? PlayerState.NDASH : PlayerState.DASH;
        
    yield return DASH_RE_INPUT_TIME;           // N๋‹จ ๋Œ€์‹œ๊ฐ€ ๊ฐ€๋Šฅํ•  ๋•Œ, ํ‚ค ์ž…๋ ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์‹œ๊ฐ„
    animator.SetBool("IsDashing", false);
    rigidBody.velocity = Vector3.zero;

    yield return DASH_TETANY_TIME;             // ๋Œ€์‹œ ํ›„, ๊ฒฝ์ง ์‹œ๊ฐ„
    playerState = PlayerState.MOVE;

    dashCoolTimeCoroutine = StartCoroutine(DashCoolTimeCoroutine());   // ๋Œ€์‹œ ์ฟจํƒ€์ž„ ์ฒดํฌ ์‹œ์ž‘
}


private IEnumerator DashCoolTimeCoroutine()
{
    float currentTime = 0f;
    while (true)
    {
        currentTime += Time.deltaTime;
        if (currentTime >= dashCoolTime)
            break;
        yield return null;
    }

    if (currentDashCount == player.DashCount)
        currentDashCount = 0;
}

 

Unity Engine์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์€ 30ํ”„๋ ˆ์ž„์ด 1์ดˆ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค. ๋Œ€์‹œ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด 35ํ”„๋ ˆ์ž„ ์ฏค ๋˜๋‹ˆ๊นŒ 1์ดˆ ์–ธ์ €๋ฆฌ๊ฒ ๋„ค์š”. ๋Œ€์‹œ๊ฐ€ ์กฐ๊ธˆ ๋” ๋นจ๋ž์œผ๋ฉด ํ•˜๋Š” ๋ง˜์— ๋Œ€์‹œ ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ์žฌ์ƒ ์†๋„๋ฅผ 2๋ฐฐ์†์œผ๋กœ ํ•ด์ฃผ์—ˆ๋Š”๋ฐ, ๊ทธ๋ ‡๋‹ค๋ฉด ๋Œ€๋žต 0.4~0.5์ดˆ๊ฐ€ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ธธ์ด๊ฐ€ ๋  ๊ฒ๋‹ˆ๋‹ค.

 

๋Œ€์‹œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์ƒ์„ ํŠธ๋ฆฌ๊ฑฐ(Trigger)๋กœ ํ•˜์˜€๋Š”๋ฐ, ์ด๋ ‡๊ฒŒ ํ•˜๋‹ˆ ๊ธฐ์กด์— ์—ฐ๊ฒฐ๋˜์—ˆ๋˜ Move ๋…ธ๋“œ๋กœ ๊ฐ”๋‹ค๊ฐ€ ๋‹ค์‹œ ๋Œ์•„์˜ค๋”๋ผ๊ตฌ์š”. ๊ทธ๋ž˜์„œ N๋‹จ ๋Œ€์‹œ๊ฐ€ ๊ฐ€๋Šฅํ•  ๋•Œ๋Š” Dash ๋…ธ๋“œ์—์„œ ๋ฒ—์–ด๋‚˜์ง€ ์•Š๋„๋ก IsDashing์ด๋ผ๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜ Bool ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์กฐ์ •ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ํ•˜๊ณ  ๋‚˜๋ฉด, ๋Œ€์‹œ ๊ธฐ๋Šฅ์€ ๋Œ€๊ฐ• ์™„์„ฑ์ด ๋ฉ๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด๋ฉฐ ์กฐ์ž‘๊ฐ์— ๋ถˆํŽธํ•จ์€ ์—†๋Š”์ง€, ์ด์ƒํ•œ ๋ฒ„๊ทธ๋Š” ์—†๋Š”์ง€ ์ฒดํฌ๋งŒ ํ•˜๋ฉด ๋˜๊ฒ ๋„ค์š”.

 

 


๊ตฌํ˜„๋œ ๋ชจ์Šต

 

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜ต์…˜๋“ค์„ ์„ธํŒ…ํ•˜๊ณ  ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•ด๋ดค์Šต๋‹ˆ๋‹ค.

 

 

1๋‹จ ๋Œ€์‹œ

 

์ œ ์‹ค๋ ฅ์ด ๋›ฐ์–ด๋‚œ ๊ฒƒ์ด ์•„๋‹ˆ๊ธฐ์— 100% ๋งŒ์กฑํ•  ์ˆ˜์ค€์€ ์•„๋‹ˆ์ง€๋งŒ, ๊ทธ๋ž˜๋„ ์ด ์ •๋„๋ฉด ์ž˜ ๋งŒ๋“ค์–ด ์ง„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. 

๋Œ€์‹œ๊ฐ€ ๋„ˆ๋ฌด ๋ถ€์ž์—ฐ์Šค๋Ÿฌ์šด ๊ฒƒ ๊ฐ™์•„, ๐Ÿ”—๋’ท ๊ธ€์—์„œ ๋ฆฌํŒฉํ† ๋ง์„ ์ง„ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

 


๋Š˜ ๋‚˜๋ฅผ ๋ฐ˜๊ฒจ์ฃผ๋Š” ๋ฒ„๊ทธ๋“ค

 

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

 

์ฒซ ๋ฒˆ์งธ ๋ฒ„๊ทธ  |  ๊ฒฝ์‚ฌ๋กœ์—์„œ ๋Œ€์‹œ๋ฅผ ํ•˜๋ฉด ํŠ€์–ด์˜ค๋ฅด๋Š” ๋ฒ„๊ทธ

 

์ฒซ ๋ฒˆ์งธ ๋ฒ„๊ทธ

 

์ฒ˜์Œ์—๋Š” ๋ฒกํ„ฐ๊ฐ€ ์ด์ƒํ•˜๊ฒŒ ๊ณ„์‚ฐ๋˜์—ˆ๋‚˜ ์ƒ๊ฐ์ด ๋“ค์–ด์„œ, ๊ธฐ์ฆˆ๋ชจ๋กœ ํ‘œ์‹œํ•ด๋ดค์ง€๋งŒ ๊ทธ๋‹ฅ ์ด์ƒํ•œ ์ ์€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋”˜๊ฐ€์— ๋ถ€๋”ชํ˜€์„œ ํŠ•๊ฒจ์ ธ ๋‚˜๊ฐ„๋‹ค๋Š” ์˜๋ฏธ๊ฐ€ ๋˜๋Š”๋ฐ, ์™œ ์ด๋Ÿด๊นŒ ํ•œ์ฐธ๋™์•ˆ ์ƒ๊ฐํ•˜๋‹ค๊ฐ€ ์›์ธ์„ ๊ฒจ์šฐ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค.

 

์›์ธ ๋ฐœ๊ฒฌ

 

๊ณ„๋‹จ ์˜ค๋ธŒ์ ํŠธ๋“ค์„ ์„œ๋กœ ์ด์–ด์ค€ ๊ฒƒ์ด๋ผ, ์ œ๋Œ€๋กœ ์ž˜ ์ด์–ด์ง€์ง€ ์•Š์•„ ์œ„์™€ ๊ฐ™์ด ์ฝœ๋ผ์ด๋”๊ฐ€ ์–ด๊ธ‹๋‚˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์–ด๊ธ‹๋‚˜์ง€ ์•Š๋„๋ก ์ž˜ ์ด์–ด์ฃผ๋˜๊ฐ€, ๊ณ„๋‹จ ๋ฐฐ์น˜๋ฅผ ๋‹ค ํ•˜๊ณ  ํ•˜๋‚˜์˜ ์ฝœ๋ผ์ด๋”๋กœ ๊ทธ๋ƒฅ ๋‹ค ์ฑ„์šฐ๋˜๊ฐ€ ํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

์ฒซ ๋ฒˆ์งธ ๋ฒ„๊ทธ ํ•ด๊ฒฐ ์™„๋ฃŒ

 

๋‘ ๋ฒˆ์งธ ๋ฒ„๊ทธ  |  ๋Œ€์‹œ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐœ๋™ ์‹œ, ๋ฒ„๋ฒ…์ด๋Š” ๋ฒ„๊ทธ

 

 

์ด ๋ถ€๋ถ„์€ ๋Œ€์‹œ ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ Has Exit Time์„ ์ฒดํฌ ํ•ด์ œ ํ•ด์ฃผ์ง€ ์•Š์•„์„œ ๊ณ„์† ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹ฑํฌ๊ฐ€ ๋’ค๋กœ ๋ฐ€๋ฆฌ๋Š” ๊ฒ๋‹ˆ๋‹ค.

Has Exit Time์„ ์ฒดํฌ ํ•ด์ œํ•ด๋ฒ„๋ฆฌ๋ฉด, ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋‹ค ์žฌ์ƒ๋˜๊ธฐ๋„ ์ „์— ์ƒˆ๋กœ ์žฌ์ƒ๋˜์–ด ๋ฒ„๋ฆฌ๋‹ˆ ์–ด๋Š ์ •๋„ ์žฌ์ƒ์ด ๋œ ํ›„์— ๋Œ€์‹œ ์ž…๋ ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ € ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ์œ„์—์„œ ์ฝ”๋ฃจํ‹ด์„ ์ด์šฉํ•˜์—ฌ ์ ์šฉํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

 

์„ธ ๋ฒˆ์งธ ๋ฒ„๊ทธ  |  ๋ฌผ๋ฆฌ์™€ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ฐ„์˜ ์‹ฑํฌ๊ฐ€ ์•ˆ ๋งž๋Š” ๋ถ€๋ถ„

 

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

๋‹ค์Œ์„ ๋ณด๋ฉด ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์ƒ ์‹œ๊ฐ„๋ณด๋‹ค ๋Œ€์‹œ์˜ ๋ฌผ๋ฆฌ ์ง€์†์‹œ๊ฐ„์ด ๋” ๊ธธ์–ด, ๋ฏธ๋„๋Ÿฌ์ง€๋Š” ๋ชจ์Šต์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์‹ฑํฌ ๋งž์ถ”๊ธฐ ์ „

 

๋‹ค์Œ์€ ์‹ฑํฌ๋ฅผ ๋งž์ถ˜ ๋ถ€๋ถ„์ธ๋ฐ, ์‚ฌ์‹ค ์กฐ๊ธˆ ๋” ๊ธธ๊ฒŒ ์žก์•„์•ผ ์•Œ๋งž์€ ๋ชจ์Šต์ด๊ธด ํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋” ๊ธธ๊ฒŒ ์žก์œผ๋ฉด, N๋‹จ ๋Œ€์‹œ๋ฅผ ํ•  ๋•Œ ์กฐ์ž‘๊ฐ์ด ๋ถˆํŽธํ•ด์ง€๋Š” ๋ถ€๋ถ„์ด ์žˆ์–ด ์ด ๋ถ€๋ถ„์€ ์ด ์ •๋„๋กœ ํƒ€ํ˜‘ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

์‹ฑํฌ ๋งž์ถ˜ ํ›„

 

 

๋„ค ๋ฒˆ์งธ ๋ฒ„๊ทธ  |  ๋Œ€์‹œ ์ด๋™ ๋ฐฉํ–ฅ๊ณผ ๋ฐ”๋ผ๋ณด๋Š” ๋ฐฉํ–ฅ์ด ๋‹ค๋ฅธ ๋ฒ„๊ทธ

 

์ด ๋ฒ„๊ทธ๋Š” ์ด๋™ ํ‚ค์™€ ์ŠคํŽ˜์ด์Šค ๋ฐ”๋ฅผ ๋™์‹œ์— ๋ˆŒ๋ €๋‹ค๊ฐ€ ๋–ผ๋ฉด ์•„์ฃผ ๊ฐ€๋” ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ํ‚ค ์ž…๋ ฅ๋“ค์ด ๊ผฌ์—ฌ์„œ ๋ฐœ์ƒํ•˜๋Š” ๊ฑฐ์ฃ .

 

 

ํ•˜์ง€๋งŒ ์ด๋™ ํ‚ค์™€ ์ŠคํŽ˜์ด์Šค ๋ฐ”๋ฅผ ๋™์‹œ์— ๋ˆŒ๋ €๋‹ค ๋–ผ๋ฉด์„œ ๊ฒŒ์ž„ ํ”Œ๋ ˆ์ด ํ•˜๋Š” ์‚ฌ๋žŒ์„ ์—†์„ ๊ฒƒ์ด๊ธฐ์— ์ด ๋ถ€๋ถ„์€ ๋‚ด๋ฒ„๋ ค ๋‘๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

 

๋งˆ๋ฌด๋ฆฌ

 

๊ธ€์ด ์–ด์ฉŒ๋‹ค๋ณด๋‹ˆ ๊ธธ์–ด์กŒ๋„ค์š”. ๊ฐ„๋‹จํ•˜๋‹ค๋ฉด ๊ฐ„๋‹จํ•œ ๊ธฐ๋Šฅ์ผ ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ, ์ตœ๋Œ€ํ•œ ๋ฒ„๊ทธ์—†์ด ๊ตฌํ˜„ํ•˜๋ ค๊ณ  ์—ด์‹ฌํžˆ ์ƒ๊ฐ์„ ํ–ˆ๋˜ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ๊ธ€์—์„œ ์ฐพ์•„๋ต™๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค! ๊ธด ๊ธ€ ์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ด์š”!

 

 

 

728x90
๋ฐ˜์‘ํ˜•