Skip to content

Latest commit

ย 

History

History
399 lines (286 loc) ยท 15.5 KB

File metadata and controls

399 lines (286 loc) ยท 15.5 KB

SW ์˜คํ”ˆ์†Œ์Šค ๊ธฐ๋ฐ˜ ๋ฉ€ํ‹ฐํ”Œ๋ ˆ์ด์–ด ์ŠˆํŒ…๊ฒŒ์ž„ ๊ฐœ๋ฐœ์ž ๊ฐ€์ด๋“œ

1. ๊ฒŒ์ž„ ์‹คํ–‰ ๋ฐ ํ…Œ์ŠคํŠธ ์‹œ ์œ ์˜์‚ฌํ•ญ

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

  • ๊ฐ€์žฅ ๊ฐ„ํŽธํ•œ ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•:

    • ํ•˜๋‚˜๋Š” Build(Build Settings โ†’ Build) ํ•˜์—ฌ ์‹คํ–‰ (.exe ๋˜๋Š” Android APK ๋“ฑ)
    • ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ์—๋””ํ„ฐ(Play ๋ชจ๋“œ) ์—์„œ ์‹คํ–‰
  • ๊ฒŒ์ž„ ์‹œ์ž‘ ์‹œ ๋ฐ˜๋“œ์‹œ LobbyScene๋ถ€ํ„ฐ ์‹คํ–‰ํ•ด์•ผ Photon ์„œ๋ฒ„์™€ ์ •์ƒ์ ์œผ๋กœ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

2. GameManager ๊ตฌ์„ฑ ๋ฐ ๋งค๋‹ˆ์ € ๊ตฌ์กฐ

GameManager๋Š” ํ”„๋กœ์ ํŠธ ๋‚ด ๋ชจ๋“  ๋งค๋‹ˆ์ €๋“ค์˜ ์ค‘์•™ ์ดˆ๊ธฐํ™” ๋ฐ ๋ฆด๋ฆฌ์ฆˆ, ์‹ฑ๊ธ€ํ†ค ์ ‘๊ทผ ๋ฐฉ์‹์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

public static DataManager Data { get; } = new DataManager();

var managers = new List<IManager>
{
    UI,
    Scene,
    Resource,
    Photon,
    Data,
};

private static void Relese()
{
    Scene?.Release();
    UI?.Release();
    Resource?.Release();
    Photon?.Release();
    Data?.Release();
}
  • ๊ฐ ๋งค๋‹ˆ์ €๋Š” static์œผ๋กœ ์„ ์–ธ๋˜๋ฏ€๋กœ GameManager.Data.๊ธฐ๋Šฅ()์ฒ˜๋Ÿผ ์ ‘๊ทผํ•ฉ๋‹ˆ๋‹ค.
  • ์”ฌ ์ „ํ™˜ ์‹œ์—๋„ ์œ ์ง€๋˜๋ฉฐ ์ „์—ญ์—์„œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

3. UI ๊ด€๋ จ ๊ฐ€์ด๋“œ (UIManager, IPopupPresenter)

  • UIManager๋Š” ํŒ์—… UI์˜ ์ƒ์„ฑ, ํ‘œ์‹œ, ์ˆจ๊น€, ์Šคํƒ ๊ด€๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
๋ฉ”์„œ๋“œ ์„ค๋ช…
ShowPopup(string popupName) ๋น„๋™๊ธฐ๋กœ ํŒ์—… ์ƒ์„ฑ ๋ฐ ํ‘œ์‹œ (์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ)
HidePopup(IPopupPresenter popup) ํŒ์—… ์Šคํƒ์—์„œ ์ œ๊ฑฐ ๋ฐ ์ˆจ๊น€
IsPopupStack(string popupName) ํŒ์—… ์Šคํƒ์— ํ•ด๋‹น ์ด๋ฆ„ ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ
CreatePopup(string popupName) ์ฃผ์†Œ ๊ธฐ๋ฐ˜์œผ๋กœ ํŒ์—… ์˜ค๋ธŒ์ ํŠธ ์ƒ์„ฑ
void GetPlayerInput()
{
    if (Input.GetKeyDown(KeyCode.Tab))
    {
        var popup = GameManager.UI.IsPopupStack(matchPopupName);
        if (popup != null)
            GameManager.UI.HidePopup(popup);
        else
            GameManager.UI.ShowPopup(matchPopupName).Forget();
    }
}

