โ ๋ณธ ๊ธ์ ์์ฑ์๊ฐ ๊ฐ๋ฐํ ๋ด์ฉ์ ์ ๋ฆฌํ ๊ธ๋ก ์๋ชป๋ ์ ์ด ์์ ์ ์์ด, ๋ฌธ์ ๊ฐ ์๋ค๋ฉด ๋๊ธ๋ก ๋จ๊ฒจ์ฃผ์๊ธฐ ๋ฐ๋๋๋ค.
โ ํด๋น ๋ด์ฉ์ ๊ณต์ ํ๊ฒ ๋๋ค๋ฉด, ๋ฐ๋์ ์ถ์ฒ๋ฅผ ๊ผญ ๋ช
์ํด์ฃผ๊ธฐ ๋ฐ๋๋๋ค.
[AR FPS ๊ฒ์] 2. ์ ๋๋ค ์์น ์คํฐ & UI์ ์ ์ ๊ฐฑ์
โ ๋ณธ ๊ธ์ ์์ฑ์๊ฐ ๊ฐ๋ฐํ ๋ด์ฉ์ ์ ๋ฆฌํ ๊ธ๋ก ์๋ชป๋ ์ ์ด ์์ ์ ์์ด, ๋ฌธ์ ๊ฐ ์๋ค๋ฉด ๋๊ธ๋ก ๋จ๊ฒจ์ฃผ์๊ธฐ ๋ฐ๋๋๋ค. โ ํด๋น ๋ด์ฉ์ ๊ณต์ ํ๊ฒ ๋๋ค๋ฉด, ๋ฐ๋์ ์ถ์ฒ๋ฅผ ๊ผญ ๋ช ์ํด์ฃผ๊ธฐ ๋ฐ๋๋
vrworld.tistory.com
์ ๋ฒ ํฌ์คํ ๊น์ง ํด์ AR FPS ๊ฐ๋ฐ์ ์ํ ์ด๊ธฐ ์ธํ ๊น์ง ๊ตฌํ ์ ๋ฆฌ๋ฅผ ์ ์ด๋ณด์์ต๋๋ค.
์ด์ ์ฌ๊ธฐ์์ ์ฌ์ฅ์ ๊ธฐ๋ฅ๊ณผ ์ด์ ์์ ๋ ๋ฐ๋ ์ ๋๋ฉ์ด์ ๋ฑ์ ์ถ๊ฐ๋ก ๊ตฌํํ ๋ถ๋ถ์ ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค.
โ ๊ตฌํ ์์ฝ
1. ์ด์ ์์ ๋ ๋ฐ๋ ๋ชจ์ (์ ๋๋ฉ์ด์ )
2. ์ฌ์ฅ์ ํ์ ๋ ํ๋ ์ด์ด UI ๋ณํ (ํ์ฌ ์ด์/ ๋จ์ ์ด์)
3. ์ฌ์ฅ์ ๋ชจ์ ์ถ๊ฐ (์ ๋๋ฉ์ด์ )
4. ํ์ฌ ์ด์์ด 0๊ฐ ์ดํ์ผ ๋ 0์ ์ ์งํ๋๋ก ์ฆ, ์ด์์ ๊ฐ์๊ฐ '-' ์์ญ๊น์ง ๊ฐ์ง ์๋๋ก ๊ตฌํ.
5. ํ์ฌ ์ด์์ด 0 ์ฆ, ์ด์์ด ์์ ๋ ์ด์์ด ๋น์๋ค๋ ๊ฑธ ์ธ์งํ๊ธฐ ์ํ ์ฌ์ด๋ ์ถ๊ฐ ๋ค์ ์ฌ์ฅ์ ํ๊ณ ์ด์ ์์ ๋ ์ด์ ์ดํํธ, ์ด๊ธฐ ์ฌ์ด๋ ์ฌ์
6. ์ด์์ด ์์ ๋ Raycast ์ฒดํฌ๋ฅผ ์ ํจ. -> ์ฆ, ์ฌ์ฉ์์ ์ด๊ตฌ ๋ฐฉํฅ๊ณผ ์ ์ ๋ฐฉํฅ์ด ์ผ์นํด๋ Fire ๋ฒํผ์ ๋๋ฌ๋ ์ ์ ์ฌ๋ผ์ง์ง ์๋๋ค.
โ ์คํฌ๋ฆฝํธ ์ถ๊ฐ & ๊ฐ์
1. ControlArm.cs ์ถ๊ฐ => ์ฌ์ฅ์ & ์ด์ ๋ฐ๋ ๋ชจ์ ๋ด๋น
2. PlayerHud.cs ์ถ๊ฐ => ์ด์ UI ๋ณํ
3. ManageGun.cs ์ถ๊ฐ => ํ์ฌ ์ด์ ์ํ (์ด๊ธฐ ์์ ์ด์์ด ์ผ๋ง๋ ์๋์ง ํ๋จํจ.)
4. HandGunFire ๊ฐ์ => checkRaycast()ํจ์๋ฅผ ๋ง๋ค์ด ์ด์์ด ์์ ๋๋ง Raycast ์ฒดํฌํ๋๋ก ๊ตฌํ.
shoot() ํจ์์์๋ ํ์ฌ ์ด์ ๊ฐ์์ ๋ฐ๋ฅธ ๋ค๋ฅธ ๋ฐ์์ ๋ณด์ด๋๋ก ๊ตฌํ.
์ฌ์ฅ์ & ์ด ๋ฐ๋ ๋ชจ์
์ ์ฌ์ง์์ ๋นจ๊ฐ์ ์์ ์ด๋ค ๋์์ ์ทจํ ๊ฒ์ธ์ง์ ๋ํ Clip๋ค์ด๊ณ , ํ๋์ ์์ ๊ฐ๊ฐ์ ๋ชจ์ ๋ค์ด ์ด๋ป๊ฒ ์ ํ๋ ๊ฒ์ธ์ง์ ๋ํ Transition์ผ๋ก ํ์ ํ ์ ์์ต๋๋ค.
Reload(์ฌ์ฅ์ ) ๋ณ์๋ฅผ Trigger ํ์ ์ผ๋ก ๋ง๋ค์ด ํ๋ฒ ์คํ ํ ์ฐ๊ฒฐ๋ Transition์ ๋ฐ๋ผ ๋์ ์ ํ์ด ์ด๋ฃจ์ด์ง๋๋ก ๋ง๋ค์ด ์ค๋๋ค.
์ ์ฌ์ง์ New State -> Reload๋ก ๋ชจ์ ๋์์ ํ๊ณ ์์ต๋๋ค. New State๋ ์ด์ ์ฅ๊ณ ๊ฐ๋งํ ์๋ ์ํ, Reload๋ ์ฌ์ฅ์ ๋์์ ๋๋ค. ์ฌ๊ธฐ์ ์ค์ํ ๊ฒ์ Conditions์ ๋๋ค. ์กฐ๊ธ ์ ์ Triger ํ์ ์ผ๋ก ๋ง๋ ํ๋ผ๋ฏธํฐ Reload๋ฅผ Conditions์ผ๋ก ์ถ๊ฐํด์ค ๋ค ์คํ๋ ๋ ์ ์ฌ์ง์ ๋ชจ์ ๋ณํ๊ฐ ์ด๋ฃจ์ด์ง๊ฒ ๋ฉ๋๋ค.
์ด์ ์ฝ๋์์ SetTrigger()๋ฅผ ํธ์ถํ์ฌ ์ฐ๋ฆฌ๊ฐ ์กฐ๊ธ ์ ์ Triger ํ์ ์ผ๋ก ๋ง๋ค์ด ์ค Reload๊ฐ 1ํ ์คํ๋ฉ๋๋ค.
์คํ์ํจ ๋ค Conditions์ด Reload์ธ Transiton์ ๋ฐ๋ผ ๋ชจ์ ๋ณํ๊ฐ ์ด๋ฃจ์ด์ง๊ฒ ๋ฉ๋๋ค.
๋ค์์ ์ด์ ๋ฐ๋ ๋ชจ์ ์ ํ๊ธฐ ์ํด CrossFadeInFixedTime()๋ฅผ ํธ์ถํด rebound ๋ผ๋ ์ด์ ๋ฐ๋ ๋์ ์ํ ํ 0.01์ด ๊ฐ๊ฒฉ์ผ๋ก ๋ค์ ๋์์ ์ํํ๊ฒ ๋ง๋ค์ด์ฃผ์์ต๋๋ค.
rebound (์ด ๋ฐ๋) ์ํ ํ New State(์ด์ ๊ฐ์ง๊ณ ๋๊ธฐ ์ํ)๋ก ์ ํํ๊ณ ์์ต๋๋ค. ์ฆ, CrossFadeInFixedTime() ํธ์ถํ์ฌ 0,01์ด ๊ฐ๊ฒฉ์ผ๋ก ๋ชจ์ ๋ณํ์ ํ๊ฒ ๋๋ ๊ฒ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ControlArm : MonoBehaviour
{
[Tooltip("ํ์ฌ ์์ ํ ์ด๊ธฐ์ ์ด์์ ๊ฐ์๋ฅผ ๋ด๋นํ๋ ์ปดํฌ๋ํธ")]
[SerializeField] private ManageGun currentGun;
Animator anis; //์ ๋๋ฉ์ด์
๋ณ์
[Header("Sound")]
public AudioSource ReloadSound; //์ฌ์ฅ์ ์ฌ์ด๋
void Start()
{
anis = GetComponent<Animator>();
}
public void work()
{
anis.CrossFadeInFixedTime("rebound", 0.01f);
}
public void Reload()
{
// ์์ ํ๊ณ ์๋ ์ด์์ด ์์ผ๋ฉด ์ฌ์ฅ์ , ์์ผ๋ฉด ์ฌ์ฅ์ ๋ถ๊ฐ๋ฅ
if (currentGun.carryBulletCount > 0)
{
anis.SetTrigger("Reload"); // ์ฌ์ฅ์ ๋ชจ์
์ฌ์
ReloadSound.Play();
if (currentGun.carryBulletCount >= currentGun.reloadBulletCount) // ๊ฐ์ง๊ณ ์๋ ์ด์ >= ํ์ฐฝ์ ๋ฃ์ด์ผํ ์ด์ ๊ฐ์
{
currentGun.currentBulletCount = currentGun.reloadBulletCount;
currentGun.carryBulletCount -= currentGun.reloadBulletCount;
//ํ์ฌ ์์ ํ ์ด์ ๊ฐ์๊ฐ ํ์ฐฝ์ ๋ฃ์ ๊ฐ์๋งํผ ๋น ์ง
}
else
{
// ๊ฐ์ง๊ณ ์๋ ์ด์์ด ํ์ฐฝ์ ๋ฃ์ด์ผํ ์ด์๋ณด๋ค ๋ถ์กฑํ ๊ฒฝ์ฐ
currentGun.currentBulletCount = currentGun.carryBulletCount;
currentGun.carryBulletCount = 0;
}
}
}
public ManageGun GetGun()
{
return currentGun;
}
}
|
cs |
์ ์ฝ๋๋ ์ฌ์ฅ์ ๊ณผ ์ด์ ๋ฐ๋ ๋ชจ์ ๋ด๋น์ ๊ตฌํํ ControlArm ํด๋์ค์ ๋๋ค.
ํ์ฌ ์์ ํ ์ด๊ธฐ์ ์ด์ ์ ๋ณด๋ฅผ ์๊ธฐ ์ํด ManageGun ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ ธ์ค๊ฒ ๋ฉ๋๋ค. (์ฝ๋ 8๋ฒ์งธ ์ค)
Reload() ํจ์ ์์ ์๋ if / else ๋ฌธ์ ํ์ฌ ์์ ํ๊ณ ์๋ ์ด์ ๊ฐ์์ ํ์ฐฝ์ ๋ฃ์ด์ผ ํ ์ด์ ๊ฐ์๋ฅผ ๋น๊ตํ์ฌ ์ฌ์ฅ์ ์ด ์ ์์ ์ผ๋ก ์ด๋ฃจ์ด์ง ์ ์๋๋ก ๋ง๋ค์์ต๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ManageGun : MonoBehaviour
{
[HideInInspector] public string gunName; // ํ์ฌ ์ด์ ์ด๋ฆ.
[Header("Bullet")]
[Tooltip("์ด์ ์ฌ์ฅ์ ๊ฐ์")]
public int reloadBulletCount = 20;
[Tooltip("ํ์ฌ ํ์์ง์ ๋จ์์๋ ์ด์์ ๊ฐ์")]
public int currentBulletCount = 20;
[Tooltip("์ต๋ ์์ ๊ฐ๋ฅ ์ด์ ๊ฐ์")]
public int maxBulletCount = 60;
[Tooltip("ํ์ฌ ์์ ํ๊ณ ์๋ ์ด์ ๊ฐ์")]
public int carryBulletCount = 60;
}
|
cs |
ํ์ฌ ์ด์ ์ํ(์ฌ์ฅ์ ์ ์ผ๋ง๋ ํ ๊ฒ์ธ์ง, ์์ ํ ์ด์, ํ์ฐฝ์ ์ผ๋ง๋ ๋ฃ์ด์ผ ํ๋์ง ๋ฑ)๋ฅผ ์ ์ ์๋ ManageGun ํด๋์ค์ ๋๋ค.
์ด์ ๋ง๋ค์๋ ์ ๋๋ฉ์ด์ ๊ณผ ํ์ํ ์ปดํฌ๋ํธ๋ฅผ ๋ฃ์ด์ค ๋ชจ์ต์ ๋๋ค. Handgun_Aim_Pose ์ค๋ธ์ ํธ๋ ํ๋ ์ด์ด์ ํ ์ ๋๋ค. ์ฌ์ฅ์ ์ ๋ด๋นํ๋ ์ปดํฌ๋ํธ๋ฅผ ์ด์ ๋ฃ์ด์ผ ํ ์ง, ํ๋ ์ด์ด์ ํ์ ๋ฃ์ด์ค์ผ ํ ์ง ๊ณ ๋ฏผํ์๋๋ฐ, ์๋ฌด๋๋ ํ์ฐฝ์ ์๋ก ๋ฐ๊ฟ ๋๋ ํ์ ๊ฐ์ ์ด ๋ ํฌ๋ค๊ณ ์๊ฐ๋ผ ํ๋ ์ด์ด์ ํ ์ค๋ธ์ ํธ์ธ Handgun_Aim_Pose์ ๋ฃ์ด์ฃผ๊ฒ ๋์์ต๋๋ค.
UI์ Fire ๋ฒํผ๊ณผ Reload ๋ฒํผ์ ๋๋ฅผ ๋ ๋นจ๊ฐ์ ์์ผ๋ก ๊ทธ๋ ค์ง ์ฝ๋๊ฐ ์คํํ์ฌ ๋ชจ์ ์ด ์ ์์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋๋ก On Click() ํจ์์์ ์ฒ๋ฆฌํด์ฃผ์์ต๋๋ค.
์ค์ - ์ด ์ฌ์ฅ์ ๋ชจ์ ์ค๋ฅ
์ฒซ ๋ฒ์งธ ์ฌ์ง์ ํ๋ ์ด์ด ํ ์ค๋ธ์ ํธ์ ์์ ์ค๋ธ์ ํธ๋ฅผ ๊ถ์ด ์ค๋ธ์ ํธ๋ก ๋ฃ์ ๋ชจ์ต์ ๋๋ค.
ํ์ง๋ง ๋ ๋ฒ์งธ ์ฌ์ง์ฒ๋ผ ์ฌ์ฅ์ ๋ชจ์ ๋์์ ํ ๋ ํ๋ ์ด์ด์ ํ์ด ์ด์ ๊ฐ์ง๊ณ ์ฌ์ฅ์ ํ์ง ์๊ณ , ์ด๋ง ๊ณต์ค์ ๋ฅ๋ฅ ๋ ์๋ ๋ชจ์ต์ ๋ณด์ด๊ณ ์์ต๋๋ค.
์ ์ฌ์ง์ฒ๋ผ ik_hand_r ์์ HandGun(๊ถ์ด)์ค๋ธ์ ํธ๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ์ฌ์ฅ์ ์ ๋ชจ์ต์ด ์ ์์ ์ผ๋ก ๋์ํ ์ ์์ต๋๋ค.