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

 

 

 

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

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

 

 

 


1. ๊ณต๊ฒฉ ํ‚ค ๋ฐ”์ธ๋”ฉ ๋ฐ ์ž…๋ ฅ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌํ•˜๊ธฐ

 

New Input System์˜ "์ƒํ˜ธ ์ž‘์šฉ(Interaction)"

 

๊ณต๊ฒฉ์€ ๋งˆ์šฐ์Šค ์ขŒ ํด๋ฆญ์œผ๋กœ ์ž…๋ ฅ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. Player Input Actions์— ๋“ค์–ด๊ฐ€์„œ ํ•ด๋‹น ํ‚ค ๋ฐ”์ธ๋”ฉ์„ ํ•ด์ฃผ๋„๋ก ํ•˜์ฃ .

 

 

์™ผ์ชฝ ๋งˆ์šฐ์Šค ๋ฒ„ํŠผ์„ ๋ฐ”์ธ๋”ฉ ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ Interactions์— Hold์™€ Press๊ฐ€ ์ถ”๊ฐ€ํ•œ ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฐ์š”.

 

์ƒํ˜ธ์ž‘์šฉ(Interaction)์€ ํ•ด๋‹น ํ‚ค ์ž…๋ ฅ์— ๋Œ€ํ•ด์„œ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•  ๊ฒƒ์ธ์ง€์— ๋Œ€ํ•ด ์„ค์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์ž…๋‹ˆ๋‹ค. ์ƒํ˜ธ ์ž‘์šฉ์€ ์ถ”๊ฐ€ํ•œ ์ˆœ์„œ๋Œ€๋กœ ์šฐ์„  ์ˆœ์œ„๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์‚ฌ์ง„์„ ์˜ˆ๋กœ ๋“ ๋‹ค๋ฉด, HoldPress ์ˆœ์„œ๋Œ€๋กœ ์šฐ์„ ๊ถŒ์„ ๊ฐ€์งˆ ๊ฒ๋‹ˆ๋‹ค.

 

์ €ํฌ ๊ฒŒ์ž„์˜ ๋ฌด๊ธฐ ๊ณต๊ฒฉ ์ข…๋ฅ˜์—๋Š” ์ฐจ์ง• ๊ณต๊ฒฉ(Charging Attack)์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋งˆ์šฐ์Šค ๋ฒ„ํŠผ์„ ์ผ์ • ์‹œ๊ฐ„ ์ด์ƒ ๋ˆ„๋ฅด๊ณ  ์žˆ๋Š”์ง€๋ฅผ ๋จผ์ € ๊ฒ€์‚ฌํ•ด์•ผ ํ•˜์ฃ . ๋”ฐ๋ผ์„œ Hold ์ƒํ˜ธ ์ž‘์šฉ์„ ๋จผ์ € ๊ฒ€์‚ฌํ•˜๋Š” ๊ฒƒ์ด๋ฉฐ, ๋งŒ์•ฝ Hold๊ฐ€ ์‹คํŒจํ•˜๊ฒŒ ๋˜๋ฉด ๋‹ค์Œ ์šฐ์„ ์ˆœ์œ„ ์ƒํ˜ธ์ž‘์šฉ์ธ Press๊ฐ€ ๋ฐœ๋™๋  ๊ถŒํ•œ์„ ์–ป๊ฒŒ ๋  ๊ฒ๋‹ˆ๋‹ค.

 

์ผ๋ฐ˜ ๊ณต๊ฒฉ์˜ ๊ฒฝ์šฐ์—๋Š” ๋งˆ์šฐ์Šค ํด๋ฆญํ•˜๊ณ  ๋—์„ ๋•Œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋˜๋‹ˆ, Press๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  Trigger Behavior๋ฅผ Release Only๋กœ ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ์„ค๋ช…์ด ๊ธธ์–ด์กŒ์ง€๋งŒ, ๋‚ด์šฉ์„ ์š”์•ฝํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

  • ๋ฐ”์ธ๋”ฉํ•œ ํ‚ค์— ๋Œ€ํ•˜์—ฌ ์ž…๋ ฅ์„ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ง€์— ๋Œ€ํ•œ ์˜ต์…˜์„ ์ค„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๊ฑธ ์ƒํ˜ธ์ž‘์šฉ(Interaction)์ด๋ผ๊ณ  ํ•œ๋‹ค.
  • ์ƒํ˜ธ์ž‘์šฉ์€ ์ถ”๊ฐ€ํ•œ ์ˆœ์„œ๋Œ€๋กœ ์šฐ์„  ์ˆœ์œ„๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋œ๋‹ค.
  • ํ˜„์žฌ ์ƒํ˜ธ์ž‘์šฉ์ด ์„ฑ๊ณต์ด ๋˜์—ˆ๋‹ค๋ฉด, ๊ทธ ๋‹ค์Œ ์šฐ์„  ์ˆœ์œ„ ์ƒํ˜ธ์ž‘์šฉ์€ ๊ถŒํ•œ์„ ์–ป์ง€ ๋ชปํ•œ๋‹ค.
    • ex) ์ฐจ์ง• ๊ณต๊ฒฉ์„ ํ•˜๋ ค๊ณ  ๋งˆ์šฐ์Šค ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ณ  ์žˆ์–ด, Hold ์ƒํ˜ธ ์ž‘์šฉ์ด ์„ฑ๊ณตํ–ˆ๋‹ค๋ฉด ๊ทธ ๋‹ค์Œ์ธ Press ์ƒํ˜ธ ์ž‘์šฉ์€ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.
  • ํ˜„์žฌ ์ƒํ˜ธ์ž‘์šฉ์ด ์‹คํŒจํ–ˆ๋‹ค๋ฉด, ๊ทธ ๋‹ค์Œ ์šฐ์„  ์ˆœ์œ„์˜ ์ƒํ˜ธ ์ž‘์šฉ์ด ๊ถŒํ•œ์„ ์–ป์–ด ์‹คํ–‰๋œ๋‹ค.
    • ex) ์ผ๋ฐ˜ ๊ณต๊ฒฉ์„ ์œ„ํ•ด ๋งˆ์šฐ์Šค ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๊ณ  ๋—๋‹ค๋ฉด, Hold ์ƒํ˜ธ ์ž‘์šฉ์„ ์‹คํŒจํ•œ ๊ฒƒ์ด๋ฏ€๋กœ ๊ทธ ๋‹ค์Œ์ธ Press ์ƒํ˜ธ ์ž‘์šฉ์ด ์‹คํ–‰๋œ๋‹ค.

 

 