์—ฐ๋™ ์กฐ๊ฑด

  • ํŒ์—… ํ”„๋ฆฌํŒน์€ ResourceManager๋ฅผ ํ†ตํ•ด ๋กœ๋“œ ๊ฐ€๋Šฅํ•ด์•ผ ํ•จ
  • IPopupPresenter๋ฅผ ๊ตฌํ˜„ํ•œ MonoBehaviour ์ปดํฌ๋„ŒํŠธ๋ฅผ ํฌํ•จํ•ด์•ผ ํ•จ
  • ์ตœ์†Œํ•œ ShowView(), HideView() ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ

์ถ”ํ›„ ํ™•์žฅ ๊ฐ€๋Šฅ ์š”์†Œ

  • PopupType ๊ธฐ๋ฐ˜ ๋ถ„๊ธฐ ํ™•์žฅ
  • MVP ๊ตฌ์กฐ ์ ์šฉ ์‹œ IPresenter๋กœ ์ผ๋ฐ˜ํ™” ๊ฐ€๋Šฅ
  • PresenterBase.cs ๋“ฑ์„ ์ด์šฉํ•œ ์ด๋ฒคํŠธ ์—ฐ๋™ ๊ตฌ์กฐ ๊ฐ€๋Šฅ

4. ResourceManager ๊ฐ€์ด๋“œ

Unity Addressables ๊ธฐ๋ฐ˜์œผ๋กœ ๋น„๋™๊ธฐ ๋ฐฉ์‹ ๋ฆฌ์†Œ์Šค ๋กœ๋”ฉ/์บ์‹ฑ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

์ฃผ์š” ๊ธฐ๋Šฅ

  • ์ฃผ์†Œ ๊ธฐ๋ฐ˜ GameObject ๋น„๋™๊ธฐ ๋กœ๋”ฉ
  • ์ด๋ฆ„ ์ •๋ฆฌํ•˜์—ฌ ์บ์‹œ ํ‚ค ์ผ๊ด€์„ฑ ์œ ์ง€
  • ํŠน์ • ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„ ๋กœ๋”ฉ ์ง€์›
  • ๋‚ด๋ถ€ ํ•ธ๋“ค ์บ์‹ฑ
private readonly Dictionary<string, AsyncOperationHandle<GameObject>> _instantiateResource;

async UniTask<GameObject> Instantiate(string address, Transform parent = null);
async UniTask<T> Instantiate<T>(string address, Transform parent = null) where T : class;

์˜ˆ์‹œ:

GameObject avatar = await GameManager.Resource.Instantiate("PlayerInfo", parent);
return await GameManager.Resource.Instantiate<IPopupPresenter>(popupName, container);

5. PhotonManager ๊ฐ€์ด๋“œ (๋ฉ€ํ‹ฐํ”Œ๋ ˆ์ด ์‹œ์Šคํ…œ)

PhotonManager๋Š” ์„œ๋ฒ„ ์—ฐ๊ฒฐ, ๋งค์นญ, ๋ฃธ ์ƒ์„ฑ, ์”ฌ ์ „ํ™˜ ๋“ฑ์˜ ์ƒ์œ„ ๋„คํŠธ์›Œํฌ ๋กœ์ง์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ์„ฑ ๊ตฌ์กฐ

  • ์ƒ์œ„ ๋งค๋‹ˆ์ €: PhotonManager

    • ์„œ๋ฒ„ ์—ฐ๊ฒฐ, ๋งค์นญ, GamePhase์— ๋”ฐ๋ผ ์”ฌ ์ „ํ™˜
    • ๊ฐ ์”ฌ๋ณ„ IScenePhotonManager ์ดˆ๊ธฐํ™”
  • ํ•˜์œ„ ๋งค๋‹ˆ์ €:

    • WaitingRoomPhotonManager: ๋Œ€๊ธฐ๋ฐฉ ์ž…์žฅ/์ค€๋น„ ์ƒํƒœ ์ฒ˜๋ฆฌ
    • InGamePhotonManager: ์ธ๊ฒŒ์ž„ ์กฐ์ž‘, ์ŠนํŒจ, ์บ๋ฆญํ„ฐ ๋™๊ธฐํ™” ๋“ฑ ์ฒ˜๋ฆฌ

