실행 이미지

 

using Photon.Pun;
using System.Collections;
using Unity.VisualScripting;
using UnityEngine;

public class PlayerController : MonoBehaviourPun, IPunObservable
{
    [SerializeField] private float speed = 1f;
    [SerializeField] private GameObject bombPrefab;
    public float moveDistance = 10;
    private Animator anim;
    private PlayerType playerType;

    private Vector3 networkPosition;
    private Quaternion networkRotation;
    private Vector3 networkScale;
    private int networkAnimDir;
    private GameObject collidedBomb;   // 충돌된 BOMB 오브젝트를 저장할 변수

    private float distance;
    private float angle;

    public enum PlayerType
    {
        BombGuy,
        BigGuy
    }

    public void Init(PlayerType player)
    {
        playerType = player;
    }

    private void Start()
    {
        anim = this.GetComponentInChildren<Animator>();
        networkPosition = transform.position;
        networkRotation = transform.rotation;
        networkScale = transform.localScale;
        networkAnimDir = 0;

        if (playerType == PlayerType.BombGuy)
            StartCoroutine("CreateBomb");
        else
            StartCoroutine("AttackBomb");
    }

    void Update()
    {
        if (photonView.IsMine)
        {
            HandleMovement();
        }
        else
        {
            // 네트워크 위치, 회전, 스케일로 보간
            transform.position = Vector3.Lerp(transform.position, networkPosition, Time.deltaTime * 20);
            //transform.rotation = Quaternion.Slerp(transform.rotation, networkRotation, Time.deltaTime * 15);
            transform.localScale = networkScale;
            anim.SetInteger("dir", networkAnimDir);
        }
    }

    void HandleMovement()
    {
        float dirX = Input.GetAxisRaw("Horizontal");
        var dir = new Vector2(dirX, 0);

        transform.localScale = new Vector3(dirX == 0 ? transform.localScale.x : dirX, 1, 1);
        anim.SetInteger("dir", (int)dirX);

        transform.Translate(new Vector3(dir.x, dir.y, 0) * speed * Time.deltaTime);
    }

    public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        if (stream.IsWriting)
        {
            // 우리가 움직이는 캐릭터라면 현재 위치, 회전, 스케일, 애니메이션 상태를 네트워크로 전송
            stream.SendNext(transform.position);
            stream.SendNext(transform.rotation);
            stream.SendNext(transform.localScale);
            stream.SendNext(anim.GetInteger("dir"));
        }
        else
        {
            // 네트워크로부터 다른 플레이어의 위치, 회전, 스케일, 애니메이션 상태를 수신
            networkPosition = (Vector3)stream.ReceiveNext();
            networkRotation = (Quaternion)stream.ReceiveNext();
            networkScale = (Vector3)stream.ReceiveNext();
            networkAnimDir = (int)stream.ReceiveNext();
        }
    }

    // 트리거 시작 시 호출되는 함수
    void OnTriggerEnter2D(Collider2D other)
    {
        // 충돌된 오브젝트의 태그가 BOMB인지 확인
        if (other.gameObject.CompareTag("BOMB") && photonView.IsMine && playerType == PlayerType.BigGuy)
        {
            Debug.Log("폭탄 충돌 시작");
            collidedBomb = other.gameObject;
        }
    }

    // 트리거 종료 시 호출되는 함수
    void OnTriggerExit2D(Collider2D other)
    {
        // 충돌이 종료된 오브젝트의 태그가 BOMB인지 확인 
        if (other.gameObject.CompareTag("BOMB") && photonView.IsMine && playerType == PlayerType.BigGuy)
        {
            Debug.Log("폭탄 충돌 해제");
            collidedBomb = null;
        }
    }

    IEnumerator CreateBomb()
    {
        while (true)
        {
            if (photonView.IsMine && Input.GetKeyDown(KeyCode.Space) && playerType == PlayerType.BombGuy)
            {
                PhotonNetwork.Instantiate(bombPrefab.name, new Vector3(transform.position.x, -3.46f), Quaternion.identity);
                Debug.Log("폭탄 생성");
            }
            yield return null;
        }
    }

    IEnumerator AttackBomb()
    {
        while (true)
        {
            if (Input.GetKeyDown(KeyCode.Space) && playerType == PlayerType.BigGuy)
            {
                anim.SetTrigger("attackBomb");
                Debug.Log("폭탄 날리기");

                if (collidedBomb != null)
                {
                    photonView.RPC("MoveBomb", RpcTarget.All, collidedBomb.GetComponent<PhotonView>().ViewID, transform.localScale.x);
                }
            }
            yield return null;
        }
    }

    [PunRPC]
    void MoveBomb(int bombViewID, float direction)
    {
        GameObject bomb = PhotonView.Find(bombViewID).gameObject;
        Bomb bombScript = bomb.GetComponent<Bomb>();
        bombScript.dir = direction;
        bombScript.isMoved = true;
    }
}

PlayerController.cs

 