์ด๋Ÿฌํ•œ ๋‚ด์šฉ์„ ์ˆ™์ง€ํ•œ ์ฑ„๋กœ, ์ด์ œ ๋งˆ์šฐ์Šค ์™ผ์ชฝ ๋ฒ„ํŠผ์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜์—ฌ ๋“ฑ๋กํ•ด์ฃผ๋„๋ก ํ•ฉ์‹œ๋‹ค.

// PlayerController

public void OnClickLeftMouse(InputAction.CallbackContext context)
{
    ...
}

 

์ด๋ฒคํŠธ ํ•จ์ˆ˜ ๋“ฑ๋กํ•˜๊ธฐ

 

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

 

 

 

์ƒํ˜ธ์ž‘์šฉ ๊ฒ€์‚ฌํ•˜์—ฌ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌํ•˜๊ธฐ

 

์ƒํ˜ธ ์ž‘์šฉ ์ž…๋ ฅ ์ฝœ๋ฐฑ์—๋Š” ๋Œ€ํ‘œ์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋„ค ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

  • Waiting  :  ์ƒํ˜ธ ์ž‘์šฉ์ด ์ž…๋ ฅ์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋Š” ์ƒํƒœ
  • Started  :  ์ƒํ˜ธ ์ž‘์šฉ์ด ์‹œ์ž‘๋˜์—ˆ์ง€๋งŒ(์˜ˆ์ƒ ์ž…๋ ฅ ์ค‘ ์ผ๋ถ€๋ฅผ ์ˆ˜์‹ ๋ฐ›์Œ), ์•„์ง ์™„๋ฃŒ๋Š” ์•ˆ ๋œ ์ƒํƒœ
  • Performed  :  ์ƒํ˜ธ ์ž‘์šฉ์ด ์™„์ „ํžˆ ๋‹ค ์ด๋ฃจ์–ด์ง„ ์ƒํƒœ
  • Canceled  :  ์ƒํ˜ธ ์ž‘์šฉ์ด ์ด๋ฃจ์–ด ์ง€๋Š” ๊ณผ์ • ์ค‘ ์กฐ๊ฑด์„ ์ถฉ์กฑํ•˜์ง€ ๋ชปํ•ด ์ค‘๋‹จ๋œ ์ƒํƒœ
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €๋‹ค๊ฐ€ ๋†“๋Š”๋ฐ ํ•„์š”ํ•œ ์ตœ์†Œ ์‹œ๊ฐ„์ด ์žˆ๋Š”๋ฐ ๊ทธ ์‹œ๊ฐ„ ์ „์— ์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์— ์†์„ ๋—€ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

์ด ์ฝœ๋ฐฑ ์ •๋ณด๋ฅผ ์ด์šฉํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์งœ์„œ, ์ฐจ์ง• ๊ณต๊ฒฉ์ผ ๋•Œ์™€ ์ผ๋ฐ˜ ๊ณต๊ฒฉ์ผ ๋•Œ๋ฅผ ๋ถ„๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.

public void OnClickLeftMouse(InputAction.CallbackContext context)
{
    if (context.performed)
    {
        if (context.interaction is HoldInteraction)         // ์ฐจ์ง€ ๊ณต๊ฒฉ
        {
        
        }

        else if (context.interaction is PressInteraction)   // ์ผ๋ฐ˜ ๊ณต๊ฒฉ
        {


        }
    }
}

 