๊ธฐ๋ณธ ํ๋ฆ„

ConnectToPhoton()
โ†’ OnConnectedToMaster() โ†’ JoinLobby()
โ†’ OnJoinedLobby() โ†’ StartRandomMatch()
โ†’ JoinRandomRoom() โ†’ OnJoinRandomFailed() โ†’ CreateRoom()
โ†’ OnJoinedRoom() โ†’ ์”ฌ ์ „ํ™˜

6. Photon ์‚ฌ์šฉ ๊ฐ€์ด๋“œ (๋„คํŠธ์›Œํฌ ๋™๊ธฐํ™” ๋ฐ RPC)

ํ•„์ˆ˜ ์กฐ๊ฑด

  • ๋™๊ธฐํ™” ๋Œ€์ƒ ์˜ค๋ธŒ์ ํŠธ์—๋Š” ๋ฐ˜๋“œ์‹œ PhotonView ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•จ
  • photonView.IsMine ์ฒดํฌ๋ฅผ ํ†ตํ•ด ๋กœ์ปฌ ํ”Œ๋ ˆ์ด์–ด๋งŒ ์กฐ์ž‘ ๊ฐ€๋Šฅํ•˜๋„๋ก ์ฒ˜๋ฆฌ
void Update()
{
    if (!photonView.IsMine) return; // ๋‚ด ์บ๋ฆญํ„ฐ๋งŒ ์กฐ์ž‘

    float h = Input.GetAxis("Horizontal");
    float v = Input.GetAxis("Vertical");
    transform.Translate(new Vector3(h, 0, v));
}

๋™๊ธฐํ™” ์˜ˆ์‹œ: ํƒ„ํ™˜ ๋ฐœ์‚ฌ

GameObject bullet = PhotonNetwork.Instantiate("Projectiles/Bullet", spawnPos, rotation);
bullet.GetComponent<Projectile>().isRPCFire = true;
  • ๋กœ์ปฌ์—์„œ๋งŒ Instantiate ๊ฐ€๋Šฅํ•˜๋„๋ก ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ
  • ํƒ„ํ™˜์ด ์ด๋™ ์ค‘์ผ ๋•Œ, ์œ„์น˜๋Š” photonView.IsMine์ธ ๊ฒฝ์šฐ๋งŒ ์ด๋™์‹œํ‚ค๊ณ  ๊ทธ ์™ธ์—๋Š” ๋™๊ธฐํ™” ๋Œ€๊ธฐ

RPC ์‚ฌ์šฉ ์˜ˆ์‹œ

[PunRPC]
void RPC_Fire(float angle, bool isRight)
{
    SetActive(true);
    hasLaunched = true;
    transform.rotation = Quaternion.Euler(0, 0, angle);
    // ๊ธฐํƒ€ ์ดํŽ™ํŠธ ์‹คํ–‰
}
  • RPC๋Š” photonView.RPC("RPC_Fire", RpcTarget.All, angle, isRight); ํ˜•์‹์œผ๋กœ ํ˜ธ์ถœ

Animator/Transform ๋™๊ธฐํ™” ๊ฐ€์ด๋“œ

  • ์›€์ง์ž„ ๋ฐ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋™๊ธฐํ™”๋ฅผ ์œ„ํ•ด PhotonView์˜ Observed Components์— Transform, Animator๋ฅผ ํฌํ•จ์‹œ์ผœ์•ผ ํ•จ
  • Animator๊ฐ€ ์—†์œผ๋ฉด Mecanim ๊ธฐ๋ฐ˜ ๋™๊ธฐํ™”๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ, ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ์Šคํ…œ์€ ๋ฐ˜๋“œ์‹œ Mecanim(Animator Controller) ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ

