first commit
This commit is contained in:
87
Assets/Scripts/GameManager.cs
Normal file
87
Assets/Scripts/GameManager.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
using Photon.Pun;
|
||||
using Photon.Realtime;
|
||||
|
||||
namespace cc.ivanli.pun01
|
||||
{
|
||||
public class GameManager : MonoBehaviourPunCallbacks
|
||||
{
|
||||
public static GameManager Instance;
|
||||
|
||||
[Tooltip("The prefab to use for representing the player")]
|
||||
public GameObject playerPrefab;
|
||||
|
||||
[System.Obsolete]
|
||||
void Start()
|
||||
{
|
||||
Instance = this;
|
||||
|
||||
if (!playerPrefab)
|
||||
{
|
||||
Debug.LogError("<Color=Red><a>Missing</a></Color> playerPrefab Reference. Please set it up in GameObject 'Game Manager'", this);
|
||||
}
|
||||
else if (!PlayerManager.LocalPlayerInstance)
|
||||
{
|
||||
Debug.LogFormat("We are Instantiating LocalPlayer from {0}", Application.loadedLevelName);
|
||||
// we're in a room. spawn a character for the local player. it gets synced by using PhotonNetwork.Instantiate
|
||||
PhotonNetwork.Instantiate(this.playerPrefab.name, new Vector3(0f, 5f, 0f), Quaternion.identity, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogFormat("Ignoring scene load for {0}", SceneManagerHelper.ActiveSceneName);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnLeftRoom()
|
||||
{
|
||||
base.OnLeftRoom();
|
||||
SceneManager.LoadScene(0);
|
||||
}
|
||||
|
||||
public void LeaveRoom()
|
||||
{
|
||||
PhotonNetwork.LeaveRoom();
|
||||
}
|
||||
|
||||
public void LoadArena()
|
||||
{
|
||||
if (!PhotonNetwork.IsMasterClient)
|
||||
{
|
||||
Debug.LogError("PhotonNetwork : Trying to Load a level but we are not the master Client");
|
||||
}
|
||||
Debug.LogFormat("PhotonNetwork : Loading Level : {0}", PhotonNetwork.CurrentRoom.PlayerCount);
|
||||
PhotonNetwork.LoadLevel("Room for " + PhotonNetwork.CurrentRoom.PlayerCount);
|
||||
}
|
||||
|
||||
public override void OnPlayerEnteredRoom(Player other)
|
||||
{
|
||||
Debug.LogFormat("OnPlayerEnteredRoom() {0}", other.NickName); // not seen if you're the player connecting
|
||||
|
||||
|
||||
if (PhotonNetwork.IsMasterClient)
|
||||
{
|
||||
Debug.LogFormat("OnPlayerEnteredRoom IsMasterClient {0}", PhotonNetwork.IsMasterClient); // called before OnPlayerLeftRoom
|
||||
|
||||
|
||||
LoadArena();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void OnPlayerLeftRoom(Player other)
|
||||
{
|
||||
Debug.LogFormat("OnPlayerLeftRoom() {0}", other.NickName); // seen when other disconnects
|
||||
|
||||
|
||||
if (PhotonNetwork.IsMasterClient)
|
||||
{
|
||||
Debug.LogFormat("OnPlayerLeftRoom IsMasterClient {0}", PhotonNetwork.IsMasterClient); // called before OnPlayerLeftRoom
|
||||
|
||||
|
||||
LoadArena();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/GameManager.cs.meta
Normal file
11
Assets/Scripts/GameManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03cf4f63c046f44df845e85c35f39e32
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
104
Assets/Scripts/Launcher.cs
Normal file
104
Assets/Scripts/Launcher.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using Photon.Pun;
|
||||
using Photon.Realtime;
|
||||
using UnityEngine;
|
||||
|
||||
namespace cc.ivanli.pun01
|
||||
{
|
||||
public class Launcher : MonoBehaviourPunCallbacks
|
||||
{
|
||||
/// <summary>
|
||||
/// Client's version
|
||||
/// </summary>
|
||||
private readonly string gameVersion = "1";
|
||||
|
||||
[Tooltip("The maximum number of players per room. When a room is full, it can't be joined by new players, and so new room will be created")]
|
||||
[SerializeField]
|
||||
private byte maxPlayersPerRoom = 4;
|
||||
|
||||
[Tooltip("The Ui Panel to let the user enter name, connect and play")]
|
||||
[SerializeField]
|
||||
private GameObject controlPanel;
|
||||
|
||||
[Tooltip("The UI Label to inform the user that the connection is in progress")]
|
||||
[SerializeField]
|
||||
private GameObject progressLabel;
|
||||
|
||||
bool isConnecting;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
PhotonNetwork.AutomaticallySyncScene = true;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
progressLabel.SetActive(false);
|
||||
controlPanel.SetActive(true);
|
||||
}
|
||||
|
||||
public void Connect()
|
||||
{
|
||||
progressLabel.SetActive(true);
|
||||
controlPanel.SetActive(false);
|
||||
if (PhotonNetwork.IsConnected)
|
||||
{
|
||||
PhotonNetwork.JoinRandomRoom();
|
||||
}
|
||||
else
|
||||
{
|
||||
isConnecting = PhotonNetwork.ConnectUsingSettings();
|
||||
PhotonNetwork.GameVersion = gameVersion;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnConnectedToMaster()
|
||||
{
|
||||
Debug.Log("PUN Basics Launcher:OnConnectedToMaster() was called by PUN");
|
||||
base.OnConnectedToMaster();
|
||||
if (isConnecting)
|
||||
{
|
||||
// #Critical: The first we try to do is to join a potential existing room. If there is, good, else, we'll be called back with OnJoinRandomFailed()
|
||||
PhotonNetwork.JoinRandomRoom();
|
||||
isConnecting = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDisconnected(DisconnectCause cause)
|
||||
{
|
||||
progressLabel.SetActive(false);
|
||||
controlPanel.SetActive(true);
|
||||
isConnecting = false;
|
||||
|
||||
Debug.LogWarningFormat("PUN basics Launcher:OnDisconnected() was called by PUN with reason {0}", cause);
|
||||
base.OnDisconnected(cause);
|
||||
}
|
||||
|
||||
public override void OnJoinRandomFailed(short returnCode, string message)
|
||||
{
|
||||
Debug.Log("PUN BasicsLauncher:OnJoinRandomFailed() was called by PUN. No random room available, so we create one.\nCalling: PhotonNetwork.CreateRoom()");
|
||||
base.OnJoinRandomFailed(returnCode, message);
|
||||
|
||||
PhotonNetwork.CreateRoom(null, new RoomOptions
|
||||
{
|
||||
MaxPlayers = maxPlayersPerRoom
|
||||
});
|
||||
}
|
||||
|
||||
public override void OnJoinedRoom()
|
||||
{
|
||||
Debug.Log("PUN Basics Launcher:OnJoinedRoom() called by PUN. Now this client is in a room.");
|
||||
base.OnJoinedRoom();
|
||||
|
||||
// #Critical: We only load if we are the first player, else we rely on `PhotonNetwork.AutomaticallySyncScene` to sync our instance scene.
|
||||
if (PhotonNetwork.CurrentRoom.PlayerCount == 1)
|
||||
{
|
||||
Debug.Log("We load the 'Room for 1' ");
|
||||
|
||||
|
||||
// #Critical
|
||||
// Load the Room Level.
|
||||
PhotonNetwork.LoadLevel("Room for 1");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/Launcher.cs.meta
Normal file
11
Assets/Scripts/Launcher.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 66646a4c5f9e14677a41bb258a59f7f5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
54
Assets/Scripts/PlayerAnimatorManager.cs
Normal file
54
Assets/Scripts/PlayerAnimatorManager.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using Photon.Pun;
|
||||
using UnityEngine;
|
||||
|
||||
namespace cc.ivanli.pun01
|
||||
{
|
||||
public class PlayerAnimatorManager : MonoBehaviourPun
|
||||
{
|
||||
private Animator animator;
|
||||
|
||||
[SerializeField]
|
||||
private float directionDampTime = 0.25f;
|
||||
|
||||
|
||||
void Start()
|
||||
{
|
||||
animator = GetComponent<Animator>();
|
||||
if (!animator)
|
||||
{
|
||||
Debug.LogError("PlayerAnimatorManager is Missing Animator Component", this);
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (!animator)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (photonView.IsMine == false && PhotonNetwork.IsConnected == true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var stateInfo = animator.GetCurrentAnimatorStateInfo(0);
|
||||
|
||||
if (stateInfo.IsName("Base Layer.Run")) {
|
||||
if (Input.GetButtonDown("Fire2")) {
|
||||
animator.SetTrigger("Jump");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var h = Input.GetAxis("Horizontal");
|
||||
var v = Input.GetAxis("Vertical");
|
||||
|
||||
if (v < 0)
|
||||
{
|
||||
v = 0;
|
||||
}
|
||||
animator.SetFloat("Speed", h * h + v * v);
|
||||
animator.SetFloat("Direction", h, directionDampTime, Time.deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/PlayerAnimatorManager.cs.meta
Normal file
11
Assets/Scripts/PlayerAnimatorManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a45f03bc523624ba281eecfad7f6d82f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
181
Assets/Scripts/PlayerManager.cs
Normal file
181
Assets/Scripts/PlayerManager.cs
Normal file
@@ -0,0 +1,181 @@
|
||||
using Photon.Pun;
|
||||
using Photon.Pun.Demo.PunBasics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace cc.ivanli.pun01
|
||||
{
|
||||
public class PlayerManager : MonoBehaviourPunCallbacks, IPunObservable
|
||||
{
|
||||
[Tooltip("The Beams GameObject to control")]
|
||||
[SerializeField]
|
||||
private GameObject beams;
|
||||
//True, when the user is firing
|
||||
private bool IsFiring;
|
||||
|
||||
[Tooltip("The current Health of our player")]
|
||||
public float Health = 1f;
|
||||
|
||||
[Tooltip("The local player instance. Use this to know if the local player is represented in the Scene")]
|
||||
public static GameObject LocalPlayerInstance;
|
||||
|
||||
[Tooltip("The Player's UI GameObject Prefab")]
|
||||
[SerializeField]
|
||||
public GameObject PlayerUiPrefab;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (beams == null)
|
||||
{
|
||||
Debug.LogError("<Color=Red><a>Missing</a></Color> Beams Reference.", this);
|
||||
}
|
||||
else
|
||||
{
|
||||
beams.SetActive(false);
|
||||
}
|
||||
|
||||
if (photonView.IsMine)
|
||||
{
|
||||
PlayerManager.LocalPlayerInstance = this.gameObject;
|
||||
}
|
||||
DontDestroyOnLoad(this.gameObject);
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
CameraWork _cameraWork = this.gameObject.GetComponent<CameraWork>();
|
||||
UnityEngine.SceneManagement.SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
|
||||
|
||||
if (_cameraWork != null)
|
||||
{
|
||||
if (photonView.IsMine)
|
||||
{
|
||||
_cameraWork.OnStartFollowing();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("<Color=Red><a>Missing</a></Color> CameraWork Component on playerPrefab.", this);
|
||||
}
|
||||
|
||||
if (PlayerUiPrefab != null)
|
||||
{
|
||||
GameObject _uiGo = Instantiate(PlayerUiPrefab);
|
||||
_uiGo.SendMessage("SetTarget", this, SendMessageOptions.RequireReceiver);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("<Color=Red><a>Missing</a></Color> PlayerUiPrefab reference on player Prefab.", this);
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
|
||||
if (photonView.IsMine)
|
||||
{
|
||||
ProcessInputs();
|
||||
if (Health <= 0f)
|
||||
{
|
||||
GameManager.Instance.LeaveRoom();
|
||||
}
|
||||
}
|
||||
|
||||
// trigger Beams active state
|
||||
if (beams != null && IsFiring != beams.activeInHierarchy)
|
||||
{
|
||||
beams.SetActive(IsFiring);
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessInputs()
|
||||
{
|
||||
if (Input.GetButtonDown("Fire1"))
|
||||
{
|
||||
if (!IsFiring)
|
||||
{
|
||||
IsFiring = true;
|
||||
}
|
||||
}
|
||||
if (Input.GetButtonUp("Fire1"))
|
||||
{
|
||||
if (IsFiring)
|
||||
{
|
||||
IsFiring = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (!photonView.IsMine)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// We are only interested in Beamers
|
||||
// we should be using tags but for the sake of distribution, let's simply check by name.
|
||||
if (!other.name.Contains("Beam"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Health -= 0.1f;
|
||||
}
|
||||
|
||||
void OnTriggerStay(Collider other)
|
||||
{
|
||||
// we dont' do anything if we are not the local player.
|
||||
if (!photonView.IsMine)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// We are only interested in Beamers
|
||||
// we should be using tags but for the sake of distribution, let's simply check by name.
|
||||
if (!other.name.Contains("Beam"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// we slowly affect health when beam is constantly hitting us, so player has to move to prevent death.
|
||||
Health -= 0.1f * Time.deltaTime;
|
||||
}
|
||||
|
||||
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
|
||||
{
|
||||
if (stream.IsWriting)
|
||||
{
|
||||
// We own this player: send the others our data
|
||||
stream.SendNext(IsFiring);
|
||||
stream.SendNext(Health);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Network player, receive data
|
||||
IsFiring = (bool)stream.ReceiveNext();
|
||||
Health = (float)stream.ReceiveNext();
|
||||
}
|
||||
}
|
||||
void OnSceneLoaded(UnityEngine.SceneManagement.Scene scene, UnityEngine.SceneManagement.LoadSceneMode loadingMode)
|
||||
{
|
||||
this.CalledOnLevelWasLoaded(scene.buildIndex);
|
||||
}
|
||||
void OnLevelWasLoaded(int level)
|
||||
{
|
||||
this.CalledOnLevelWasLoaded(level);
|
||||
}
|
||||
void CalledOnLevelWasLoaded(int level)
|
||||
{
|
||||
// check if we are outside the Arena and if it's the case, spawn around the center of the arena in a safe zone
|
||||
if (!Physics.Raycast(transform.position, -Vector3.up, 5f))
|
||||
{
|
||||
transform.position = new Vector3(0f, 5f, 0f);
|
||||
}
|
||||
GameObject _uiGo = Instantiate(PlayerUiPrefab);
|
||||
_uiGo.SendMessage("SetTarget", this, SendMessageOptions.RequireReceiver);
|
||||
}
|
||||
public override void OnDisable()
|
||||
{
|
||||
// Always call the base to remove callbacks
|
||||
base.OnDisable();
|
||||
UnityEngine.SceneManagement.SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/PlayerManager.cs.meta
Normal file
11
Assets/Scripts/PlayerManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91e81c63f27d24248bb2306e958fa2c8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
41
Assets/Scripts/PlayerNameInputField.cs
Normal file
41
Assets/Scripts/PlayerNameInputField.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using Photon.Pun;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace cc.ivanli.pun01
|
||||
{
|
||||
[RequireComponent(typeof(TMP_InputField))]
|
||||
public class PlayerNameInputField : MonoBehaviour
|
||||
{
|
||||
private const string playerNamePrefKey = "PlayerName";
|
||||
|
||||
public void Start()
|
||||
{
|
||||
|
||||
string defaultName = string.Empty;
|
||||
TMP_InputField inputField = GetComponent<TMP_InputField>();
|
||||
if (inputField != null)
|
||||
{
|
||||
if (PlayerPrefs.HasKey(playerNamePrefKey))
|
||||
{
|
||||
defaultName = PlayerPrefs.GetString(playerNamePrefKey);
|
||||
inputField.text = defaultName;
|
||||
}
|
||||
}
|
||||
|
||||
PhotonNetwork.NickName = defaultName;
|
||||
}
|
||||
public void SetPlayerName(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
Debug.LogError("Player Name is not null or empty");
|
||||
return;
|
||||
}
|
||||
PhotonNetwork.NickName = value;
|
||||
|
||||
PlayerPrefs.SetString(playerNamePrefKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
11
Assets/Scripts/PlayerNameInputField.cs.meta
Normal file
11
Assets/Scripts/PlayerNameInputField.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e6dad244d51e446bb7f0ca38406fbb7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
53
Assets/Scripts/PlayerUI.cs
Normal file
53
Assets/Scripts/PlayerUI.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace cc.ivanli.pun01
|
||||
{
|
||||
public class PlayerUI : MonoBehaviour
|
||||
{
|
||||
[Tooltip("UI Text to display Player's Name")]
|
||||
[SerializeField]
|
||||
private TMP_Text playerNameText;
|
||||
|
||||
|
||||
[Tooltip("UI Slider to display Player's Health")]
|
||||
[SerializeField]
|
||||
private Slider playerHealthSlider;
|
||||
|
||||
private PlayerManager target;
|
||||
|
||||
public void SetTarget(PlayerManager _target)
|
||||
{
|
||||
if (_target == null)
|
||||
{
|
||||
Debug.LogError("<Color=Red><a>Missing</a></Color> PlayMakerManager target for PlayerUI.SetTarget.", this);
|
||||
return;
|
||||
}
|
||||
// Cache references for efficiency
|
||||
target = _target;
|
||||
if (playerNameText != null)
|
||||
{
|
||||
playerNameText.text = target.photonView.Owner.NickName;
|
||||
}
|
||||
}
|
||||
void Awake()
|
||||
{
|
||||
this.transform.SetParent(GameObject.Find("Canvas").GetComponent<Transform>(), false);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
// Reflect the Player Health
|
||||
if (playerHealthSlider != null)
|
||||
{
|
||||
playerHealthSlider.value = target.Health;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/PlayerUI.cs.meta
Normal file
11
Assets/Scripts/PlayerUI.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 27c3bc70114064f9bbf8b4598034448f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user