๋งˆ์šฐ์Šค ์™ผ์ชฝ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €๋‹ค๋ฉด ๊ฐ€์žฅ ๋จผ์ € Hold Interaction์ด ์‹คํ–‰๋˜๊ฒ ์ง€์š”. ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์ฐจ์ง• ๊ณต๊ฒฉ์„ ํ•˜๊ธฐ ์œ„ํ•ด ๋งˆ์šฐ์Šค ์™ผ์ชฝ ๋ฒ„ํŠผ์„ ๊ณ„์† ๋ˆ„๋ฅด๊ณ  ์žˆ๋Š”๋‹ค๋ฉด, ํ•ด๋‹น ์ƒํ˜ธ ์ž‘์šฉ์€ ์„ฑ๊ณต์œผ๋กœ ๊ฐ„์ฃผ๋˜์–ด Performed ์ฝœ๋ฐฑ์„ ํ˜ธ์ถœํ•ด์ค„ ๊ฒ๋‹ˆ๋‹ค.

 

ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์ผ๋ฐ˜ ๊ณต๊ฒฉ์„ ํ•˜๊ธฐ ์œ„ํ•ด ๋งˆ์šฐ์Šค ์™ผ์ชฝ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €๋‹ค๊ฐ€ ๋—€๋‹ค๋ฉด, Hold Interaction์˜ ์ฝœ๋ฐฑ์€ Canceled๊ฐ€ ํ˜ธ์ถœ ๋  ๊ฒ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ ๋‹ค์Œ ์ƒํ˜ธ ์ž‘์šฉ์ธ Press Interaction์ด ์‹คํ–‰๋˜๊ฒ ์ง€์š”. ๋ˆŒ๋ €๋‹ค ๋—์œผ๋‹ˆ ์„ฑ๊ณตํ–ˆ์œผ๋ฏ€๋กœ Performed๊ฐ€ ํ˜ธ์ถœ๋  ๊ฒ๋‹ˆ๋‹ค.

 

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

 

 

 


2. ๋งˆ์šฐ์Šค ์›”๋“œ ์ขŒํ‘œ ์–ป์–ด์˜ค๊ธฐ

 

๋งˆ์šฐ์Šค์˜ ์ขŒํ‘œ๋Š” ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์–ป์–ด์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Mouse.current.position.ReadValue();   // ์Šคํฌ๋ฆฐ ์ขŒํ‘œ

 

ํ•˜์ง€๋งŒ ์œ„์˜ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์–ป์–ด์˜ค๋Š” ๊ฒƒ์€ ์Šคํฌ๋ฆฐ ์ขŒํ‘œ๊ณ„์˜ ๋งˆ์šฐ์Šค ์ขŒํ‘œ์ž…๋‹ˆ๋‹ค. ๋ชจ๋‹ˆํ„ฐ ์Šคํฌ๋ฆฐ์€ 2์ฐจ์›์œผ๋กœ ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— x์™€ y ๊ฐ’๋งŒ ์กด์žฌํ•˜๊ณ  z๊ฐ’์€ ํ•ญ์ƒ 0์ž…๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ ์บ๋ฆญํ„ฐ๋Š” ์Šคํฌ๋ฆฐ ์ขŒํ‘œ๊ณ„์— ์กด์žฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๊ฒŒ์ž„ ์›”๋“œ ์ขŒํ‘œ๊ณ„์— ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์Šคํฌ๋ฆฐ ์ขŒํ‘œ๊ณ„์˜ ๋งˆ์šฐ์Šค ์ขŒํ‘œ๋ฅผ ํ†ตํ•ด ์–ด๋–ป๊ฒŒ ์›”๋“œ ์ขŒํ‘œ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์„๊นŒ์š”?

 

๋งˆ์šฐ์Šค๋ฅผ ํด๋ฆญํ•œ ์ง€์ ์œผ๋กœ๋ถ€ํ„ฐ Raycast๋ฅผ ์˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ฆ‰, ๊ฒŒ์ž„ ์›”๋“œ ๋‚ด์— ์นด๋ฉ”๋ผ๋กœ๋ถ€ํ„ฐ Raycast๊ฐ€ ๋ป—์–ด ๋‚˜์™€ ์‹ค์ œ ๊ฒŒ์ž„ ์›”๋“œ ๋‚ด์˜ ์˜ค๋ธŒ์ ํŠธ์— ์ถฉ๋Œํ•˜๋Š” ๊ฒƒ์ด์ง€์š”.

 

์šฐ๋ฆฌ๊ฐ€ ๋งˆ์šฐ์Šค๋กœ ํด๋ฆญํ•˜์—ฌ ๊ณต๊ฒฉ์„ ํ•œ๋‹ค๋ฉด, ์บ๋ฆญํ„ฐ๋Š” ํ•ด๋‹น ํด๋ฆญํ•œ ๋ฐฉํ–ฅ์„ ๋ฐ”๋ผ๋ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Raycast์™€ ์ถฉ๋Œํ•œ ์ง€์ ์œผ๋กœ๋ถ€ํ„ฐ ํ˜„์žฌ ์บ๋ฆญํ„ฐ์˜ ์ขŒํ‘œ๋ฅผ ๋นผ์„œ, ํ•ด๋‹น ๋ฐฉํ–ฅ์œผ๋กœ์˜ ๋ฒกํ„ฐ๋ฅผ ์–ป์–ด๋‚ด๋„๋ก ํ•ฉ์‹œ๋‹ค.

// PlayerController

protected Vector3 GetMouseWorldPosition()
{
    Vector3 mousePosition = Mouse.current.position.ReadValue();
    Ray ray = Camera.main.ScreenPointToRay(mousePosition);
    Debug.DrawRay(ray.origin, ray.direction * 1000f, Color.red, 5f);  // Raycast ์‹œ๊ฐํ™”

    if (Physics.Raycast(ray, out RaycastHit HitInfo, Mathf.Infinity))
    {
        Vector3 target = HitInfo.point;
        Vector3 myPosition = new Vector3(transform.position.x, 0f, transform.position.z);
        target.Set(target.x, 0f, target.z);
        return (target - myPosition).normalized;
    }
    
    return Vector3.zero;
}

 