์ง์ ‘ ๋™๊ธฐํ™” ๋ฐฉ์‹: OnPhotonSerializeView

  • PhotonStream์„ ์ด์šฉํ•ด ์ขŒ์šฐ ๋ฐฉํ–ฅ, ๊ฐ๋„ ๋“ฑ ๊ฐœ๋ณ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์œผ๋กœ ๋™๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
    if (stream.IsWriting)
    {
        bool isLeftDirection = crosshairMouse.AimDirection.x < 0.1f;
        stream.SendNext(isLeftDirection);
    }
    else
    {
        bool isLeftDirection = (bool)stream.ReceiveNext();
        Debug.Log("isLeftDirection: " + isLeftDirection);

        isRightDirection = isLeftDirection;
        SetBodyPartsDirection(isLeftDirection ? Direction.Left : Direction.Right);
    }
}
  • ์ฃผ๋กœ ์บ๋ฆญํ„ฐ์˜ ํšŒ์ „ ๋ฐฉํ–ฅ, ๋ถ€์œ„ ์ƒํƒœ, ์—์ž„ ๋ฐฉํ–ฅ ๋“ฑ์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋‹ค๋ฅธ ํ”Œ๋ ˆ์ด์–ด์—๊ฒŒ ์ „๋‹ฌํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

7. ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ์Šคํ…œ ๊ฐ€์ด๋“œ

๊ธฐ์กด ์˜คํ”ˆ์†Œ์Šค๋Š” Animation Clip๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด์—ˆ์œผ๋‚˜, ๋ณธ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” Photon๊ณผ์˜ ํ˜ธํ™˜์„ ์œ„ํ•ด Animator Controller ๊ธฐ๋ฐ˜์˜ Mecanim ๊ตฌ์กฐ๋กœ ๋ณ€๊ฒฝํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์ฃผ์š” ๊ตฌํ˜„ ์‚ฌํ•ญ

  • ๊ฐ ๋ฌด๊ธฐ๋งˆ๋‹ค ์ „์šฉ Animator Controller ์ƒ์„ฑ (Idle, BasicShot, StrongShot ๋“ฑ ์ƒํƒœ ์ •์˜)
  • animator.SetInteger("WeaponAction", ...) ๋ฐฉ์‹์œผ๋กœ ์ƒํƒœ ์ „์ด ๊ตฌํ˜„
  • Animator ์ปดํฌ๋„ŒํŠธ๋Š” PhotonView์˜ Observed Components์— ํฌํ•จํ•˜์—ฌ ๋„คํŠธ์›Œํฌ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋™๊ธฐํ™” ๊ฐ€๋Šฅ

์ด๋ฅผ ํ†ตํ•ด ๋ฉ€ํ‹ฐํ”Œ๋ ˆ์ด ํ™˜๊ฒฝ์—์„œ๋„ ๋ชจ๋“  ์‚ฌ์šฉ์ž์—๊ฒŒ ์ผ๊ด€๋œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์ƒ์ด ๊ฐ€๋Šฅํ•ด์กŒ์œผ๋ฉฐ, ์ปค์Šคํ…€ ๋ฌด๊ธฐ ๋™์ž‘ ๋ฐ ํ”ผ๊ฒฉ/๋ฐœ์‚ฌ ์ดํŽ™ํŠธ๋„ ์ •ํ™•ํžˆ ๋™๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค.

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

8. ๋ฌด๊ธฐ ์‹œ์Šคํ…œ ์ „์šฉ ๋ฆฌ์†Œ์Šค ๋กœ๋”ฉ ํ•จ์ˆ˜ ๊ฐ€์ด๋“œ (Weapon.cs)

๊ฐœ์š”

