Unity

유니티 스팀 멀티 연동하기 - 3. 플레이어 및 변수 연동

devkimluxx 2023. 10. 13. 21:30
728x90

[유니티 스팀 멀티 연동하기 - 2. 로비]

 

변수를 연동하는 방법은 간단하다.

이미 이전 글에서도 사용했었지만, SyncVar 어트리뷰트를 사용하면 된다.

이전 장에서 작성했던 PlayerObjectController 스크립트에서 플레이어의 이름을 공유하는 기능을 추가하도록 변경한다.

플레이어 이름은 스팀에서 설정한 이름을 가져오도록 한다.

 

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
using Steamworks;
 
public class PlayerObjectController : NetworkBehaviour
{
    #region MEMBER_BASE
    [SyncVar]
    public int ConnectionID;
    [SyncVar]
    public int PlayerIdNumber;
    [SyncVar]
    public ulong PlayerSteamID;
    [SyncVar(hook = nameof(PlayerNameUpdate))]
    public string PlayerName;
 
    private CustomNetworkManager manager;
    private CustomNetworkManager Manager
    {
        get
        {
            if (manager != null)
            {
                return manager;
            }
            return manager = CustomNetworkManager.singleton as CustomNetworkManager;
        }
    }
 
    #endregion
 
 
    private void Start()
    {
        DontDestroyOnLoad(this.gameObject);
    }
 
    #region ON_CREATE
 
    public override void OnStartAuthority()
    {
        CmdSetPlayerName(SteamFriends.GetPersonaName().ToString());
        gameObject.name = "LocalGamePlayer";
    }
 
    public override void OnStartClient()
    {
        Manager.GamePlayers.Add(this);
    }
 
    public override void OnStopClient()
    {
        Manager.GamePlayers.Remove(this);
    }
 
    [Command]
    private void CmdSetPlayerName(string playerName)
    {
        this.PlayerNameUpdate(this.PlayerName, playerName);
    }
 
    public void PlayerNameUpdate(string OldValue, string NewValue)
    {
        if(isServer)
        {
            this.PlayerName = NewValue;
        }
        if(isClient)
        {
           
        }
    }
 
 
 
    #endregion
 
}
cs

위의 변수들과는 다르게, 훅 기능을 사용해서 기존값에서 변동이 있을 때 변경하도록 하는 것이다.

OnStartAuthority()는 자신의 플레이어가 시작했을 때 발동하는 메소드인데, 이때 Command 어트리뷰트를 단 CmdSetPlayerName()을 실행하면서 로비의 모든 사람이 플레이어 이름을 공유받게 된다.

 

 

다음으로는 이동의 구현이다.

PlayerObject에서 필요한 컴포넌트

이동의 경우 Network Transform 컴포넌트가 있어 쉽게 구현할 수 있다.

다른 플레이어와 Transform 값을 공유하려면 Network Transform을 넣으면 된다.

Network Transform의 경우, Sync Position, Sync Rotation, Sync Scale의 체크박스를 통해 어느것을 연동하고, 하지 않을지를 정할 수 있다. 컴포넌트의 맨 아래에 Sync Direction은 'Client To Server'로 맞춘다.

 

Network Transform이 네트워크 기능을 맡고 있기 때문에, 이동 구현의 경우 싱글 게임과 구현 방법이 거의 같다.

아래의 코드처럼 PlayerMovementController 스크립트를 작성한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
using UnityEngine.SceneManagement;
public class PlayerMovementController : NetworkBehaviour
{
    public float Speed = 1f;
    void Update()
    {
        if(SceneManager.GetActiveScene().name == Constant.SCENE_GAME)	//Constant.SCENE_GAME은 현재 씬 이름에 맞게 바꿀 것
        {
            if(isLocalPlayer)//예전에는 isOwned였으나, 현재는 바뀜)
                Move();
        }
    }
    public void SetPosition()
    {
        transform.position = new Vector3(Random.Range(-2, 2), Random.Range(-2, 2));
    }
    public void Move()
    {
        float x = Input.GetAxisRaw("Horizontal");
        float y = Input.GetAxisRaw("Vertical");
        Vector3 dir = new Vector3(x, y);
        transform.position += dir * Speed * Time.deltaTime;
    }
}

 

isLocalPlayer 조건문 부분만 유의하면 된다.

자신의 플레이어일 때만 움직이게 해야 하기 때문이다.

작성한 스크립트는 PlayerObject 프리팹에 컴포넌트로 추가한다.

완전한 PlayerObject의 모습

 

728x90