์ด์ œ ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ๋งˆ์šฐ์Šค ์›”๋“œ ์ขŒํ‘œ๋ฅผ ๊ณ„์‚ฐํ•ด ์ €์žฅํ•ด๋‘๋„๋ก ํ•ฉ์‹œ๋‹ค.

// PlayerController

public Vector3 MouseDirection { get; private set; }

public void OnClickLeftMouse(InputAction.CallbackContext context)
{
    if (context.performed)
    {
        MouseDirection = GetMouseWorldPosition();
        LookAt(MouseDirection);
        
        if (context.interaction is HoldInteraction)         // ์ฐจ์ง€ ๊ณต๊ฒฉ
        {
        
        }

        else if (context.interaction is PressInteraction)   // ์ผ๋ฐ˜ ๊ณต๊ฒฉ
        {


        }
    }
}

 

ํด๋ฆญํ•œ ๋ฐฉํ–ฅ์œผ๋กœ ์บ๋ฆญํ„ฐ๊ฐ€ ์ž˜ ๋ณด๋Š”์ง€ ํ…Œ์ŠคํŠธ ํ•ด๋ด…์‹œ๋‹ค.

 

ํด๋ฆญํ•œ ๋ฐฉํ–ฅ์œผ๋กœ Raycast(๋นจ๊ฐ„ ๊ด‘์„ )์ด ๋ฐœ์‚ฌ๋˜๊ณ , ์บ๋ฆญํ„ฐ๊ฐ€ ํ•ด๋‹น ๋ฐฉํ–ฅ์œผ๋กœ ์ž˜ ๋ฐ”๋ผ๋ณด๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด์ œ ๊ณต๊ฒฉ ์ƒํƒœ(Attack State)๋ฅผ ์ •์˜ํ•˜์—ฌ, ์ƒํƒœ ๋จธ์‹ (StateMachine)์— ๋“ฑ๋กํ•ด๋ด…์‹œ๋‹ค.

 

 

 


3. ๊ณต๊ฒฉ ์ƒํƒœ(Attack State) ์ถ”๊ฐ€ํ•˜์—ฌ ๋“ฑ๋กํ•˜๊ธฐ

 

์šฐ์„  ์ผ๋ฐ˜ ๊ณต๊ฒฉ ์ƒํƒœ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด๋„๋ก ํ•˜์ฃ . ๋‹ค์Œ๊ณผ ๊ฐ™์ด AttackState ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace CharacterController
{
    public class AttackState : BaseState
    {
        public static bool IsAttack = false;
        public const float CanReInputTime = 1f;

        public AttackState(PlayerController controller) : base(controller) { }

        public override void OnEnterState()
        {
            IsAttack = true;
            Player.Instance.weaponManager.Weapon?.Attack(this);
        }

        public override void OnExitState()
        {
        }

        public override void OnFixedUpdateState()
        {
        }

        public override void OnUpdateState()
        {
        }
    }
}

 

Player ํด๋ž˜์Šค์—์„œ AttackState ๋“ฑ๋กํ•˜๊ธฐ

 

WeaponManager๊ฐ€ ํ˜„์žฌ ๋“ค๊ณ  ์žˆ๋Š” ๋ฌด๊ธฐ์˜ Attack() ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ถ”์ƒ ๋ฉ”์†Œ๋“œ๋กœ ์ •์˜ํ–ˆ์œผ๋‹ˆ, ๋“ค๊ณ  ์žˆ๋Š” ๋ฌด๊ธฐ์— ๋”ฐ๋ผ ์ œ ๊ฐ๊ฐ ๋‹ค๋ฅธ ๊ณต๊ฒฉ์ด ๋‚˜๊ฐ€๊ฒ ์ง€์š”. ๊ทธ๋Ÿฐ๋ฐ, ๋ฌด๊ธฐ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค ๋•Œ ์ƒ๊ฐํ•ด์•ผ ํ•˜๋Š” ๊ฒŒ ํ•œ ๋‘๊ฐ€์ง€๊ฐ€ ์•„๋‹ˆ๋”๊ตฐ์š”.

 

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

 

 

ํ•˜๋‚˜์”ฉ ํ•œ ๋ฒˆ ์•Œ์•„๋ณด๋„๋ก ํ•ฉ์‹œ๋‹ค.

 

 

 


4. ๊ณต๊ฒฉ ์• ๋‹ˆ๋ฉ”์ด์…˜

 

Weapon Animation Layer ์ƒ์„ฑํ•˜๊ณ , ๊ธฐ๋ณธ ๊ณต๊ฒฉ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์—ฐ๊ฒฐํ•˜๊ธฐ

 