Weapon.cs๋Š” ๊ฐ ๋ฌด๊ธฐ๋ณ„๋กœ ํ•„์š”ํ•œ ์Šคํ”„๋ผ์ดํŠธ, ํ”„๋ฆฌํŒน, ์˜ค๋””์˜ค ํด๋ฆฝ ๋“ฑ์„ ๋น ๋ฅด๊ฒŒ ๋กœ๋“œํ•˜๊ธฐ ์œ„ํ•ด ์ž์ฒด์ ์ธ ๋ฆฌ์†Œ์Šค ๋กœ๋”ฉ ํ•จ์ˆ˜๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ์‹์€ ๋ฒ”์šฉ ๋ฆฌ์†Œ์Šค ๋งค๋‹ˆ์ €๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , ๋ฌด๊ธฐ ์‹œ์Šคํ…œ์ฒ˜๋Ÿผ ์ œํ•œ๋œ ๋ฒ”์œ„์˜ ํด๋ž˜์Šค์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ„๋‹จํžˆ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

โ€ป ๋ฒ”์šฉ ๋ฆฌ์†Œ์Šค ๋กœ๋”ฉ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋Š” ResourceManager + AddressableAssets ๊ตฌ์กฐ ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ๋‹จ, ๋ฌด๊ธฐ ์‹œ์Šคํ…œ์ฒ˜๋Ÿผ ํ•œ ํด๋ž˜์Šค์— ํ•œ์ •๋œ ๋ฆฌ์†Œ์Šค๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ, ํ˜„์žฌ ๊ตฌ์กฐ์ฒ˜๋Ÿผ Resources.Load() ๊ธฐ๋ฐ˜์˜ ์ง์ ‘ ๋กœ๋”ฉ ๋ฐฉ์‹์ด ์œ ๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


์ œ๊ณต๋˜๋Š” ํ•จ์ˆ˜ ๋ชฉ๋ก

๋ฉ”์„œ๋“œ๋ช… ์„ค๋ช…
getProjPref(string) ํƒ„ํ™˜ ํ”„๋ฆฌํŒน ๋กœ๋“œ (Resources/Projectiles/)
getAudioClip(string) ๋ฌด๊ธฐ ๋ฐœ์‚ฌ ์˜ค๋””์˜ค ๋กœ๋“œ (Resources/Audio/SFX/Weapons/)
getAnimator() ์ž๊ธฐ ์ž์‹  ๋˜๋Š” ๋ถ€๋ชจ์—์„œ Animator ํƒ์ƒ‰
getSpriteSheet(string) ์Šคํ”„๋ผ์ดํŠธ ์‹œํŠธ ์ „์ฒด ๋กœ๋“œ (Resources/Sprites/)
getSpriteFromSheet(Sprite[], string) ์‹œํŠธ์—์„œ ํŠน์ • ์Šคํ”„๋ผ์ดํŠธ ์ถ”์ถœ
getObject(string) ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜ GameObject ๋กœ๋“œ
createPSp(...) Projectile ๋ฐœ์‚ฌ ์œ„์น˜์šฉ Transform ์ƒ์„ฑ
createPFX(...) ํŒŒํ‹ฐํด ํ”„๋ฆฌํŒน ์ธ์Šคํ„ด์Šคํ™” ๋ฐ ๋น„ํ™œ์„ฑํ™” ์ƒํƒœ๋กœ ๋ฆฌํ„ด
createSpriteObject(...) ์Šคํ”„๋ผ์ดํŠธ๊ฐ€ ํฌํ•จ๋œ GameObject๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์›ํ•˜๋Š” ์œ„์น˜์— ๋ฐฐ์น˜

์‚ฌ์šฉ ์˜ˆ์‹œ

// ๋ฌด๊ธฐ ์ดˆ๊ธฐํ™” ์‹œ
basicProjectilePrefab = getProjPref("pfab_Bullet_Laser_Small_Cyan");
strongProjectilePrefab = getProjPref("pfab_Bullet_Laser_MidSize_Blue");

AudioClip fireSFX = getAudioClip("shotgun_fire.wav");