using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    public static GameManager Instance;

    private void Awake()
    {
        Instance = this;
    }

    [SerializeField] private GameObject bombGuyPrefab;
    [SerializeField] private GameObject bigGuyPrefab;

    private void Start()
    {
        if (PhotonNetwork.IsMasterClient)
        {
            // bombGuy 만들기
            GameObject go = PhotonNetwork.Instantiate(bombGuyPrefab.name, new Vector3(0, -4.37f, 0), Quaternion.identity);
            go.GetComponent<PlayerController>().Init(PlayerController.PlayerType.BombGuy);
        }
        else
        {
            // bigGuy 만들기
            GameObject go = PhotonNetwork.Instantiate(bigGuyPrefab.name, new Vector3(0, -4.37f, 0), Quaternion.identity);
            go.GetComponent<PlayerController>().Init(PlayerController.PlayerType.BigGuy);
        }
    }


}

GameManager.cs

 

using Photon.Pun;
using System.Collections;
using Unity.VisualScripting;
using UnityEngine;

public class Bomb : MonoBehaviourPun, IPunObservable
{
    [SerializeField] float speed = 1f;
    private float attenuation = 0.98f;
    public bool isMoved = false;
    public float dir = 1;

    private Vector3 networkPosition;

    void Start()
    {

    }

    void Update()
    {

        if (photonView.IsMine)
        {
            float speedX = speed;
            if (isMoved)
            {
                // 0.1 유닛씩 이동한다.
                this.gameObject.transform.Translate(new Vector3(speedX * dir, 0, 0) * Time.deltaTime);
            }

        }
        else
        {

            // 네트워크 위치로 보간
            transform.position = Vector3.Lerp(transform.position, networkPosition, Time.deltaTime * 10);

        }
    }


    public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        if (stream.IsWriting)
        {
            // 우리가 움직이는 객체라면 현재 위치를 네트워크로 전송
            stream.SendNext(transform.position);
            stream.SendNext(isMoved);
            stream.SendNext(dir);
        }
        else
        {
            // 네트워크로부터 다른 플레이어의 위치와 이동 상태를 수신
            networkPosition = (Vector3)stream.ReceiveNext();
            isMoved = (bool)stream.ReceiveNext();
            dir = (float)stream.ReceiveNext();
        }
    }

}

Bomb.cs

 

using Photon.Pun;
using Photon.Realtime;
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class LobbyMain : MonoBehaviourPunCallbacks
{
    [SerializeField] private string gameVersion;
    [SerializeField] private Text statusText;
    [SerializeField] private Button joinButton;

    // Start is called before the first frame update
    void Start()
    {
        // 마스터 서버 접속
        PhotonNetwork.GameVersion = gameVersion;
        PhotonNetwork.ConnectUsingSettings();
        PhotonNetwork.ConnectUsingSettings();   //마스터 서버 접속 시도 
        joinButton.interactable = false;
        UpdateStatusText("마스터 서버에 접속중");

        joinButton.onClick.AddListener(() =>
        {
            Connect();
        });
    }

    public void Connect()
    {
        //Join 버튼을 누르면 호출되는 점수
        joinButton.interactable = false;
        // 마스터 서버 접속죽인가?
        if (PhotonNetwork.IsConnected)
        {
            //랜덤룸 조인
            UpdateStatusText("방에 접속중...");
            PhotonNetwork.JoinRandomRoom();
        }
        else
        {
            //마스터서버에 재접속 시도
            ReconnectToMasterServer();
        }


    }
    public override void OnDisconnected(DisconnectCause cause)
    {
        // 마스터 서버에 접속 실패, 마스터 서버에 접속 되어있는 상태에서 솝속이 끊길떄, 호출되는 콜백
        joinButton.interactable = false;
        UpdateStatusText("오프라인 : 마스터 서버와 연결이 되지 않음\n접속 재시도중...");
        PhotonNetwork.ConnectUsingSettings();
    }


    public override void OnConnectedToMaster()
    {
        // 마스터 서버에 접속하면 호출되는 콜백
        joinButton.interactable = true;

        UpdateStatusText("온라인 : 마스터 서버와 연결됨");
    }


    private void UpdateStatusText(string v)
    {
        statusText.text = v;
    }





    public void ReconnectToMasterServer()
    {
        UpdateStatusText("오프라인 : 마스터 서버와 연결이 되지 않음\n접속 재시도 중...");

        PhotonNetwork.ConnectUsingSettings();
    }

    public override void OnJoinRandomFailed(short returnCode, string message)
    {
        // (빈방이 없어서) 랜덤 룸 참가에 실패한 경우. 호출되는 콜백
        UpdateStatusText("빈방이 없습니다.\n새로운 방을 생성 중입니다...");
        PhotonNetwork.CreateRoom(null, new RoomOptions() { MaxPlayers = 4 });

    }
    public override void OnCreatedRoom()
    {
        //방 생성에 성공 했을때 호출 되는 콜백
        UpdateStatusText($"방이 생성되었습니다.");
    }
    public override void OnJoinedRoom()
    {
        UpdateStatusText("방에 입장했습니다.");
        PhotonNetwork.LoadLevel("Main");
    }
}

LobbyMain.cs

+ Recent posts