์†๋Œ์˜ ์• ๋‹ˆ๋ฉ”์ดํ„ฐ์—์„œ ์ƒˆ๋กœ์šด ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ ˆ์ด์–ด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , Weapon Layer๋ผ๊ณ  ์ด๋ฆ„ ์ง€์–ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ฐ€์ค‘์น˜(Weight) ๊ฐ’์„ 1๋กœ ์ฃผ์—ˆ์ฃ . ์ด๋ ‡๊ฒŒ ๋˜๋ฉด Weapon Layer ๋˜ํ•œ Base Layer์™€ ํ•จ๊ป˜ ๊ฐ™์ด ์žฌ์ƒ๋œ๋‹ค๋Š” ๊ฑธ ๋งํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ ๊ณต๊ฒฉ ์• ๋‹ˆ๋ฉ”์ด์…˜๋“ค์„ ๋ฐฐ์น˜ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋ƒฅ Base Layer์—์„œ ํ•˜๋ฉด ๋˜์ง€, ์™œ ์ด๋ ‡๊ฒŒ Layer๋ฅผ ๋‚˜๋ˆ„์–ด์„œ ํ•˜๋ƒ๊ณ  ์ƒ๊ฐ์ด ๋“ค ์ˆ˜๋„ ์žˆ๋Š”๋ฐ, ์ด๊ฒƒ์€ ๋‚˜์ค‘์— ๋ฌด๊ธฐ๋ณ„๋กœ ๋‹ค๋ฅธ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์žฌ์ƒํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„์„ ํ•ด๊ฒฐํ•ด ์ค„ ๊ฒ๋‹ˆ๋‹ค.

 

์ผ๋ฐ˜ ๊ณต๊ฒฉ ์• ๋‹ˆ๋ฉ”์ด์…˜์€ 3๊ฐœ๊ฐ€ ํ•œ ๋ฌถ์Œ์ด๊ธฐ์— Sub State๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์•ˆ์— ๋ฌถ์–ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
Default Attacks

 

Empty ์ƒํƒœ์—๋Š” ํ• ๋‹น๋œ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋ง ๊ทธ๋Œ€๋กœ ์•„๋ฌด ํ–‰๋™๋„ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ค๊ฐ€ ํŠน์ • ์กฐ๊ฑด์— ๋”ฐ๋ผ ํŠธ๋žœ์ง€์…˜์ด ์ผ์–ด๋‚˜๋ฉด ํ•ด๋‹น ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์žฌ์ƒํ•˜๊ฒ ์ง€์š”. ๊ทธ๋ฆฌ๊ณ  ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ธ ๊ฐœ๋ฅผ ์„ ์–ธํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

 

AttackCombo ๋ณ€์ˆ˜๋Š” ํ˜„์žฌ ๋ช‡ ๋ฒˆ์งธ ์ฝค๋ณด ๊ณต๊ฒฉ์ธ์ง€๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

AttackSpeed๋Š” ํ˜„์žฌ ๋‚ด ๋ฌด๊ธฐ์˜ ๊ณต๊ฒฉ ์†๋„์— ๋”ฐ๋ผ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์ƒ ์†๋„๋ฅผ ๋‹ค๋ฅด๊ฒŒ ํ•ด์ค„ ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค.

IsAttack ๋ณ€์ˆ˜๋Š” ์ข€ ๋” ๋งค๋„๋Ÿฝ๊ณ  ์ •ํ™•ํ•œ ํŠธ๋žœ์ง€์…˜์„ ์œ„ํ•ด ๋งŒ๋“ค์–ด ์ค€ ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค.

 

3ํƒ€ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ฐ๊ฐ์€ AttackSpeed ๊ฐ’์„ ์žฌ์ƒ ์†๋„์— ๊ณฑํ•˜๋„๋ก ๋งŒ๋“ค์–ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

 

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

 

*์„ธํŒ… ๊ฐ’์€ ๋”๋ณด๊ธฐ์— ์ ์–ด ๋‘์—ˆ์Šต๋‹ˆ๋‹ค.

๋”๋ณด๊ธฐ

 

 

 

 

 

 

 

 

 

 

 

 

์• ๋‹ˆ๋ฉ”์ด์…˜ ์ด๋ฒคํŠธ ํ•จ์ˆ˜ ๋“ฑ๋กํ•˜๊ธฐ

 

์• ๋‹ˆ๋ฉ”์ด์…˜์—์„œ ํŠน์ • ํ‚ค ํ”„๋ ˆ์ž„์— ์ด๋ฒคํŠธ ํ•จ์ˆ˜๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฑธ ์ด์šฉํ•˜์—ฌ ๊ณต๊ฒฉ ๋ชจ์…˜์ด ๋๋‚ฌ๋‹ค๊ณ  ์ดˆ๊ธฐํ™” ํ•ด์ฃผ๋Š” ์ด๋ฒคํŠธ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์ค„ ๊ฒ๋‹ˆ๋‹ค. ๋ชจ์…˜์ด ๊ฑฐ์˜ ๋๋‚˜๊ฐˆ ๋•Œ ์ฏค์— ๋“ฑ๋กํ•ด์ค์‹œ๋‹ค.

 

๋‘ ๋ฒˆ์งธ ๊ณต๊ฒฉ๊ณผ ์„ธ ๋ฒˆ์งธ ๊ณต๊ฒฉ ๋ชจ์…˜์—๋„ ๋˜‘๊ฐ™์ด ๋‹ฌ์•„์ฃผ๋„๋ก ํ•˜์ฃ .

 

๊ทธ๋ฆฌ๊ณ  SondolAnimationEvents๋ผ๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋งŒ๋“ค์–ด ์†๋Œ์—๊ฒŒ ๋‹ฌ์•„์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ์ •์  ๋ณ€์ˆ˜๋“ค๋กœ๋งŒ ์ ‘๊ทผ์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์‚ฌ์‹ค์ƒ ์†๋Œ์ด ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ๋นˆ ์˜ค๋ธŒ์ ํŠธ์— ๋‹ฌ๊ณ  ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ด๋ฒคํŠธ๋งŒ ๊ด€๋ฆฌํ•˜๋Š” ์• ๋ฅผ ๋งŒ๋“ค์–ด๋„ ๊ดœ์ฐฎ๊ฒ ๋„ค์š”.