Sprite[] sprites = getSpriteSheet("Weapons/Weapons_001");
Sprite muzzleSprite = getSpriteFromSheet(sprites, "LaserRifle_Muzzle");

createSpriteObject("Muzzle", muzzleSprite, 10, this, position: new Vector3(0.12f, 0, 0));

ResourceManager ๋ฐฉ์‹๊ณผ์˜ ๋น„๊ต

ํ•ญ๋ชฉ Weapon ์ „์šฉ ๋ฐฉ์‹ ResourceManager + Addressables
์‚ฌ์šฉ ๋ฒ”์œ„ ๋‹จ์ผ ํด๋ž˜์Šค (ex. ๋ฌด๊ธฐ) ์ „์ฒด ๊ฒŒ์ž„ ๋ฒ”์œ„ (UI, ์บ๋ฆญํ„ฐ ๋“ฑ)
๋ฆฌ์†Œ์Šค ๊ฒฝ๋กœ ์ฝ”๋“œ์— ํ•˜๋“œ์ฝ”๋”ฉ Addressables ์ฃผ์†Œ ๊ธฐ๋ฐ˜
์บ์‹ฑ ์ˆ˜๋™ ๊ด€๋ฆฌ ์ž๋™ ์บ์‹ฑ ๋ฐ ํ•ด์ œ ๊ฐ€๋Šฅ
๋น„๋™๊ธฐ ์ง€์› โŒ (Resources.Load) โœ… UniTask ๊ธฐ๋ฐ˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ
์žฅ์  ๋น ๋ฅด๊ณ  ์ง๊ด€์ , ์˜์กด์„ฑ ์—†์Œ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์— ์ ํ•ฉ, ์žฌ์‚ฌ์šฉ์„ฑ ๋†’์Œ

โœ… ๊ฐ€์ด๋“œ๋ผ์ธ

  • ๋ฌด๊ธฐ ํ•˜๋‚˜์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๋ฆฌ์†Œ์Šค: Weapon.cs ๋‚ด๋ถ€ ํ•จ์ˆ˜ ์‚ฌ์šฉ (๋น ๋ฅด๊ณ  ๋‹จ์ˆœํ•จ)
  • ์—ฌ๋Ÿฌ ์‹œ์Šคํ…œ์—์„œ ๊ณต์œ ๋˜๋Š” ๋ฆฌ์†Œ์Šค: ResourceManager์™€ Addressables๋ฅผ ํ†ตํ•ด ๊ด€๋ฆฌ (ํ™•์žฅ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜ ์šฐ์ˆ˜)

ํ™•์žฅ ์‹œ ์ฐธ๊ณ  ์‚ฌํ•ญ

  • ์ด ํ•จ์ˆ˜๋“ค์€ ๋ชจ๋‘ protected๋กœ ์„ ์–ธ๋˜์–ด ์žˆ์–ด, ํ•˜์œ„ ๋ฌด๊ธฐ ํด๋ž˜์Šค์—์„œ ๋ฐ”๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • Resources.Load() ๊ธฐ๋ฐ˜์ด๋ฏ€๋กœ ๊ฒฝ๋กœ ์˜คํƒ€ ์‹œ null ๋ฐ˜ํ™˜ โ†’ ๋ฐ˜๋“œ์‹œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ํ•„์š”
  • ์œ ์ง€๋ณด์ˆ˜ ์ค‘ Addressables๋กœ ์ „ํ™˜ํ•˜๋ ค๋ฉด getObject() โ†’ GameManager.Resource.Instantiate() ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ

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

9. ์‹ ๊ทœ ๋ฌด๊ธฐ ๊ธฐ์ดˆ ํด๋ž˜์Šค: ShotGun

๊ฐœ์š”