using CharacterController;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SondolAnimationEvents : MonoBehaviour
{
    public void OnFinishedAttack()
    {
        AttackState.IsAttack = false;
        Player.Instance.animator.SetBool("IsAttack", false);
        Player.Instance.stateMachine.ChangeState(StateName.MOVE);
    }
}

 

๊ทธ๋ฆฌ๊ณ  ์ด์ „์— ๋“ฑ๋กํ•ด ๋‘” ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ด๋ฒคํŠธ์— ์œ„ ํ•จ์ˆ˜๋ฅผ ๋“ฑ๋กํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์ƒ ์†๋„๊ฐ€ ๋‹ฌ๋ผ๋„, ๋ชจ์…˜์ด ๋๋‚œ ์ง€์ ์„ ์ •ํ™•ํ•˜๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์„ ๊ฒ๋‹ˆ๋‹ค.

๊ณต๊ฒฉ ๋ชจ์…˜์ด ๋๋‚ฌ์„ ๋•Œ, ๊ณต๊ฒฉ๊ณผ ๊ด€๋ จ๋œ ๋ณ€์ˆ˜๋“ค์„ ์ดˆ๊ธฐํ™”ํ•ด์ฃผ๋Š” ๊ฒƒ์ด์ง€์š”.

 

์ด์ œ ๋งˆ์ง€๋ง‰์œผ๋กœ ๊ธฐ๋ณธ ๋ฌด๊ธฐ์ธ ์นด๋ก ์˜ ๋…ธ(CharonPaddle) ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ณต๊ฒฉ ๋กœ์ง์„ ๊ตฌํ˜„ํ•ด๋ด…์‹œ๋‹ค.

 

 

 


5. ์นด๋ก ์˜ ๋…ธ(Charon's Paddle) ๋ฌด๊ธฐ ํด๋ž˜์Šค ๋งŒ๋“ค๊ธฐ

 

์ด์ „์— ๋งŒ๋“ค์—ˆ๋˜ BaseWeapon ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ƒ์† ๋ฐ›์•„ ์ถ”์ƒ ๋ฉ”์†Œ๋“œ๋“ค์„ ๊ตฌํ˜„ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

using CharacterController;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CharonPaddle : BaseWeapon
{
    public readonly int hashIsAttackAnimation = Animator.StringToHash("IsAttack");
    public readonly int hashAttackAnimation = Animator.StringToHash("AttackCombo");
    public readonly int hashAttackSpeedAnimation = Animator.StringToHash("AttackSpeed");
    private Coroutine checkAttackReInputCor;

    public override void Attack(BaseState state)
    {
        ComboCount++;
        Player.Instance.animator.SetFloat(hashAttackSpeedAnimation, AttackSpeed);
        Player.Instance.animator.SetBool(hashIsAttackAnimation, true);
        Player.Instance.animator.SetInteger(hashAttackAnimation, ComboCount);
        CheckAttackReInput(AttackState.CanReInputTime);
    }

    public override void ChargingAttack(BaseState state)
    {

    }

    public override void DashAttack(BaseState state)
    {

    }

    public override void Skill(BaseState state)
    {

    }

    public override void UltimateSkill(BaseState state)
    {

    }

    public void CheckAttackReInput(float reInputTime)
    {
        if (checkAttackReInputCor != null)
            StopCoroutine(checkAttackReInputCor);
        checkAttackReInputCor = StartCoroutine(CheckAttackReInputCoroutine(reInputTime));
    }

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

        ComboCount = 0;
        Player.Instance.animator.SetInteger(hashAttackAnimation, 0);
    }
}

 

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

 

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

 

์—ฌ๋‹ด์œผ๋กœ, ์ฝ”๋ฃจํ‹ด์ด ์ค‘์ง€๊ฐ€ ๋˜์ง€ ์•Š๊ธธ๋ž˜ ์™œ ์•ˆ ๋˜๋‚˜ ํ•˜๋‹ค๊ฐ€ ๊ธฐ์กด ์ฝ”๋ฃจํ‹ด์€ ๋ƒ…๋‘๊ณ , ์ƒˆ๋กœ ํ• ๋‹นํ•˜์—ฌ ๊ทธ๊ฑธ ์ค‘์ง€ํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค... ์ฆ‰, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜๊ณ  ์žˆ์—ˆ๋‹จ ์†Œ๋ฆฌ์ง€์š”. 

    public void CheckAttackReInput(float reInputTime)
    {
        if (checkAttackReInputCor != null)
            StopCoroutine(CheckAttackReInputCoroutine(reInputTime));
        StartCoroutine(CheckAttackReInputCoroutine(reInputTime));
    }

 

์—ฌ๋Ÿฌ๋ถ„๋“ค์€ ์ด๋Ÿฐ ์‹ค์ˆ˜ ํ•˜์ง€ ๋งˆ์„ธ์š”... ์ด๊ฒƒ ๋•Œ๋ฌธ์— 30๋ถ„ ๋‚ ๋ ธ์Šต๋‹ˆ๋‹ค. ์ด์ œ ๋งˆ์ง€๋ง‰์œผ๋กœ ๋‘ ๊ฐ€์ง€ ์ž‘์—…๋งŒ ๋‚จ์•˜์Šต๋‹ˆ๋‹ค.

 

 

 