Weapon_ShotGun์€ ๊ธฐ์กด ๋ฌด๊ธฐ ์‹œ์Šคํ…œ(Weapon)์„ ์ƒ์†ํ•˜์—ฌ, ํ•œ ๋ฒˆ์— ์—ฌ๋Ÿฌ ๋ฐœ์˜ ํƒ„ํ™˜์„ ํผ๋œจ๋ฆฌ๋Š” ์ƒท๊ฑด ๊ณ„์—ด ๋ฌด๊ธฐ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ์ดˆ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๊ณต๊ฒฉ/๊ฐ•ํ™” ๊ณต๊ฒฉ ๋ชจ๋‘ ๋‹คํƒ„ ๋ฐœ์‚ฌ๋ฅผ ์ง€์›ํ•˜๋ฉฐ, ๋ฐœ์‚ฌ ๊ฐ„๊ฒฉ๊ณผ ํƒ„ํ™˜ ๊ฐœ์ˆ˜ ์„ค์ •์ด ๊ฐ๊ฐ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

FINAL_Weapon_LaserShotGun์€ ์ด๋ฅผ ์ƒ์†ํ•˜์—ฌ ์‹ค์ œ ๊ตฌํ˜„๋œ ์ƒท๊ฑด ๋ฌด๊ธฐ๋กœ, ์Šคํ”„๋ผ์ดํŠธ ์„ค์ • ๋ฐ ๋ฐœ์‚ฌ ์œ„์น˜, ํƒ„ํ™˜ ํ”„๋ฆฌํŒน์„ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.


๊ธฐ๋ณธ ๋™์ž‘ ์‚ฌ์–‘

๊ณต๊ฒฉ ์œ ํ˜• ๋ฐœ์‚ฌ ํƒ„ํ™˜ ์ˆ˜ ๋ฐœ์‚ฌ ๊ฐ„๊ฒฉ (์ดˆ)
์ผ๋ฐ˜ ๊ณต๊ฒฉ 4๋ฐœ 0.5์ดˆ
๊ฐ•ํ™” ๊ณต๊ฒฉ 8๋ฐœ 1.0์ดˆ
  • ๊ฐ ํƒ„ํ™˜์€ ๋žœ๋ค ํšŒ์ „ ๊ฐ๋„์™€ ์†๋„๋ฅผ ์ ์šฉํ•˜์—ฌ ํผ์ง€๋Š” ํ˜•ํƒœ๋กœ ๋ฐœ์‚ฌ๋จ

๋ฌด๊ธฐ ๋ฐœ์‚ฌ ํ•จ์ˆ˜

protected override void PrimaryFire(bool isRight)
{
    for (int i = 0; i < 4; i++)
    {
        GameObject bullet = PhotonNetwork.Instantiate("Projectiles/" + basicProjectilePrefab.name,
            projectileSpawnPoint.position, projectileSpawnPoint.rotation);

        Projectile proj = bullet.GetComponent<Projectile>();
        proj.Speed = 20f * Random.Range(0.9f, 1.1f);
        proj.setVolume(2f / 3);
        proj.isRPCFire = (PhotonNetwork.InRoom && PhotonManager._currentPhase == PhotonManager.GamePhase.InGame);
        proj.Fire(Random.Range(-10f, 10f), isRight);
    }
}

10. ์•„์ดํ…œ ๋ฌด๊ธฐ ๊ต์ฒด ๋ฐ ์ƒํ˜ธ์ž‘์šฉ ์‹œ์Šคํ…œ

๊ฐœ์š”

๋ณธ ์‹œ์Šคํ…œ์€ ํ”Œ๋ ˆ์ด์–ด๊ฐ€ F ํ‚ค๋ฅผ ๋ˆŒ๋Ÿฌ ๋ฐ”๋‹ฅ์— ๋–จ์–ด์ง„ ๋ฌด๊ธฐ ์•„์ดํ…œ๊ณผ ํ˜„์žฌ ์žฅ๋น„ ์ค‘์ธ ๋ฌด๊ธฐ๋ฅผ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ์˜คํ”ˆ์†Œ์Šค ๊ตฌ์กฐ์— ํฌํ•จ๋œ TadaInput, PlayerController, WeaponHandler ํด๋ž˜์Šค๋“ค์„ ๊ทธ๋Œ€๋กœ ํ™œ์šฉํ•˜์—ฌ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค.