6. Animator Override Controller ๋งŒ๋“ค๊ธฐ

 

์œ„์—์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์„ธํŒ…ํ•˜๊ณ  ๋งค๊ฐœ๋ณ€์ˆ˜ ๋งŒ๋“ค์–ด ์ฃผ๊ณ  ํ–ˆ๋˜ ์šฐ๋ฆฌ ์†๋Œ์˜ Animator๋ฅผ ์šฐํด๋ฆญํ•˜์—ฌ, Animator Override Controller๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ๋„๋ก ํ•ฉ์‹œ๋‹ค.

 

 

๊ทธ๋ฆฌ๊ณ  ์นด๋ก ์˜ ๋…ธ ๋ฌด๊ธฐ์— ํ•ด๋‹นํ•˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜๋“ค์„ ํ• ๋‹นํ•˜์—ฌ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— "CharonPaddleController"๋ผ๊ณ  ์ด๋ฆ„ ์ง“๊ฒ ์Šต๋‹ˆ๋‹ค. ์†๋Œ์˜ ์• ๋‹ˆ๋ฉ”์ดํ„ฐ ํ™˜๊ฒฝ์„ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์˜ฌ ๊ฒƒ์ด๋ฏ€๋กœ Controller์— ์†๋Œ ์• ๋‹ˆ๋ฉ”์ดํ„ฐ๋ฅผ ์—ฐ๊ฒฐํ•ด์ค๋‹ˆ๋‹ค.

 

 

Animator Override Controller๋ž€ ๋ง ๊ทธ๋Œ€๋กœ ์„ ํƒํ•œ Animator์˜ Layer, ๋งค๊ฐœ๋ณ€์ˆ˜, ์ƒํƒœ(State)๋“ฑ์˜ ํ™˜๊ฒฝ์„ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์˜ค์ง€๋งŒ, Override๋ž€ ๋ง ๋‹ต๊ฒŒ ๋‹คํ˜•์„ฑ์„ ์ ์šฉํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์„ ๋งํ•ฉ๋‹ˆ๋‹ค.

 

๋ฌด๊ธฐ๊ฐ€ 3๊ฐ€์ง€ ์ข…๋ฅ˜๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ , ๊ทธ ๋ฌด๊ธฐ๋“ค ๋ชจ๋‘ 3ํƒ€ ๊ณต๊ฒฉ์ด ์žˆ๋Š” ๊ฒƒ์€ ๋˜‘๊ฐ™์ง€๋งŒ ์ œ ๊ฐ๊ฐ ๋ชจ์…˜์€ ๋‹ค๋ฅด๋‹ค๊ณ  ํ•ด๋ณด๋ฉด, ์ด๋Ÿฐ ๋ฐฉ์‹์„ ํ†ตํ•ด ์• ๋‹ˆ๋ฉ”์ด์…˜๋งŒ ๋ณ€๊ฒฝํ•˜์—ฌ ํšจ์œจ์ ์œผ๋กœ ํ•ด๋‹น ๋ฌด๊ธฐ ์• ๋‹ˆ๋ฉ”์ด์…˜๋“ค์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์ฃ . ๊ทธ๋ฆฌ๊ณ  ๋ฌด๊ธฐ๋ฅผ ๊ต์ฒดํ•  ๋•Œ ์• ๋‹ˆ๋ฉ”์ดํ„ฐ๋„ ๊ฐ™์ด ๊ต์ฒดํ•ด์ฃผ๋ฉด, ๋ณ„ ๋‹ค๋ฅธ ์„ธํŒ…์—†์ด ๋ฌด๊ธฐ๋งˆ๋‹ค ์„œ๋กœ ๋‹ค๋ฅธ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์ƒ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

BaseWeapon์— RuntimeAnimatorController๋ผ๋Š” ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋˜ ๊ฑธ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”? ๋ฐ”๋กœ ์ด ์šฉ๋„๋ฅผ ์œ„ํ•ด ๋„ฃ์–ด๋†จ์Šต๋‹ˆ๋‹ค.

using CharacterController;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public abstract class BaseWeapon : MonoBehaviour
{
    public int ComboCount { get; set; }
    public WeaponHandleData HandleData { get { return weaponhandleData; } }
    
    // ์ด ๋ฌด๊ธฐ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์˜ ์• ๋‹ˆ๋ฉ”์ดํ„ฐ
    public RuntimeAnimatorController WeaponAnimator { get { return weaponAnimator; } }
    ...
}

 

๋ฌด๊ธฐ๋ฅผ ๊ต์ฒดํ•  ๋•Œ๋งˆ๋‹ค, ์†๋Œ Animator์—๋‹ค๊ฐ€ ํ•ด๋‹น ๋ฌด๊ธฐ์˜ RuntimeAnimatorController๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ด ๋ถ€๋ถ„์€ WeaponManager์˜ SetWeapon()์— ์ด๋ฏธ ๊ตฌํ˜„ํ•ด ๋†จ์—ˆ์Šต๋‹ˆ๋‹ค.

    // ๋ฌด๊ธฐ ๋ณ€๊ฒฝ
    public void SetWeapon(GameObject weapon)
    {
        if (Weapon == null)
        {
            weaponObject = weapon;
            Weapon = weapon.GetComponent<BaseWeapon>();
            weaponObject.SetActive(true);
            
            /// ์• ๋‹ˆ๋ฉ”์ดํ„ฐ ๋ณ€๊ฒฝ
            Player.Instance.animator.runtimeAnimatorController = Weapon.WeaponAnimator;
            return;
        }

        for(int i = 0; i < weapons.Count; i++)
        {
            if (weapons[i].Equals(Weapon))
            {
                weaponObject = weapon;
                weaponObject.SetActive(true);
                Weapon = weapon.GetComponent<BaseWeapon>();
                
                /// ์• ๋‹ˆ๋ฉ”์ดํ„ฐ ๋ณ€๊ฒฝ
                Player.Instance.animator.runtimeAnimatorController = Weapon.WeaponAnimator;
                continue;
            }
            weapons[i].SetActive(false);
        }
    }

 

์ด์ œ ์นด๋ก ์˜ ๋…ธ ๋ฌด๊ธฐ์—๋‹ค๊ฐ€ ์œ„์—์„œ ์ƒ์„ฑํ–ˆ๋˜ "CharonPaddleController" ์• ๋‹ˆ๋ฉ”์ดํ„ฐ๋ฅผ ๋„ฃ์–ด๋‘๋„๋ก ํ•ฉ์‹œ๋‹ค.

 

 

ํ˜„์žฌ๋Š” ๋ฌด๊ธฐ๊ฐ€ ์นด๋ก ์˜ ๋…ธ ๋ฐ–์— ์—†๊ธฐ ๋•Œ๋ฌธ์— Override Controller์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜๋“ค์„ ๋‹ค๋ฅธ ๊ฑธ๋กœ ๊ต์ฒดํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋‚˜์ค‘์— ๋ฌด๊ธฐ๊ฐ€ ์ถ”๊ฐ€๋กœ ์ƒ๊ธฐ๊ฒŒ ๋˜๋ฉด, ์• ๋‹ˆ๋ฉ”์ด์…˜ ํด๋ฆฝ๋“ค๋งŒ ๊ต์ฒดํ•ด์ฃผ๊ณ  ํ•ด๋‹น ์• ๋‹ˆ๋ฉ”์ดํ„ฐ๋ฅผ ์—ฐ๊ฒฐํ•ด์ฃผ๋ฉด ๋˜๊ฒ ์ง€์š”.

 

์ด์ œ ์ง„์งœ ๋งˆ์ง€๋ง‰์œผ๋กœ, ์ž…๋ ฅ ์ฒ˜๋ฆฌ ๋ถ€๋ถ„์—์„œ ๊ณต๊ฒฉ ์ƒํƒœ๋กœ ์ „ํ™˜ํ•˜๋Š” ์ฝ”๋“œ๋งŒ ๋„ฃ์–ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

 

 


7. ๊ณต๊ฒฉ ์ƒํƒœ ์ „ํ™˜ ์ฝ”๋“œ ์ž…๋ ฅํ•˜๊ธฐ

 

ํ˜„์žฌ ๊ณต๊ฒฉ ์ค‘์ด ์•„๋‹ˆ๊ณ , ์ฝค๋ณด ์นด์šดํŠธ๊ฐ€ 3 ๋ฏธ๋งŒ์ผ ๋•Œ๋งŒ ๊ณต๊ฒฉ ์ƒํƒœ๋กœ ์ „ํ™˜์ด ์ผ์–ด๋‚˜๋„๋ก ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 // PlayerController
 
 public void OnClickLeftMouse(InputAction.CallbackContext context)
{
     
    if (context.performed)
    {
        MouseDirection = GetMouseWorldPosition();

        if (context.interaction is HoldInteraction)         // ์ฐจ์ง€ ๊ณต๊ฒฉ
        {
            /// ์ฐจ์ง€ ๊ณต๊ฒฉ ์ƒํƒœ ์ „ํ™˜
        }

        else if (context.interaction is PressInteraction)   // ์ผ๋ฐ˜ ๊ณต๊ฒฉ
        {
            if (DashState.IsDash)  // ์ผ๋‹จ์€ ๋ง‰์•„๋†จ์Œ
            {
                /// ๋Œ€์‹œ ๊ณต๊ฒฉ ์ƒํƒœ์ „ํ™˜
                return;
            }

            bool isAvailableAttack = !AttackState.IsAttack &&
                                     (player.weaponManager.Weapon.ComboCount < 3);
            if (isAvailableAttack)
            {
                LookAt(MouseDirection);
                player.stateMachine.ChangeState(StateName.ATTACK);
            }
        }
    }
}

 

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

 

ํ…Œ์ŠคํŠธ ํ•œ ๋ฒˆ ํ•ด๋ณด๊ณ  ๋งˆ์น˜๋ฉด ๋˜๊ฒ ๋„ค์š”.

 

์ž˜ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ณต๊ฒฉ ์†๋„์— ๋”ฐ๋ผ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์ƒ ์†๋„๊ฐ€ ์œ ๋™์ ์œผ๋กœ ๋ณ€ํ•˜๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

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

 

์˜ค๋Š˜ ๊ธ€์ด ๊ต‰์žฅํžˆ ๊ธธ์—ˆ๋Š”๋ฐ, ์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

 

728x90
๋ฐ˜์‘ํ˜•