ํ‚ค ์ž…๋ ฅ ์ฒ˜๋ฆฌ (TadaInput)

F ํ‚ค๋Š” TadaInput.ThisKey.GetItem์œผ๋กœ ์ง€์ •ํ•˜์—ฌ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

if (Input.GetKeyDown(KeyCode.F))
    StoreCurrentKeyDown(ThisKey.GetItem);

๋“ฑ๋ก๋œ ํ‚ค๋Š” ์ž…๋ ฅ์ด ํ•„์š”ํ•œ ์œ„์น˜ (์˜ˆ: PlayerController)์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:

if (TadaInput.GetKeyDown(TadaInput.ThisKey.GetItem))
{
    GameObject obj = _PlayerPhysics.getCollidedObject();
    if (obj != null)
    {
        Item item = obj.GetComponent<Item>();
        if (item != null)
        {
            _WeaponHandler.GetItemWeapon(item);
        }
    }
}
  • ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์ถฉ๋Œํ•œ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ Item์ผ ๊ฒฝ์šฐ์—๋งŒ ์ƒํ˜ธ์ž‘์šฉ ์‹คํ–‰
  • WeaponHandler๋ฅผ ํ†ตํ•ด ๋ฌด๊ธฐ ์Šค์™‘ ์ฒ˜๋ฆฌ

๋ฌด๊ธฐ ๊ต์ฒด ์ฒ˜๋ฆฌ (WeaponHandler.GetItemWeapon())

public void GetItemWeapon(Item item)
{
    Weapon now = currentWeapon;
    Weapon get = item.weapon;

    weapons[currentWeaponIndex] = get;
    currentWeapon = get;

    get.transform.SetParent(now.transform.parent, false);
    now.transform.SetParent(item.transform, false);

    item.weapon = now;

    get.reload();
    now.stop();
}
  • ํ˜„์žฌ ์žฅ๋น„ ๋ฌด๊ธฐ์™€ ์•„์ดํ…œ ๋ฌด๊ธฐ๋ฅผ ์„œ๋กœ ๊ต์ฒด
  • Transform ๋ถ€๋ชจ๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ ์œ„์น˜ ์‹œ๊ฐ์ ์œผ๋กœ ์กฐ์ •
  • ์ƒˆ ๋ฌด๊ธฐ๋Š” reload(), ๊ธฐ์กด ๋ฌด๊ธฐ๋Š” stop()์„ ํ˜ธ์ถœํ•˜์—ฌ ๋ฌด๊ธฐ ์ƒํƒœ๋ฅผ ์ดˆ๊ธฐํ™”

๊ตฌํ˜„ ์š”์•ฝ

ํ•ญ๋ชฉ ์„ค๋ช…
์ž…๋ ฅ ํ‚ค F ํ‚ค (TadaInput.ThisKey.GetItem)
์ถฉ๋Œ ๊ฐ์ง€ PlayerPhysics.getCollidedObject() ์‚ฌ์šฉ
์ƒํ˜ธ์ž‘์šฉ ๋Œ€์ƒ Item ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ€์ง„ ์˜ค๋ธŒ์ ํŠธ
์ฒ˜๋ฆฌ ๋ฐฉ์‹ WeaponHandler๋ฅผ ํ†ตํ•ด ๋ฌด๊ธฐ ๊ฐ์ฒด ๊ฐ„ ์Šค์™‘

๋ณธ ๊ตฌ์กฐ๋Š” ์ง๊ด€์ ์ธ ์ƒํ˜ธ์ž‘์šฉ ํ๋ฆ„์„ ์ œ๊ณตํ•˜๋ฉฐ, ํ™•์žฅ ์‹œ ๋‹ค์–‘ํ•œ ์•„์ดํ…œ ์ข…๋ฅ˜(์ฒด๋ ฅ, ๋ฐฉ์–ด๊ตฌ, ๊ธฐํƒ€ ์†Œ๋น„ ์•„์ดํ…œ ๋“ฑ)๋กœ๋„ ์—ฐ๊ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.