-
-
Save StevenPhoton/65db542e7850a441bb14dd2fc05f1c2c to your computer and use it in GitHub Desktop.
VR Photon Tanks 完整程式參考
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using UnityEngine; | |
using UnityEngine.SceneManagement; | |
using UnityEngine.UI; | |
namespace Complete | |
{ | |
public class GameManager : MonoBehaviour | |
{ | |
public int m_NumRoundsToWin = 5; // The number of rounds a single player has to win to win the game. | |
public float m_StartDelay = 3f; // The delay between the start of RoundStarting and RoundPlaying phases. | |
public float m_EndDelay = 3f; // The delay between the end of RoundPlaying and RoundEnding phases. | |
public CameraControl m_CameraControl; // Reference to the CameraControl script for control during different phases. | |
public Text m_MessageText; // Reference to the overlay Text to display winning text, etc. | |
public GameObject m_TankPrefab; // Reference to the prefab the players will control. | |
public TankManager[] m_Tanks; // A collection of managers for enabling and disabling different aspects of the tanks. | |
private int m_RoundNumber; // Which round the game is currently on. | |
private WaitForSeconds m_StartWait; // Used to have a delay whilst the round starts. | |
private WaitForSeconds m_EndWait; // Used to have a delay whilst the round or game ends. | |
private TankManager m_RoundWinner; // Reference to the winner of the current round. Used to make an announcement of who won. | |
private TankManager m_GameWinner; // Reference to the winner of the game. Used to make an announcement of who won. | |
private void Start() | |
{ | |
// Create the delays so they only have to be made once. | |
m_StartWait = new WaitForSeconds (m_StartDelay); | |
m_EndWait = new WaitForSeconds (m_EndDelay); | |
if (!PhotonNetwork.inRoom) | |
return; | |
InitTanks(); | |
SetupGVRMode(); | |
if( ! PhotonNetwork.isMasterClient ) { | |
Invoke("EnterGameLoop", 3); | |
} | |
} | |
private void InitTanks() | |
{ | |
SpawnTank(); | |
} | |
private void SpawnTank() | |
{ | |
int ID = PhotonNetwork.player.ID; | |
Debug.Log( "player.ID : " + ID ); | |
GameObject tank = PhotonNetwork.Instantiate( | |
"CompleteTankPUN", | |
m_Tanks[ID].m_SpawnPoint.position, | |
m_Tanks[ID].m_SpawnPoint.rotation, | |
0 | |
) as GameObject; | |
m_Tanks[ID].m_Instance = tank; | |
m_Tanks[ID].m_PlayerNumber = ID; | |
m_Tanks[ID].Setup(); | |
Debug.Log("SpawnTank"); | |
} | |
private void SetupGVRMode() | |
{ | |
int ID = PhotonNetwork.player.ID; | |
GameObject goCamera = GameObject.FindGameObjectWithTag("MainCamera"); | |
if ((Application.platform == RuntimePlatform.IPhonePlayer) || ( Application.platform == RuntimePlatform.Android) ) { | |
goCamera.transform.SetParent( m_Tanks[ID].m_Instance.transform ); | |
goCamera.transform.localPosition = new Vector3( -0.307f, 3.204f, -6.168f); | |
goCamera.transform.localRotation = Quaternion.identity; | |
// GvrViewer gvrView = GameObject.Find("GvrViewerMain").GetComponent<GvrViewer>(); | |
// gvrView.VRModeEnabled = true; | |
} else { | |
goCamera.transform.parent = null; | |
goCamera.transform.position = new Vector3( -20.376f, 17f, -11.2f); | |
goCamera.transform.rotation = Quaternion.Euler( new Vector3(25f, 44f, 0f) ); | |
// GvrViewer gvrView = GameObject.Find("GvrViewerMain").GetComponent<GvrViewer>(); | |
// gvrView.VRModeEnabled = false; | |
} | |
} | |
public void EnterGameLoop() | |
{ | |
FindAllTanks(); | |
SetCameraTargets(); | |
// Once the tanks have been created and the camera is using them as targets, start the game. | |
StartCoroutine (GameLoop ()); | |
} | |
private void FindAllTanks() | |
{ | |
PhotonPlayer[] playerList = PhotonNetwork.playerList; | |
int players = playerList.Length; | |
GameObject[] tanks = GameObject.FindGameObjectsWithTag("Player"); | |
foreach( GameObject go in tanks) | |
{ | |
PhotonView view = go.GetComponent<PhotonView>(); | |
int ID = view.ownerId; | |
Debug.Log(" PhotonView ID: " + ID); | |
if ( m_Tanks[ID].m_Instance == null ) { | |
m_Tanks[ID].m_Instance = go; | |
m_Tanks[ID].m_PlayerNumber = view.ownerId; | |
m_Tanks[ID].Setup(); | |
} | |
} | |
} | |
private void SetCameraTargets() | |
{ | |
PhotonPlayer[] playerList = PhotonNetwork.playerList; | |
int players = playerList.Length; | |
// Create a collection of transforms the same size as the number of tanks. | |
// Transform[] targets = new Transform[m_Tanks.Length]; | |
Transform[] targets = new Transform[players]; | |
// For each of these transforms... | |
for (int i = 0; i < targets.Length; i++) | |
{ | |
// ... set it to the appropriate tank transform. | |
if ( m_Tanks[i].m_Instance != null ) { | |
targets[i] = m_Tanks[i].m_Instance.transform; | |
} | |
} | |
// These are the targets the camera should follow. | |
m_CameraControl.m_Targets = targets; | |
} | |
// This is called from start and will run each phase of the game one after another. | |
private IEnumerator GameLoop () | |
{ | |
// Start off by running the 'RoundStarting' coroutine but don't return until it's finished. | |
yield return StartCoroutine (RoundStarting ()); | |
// Once the 'RoundStarting' coroutine is finished, run the 'RoundPlaying' coroutine but don't return until it's finished. | |
yield return StartCoroutine (RoundPlaying()); | |
// Once execution has returned here, run the 'RoundEnding' coroutine, again don't return until it's finished. | |
yield return StartCoroutine (RoundEnding()); | |
// This code is not run until 'RoundEnding' has finished. At which point, check if a game winner has been found. | |
if (m_GameWinner != null) | |
{ | |
// If there is a game winner, restart the level. | |
SceneManager.LoadScene (0); | |
} | |
else | |
{ | |
// If there isn't a winner yet, restart this coroutine so the loop continues. | |
// Note that this coroutine doesn't yield. This means that the current version of the GameLoop will end. | |
StartCoroutine (GameLoop ()); | |
} | |
} | |
private IEnumerator RoundStarting () | |
{ | |
// As soon as the round starts reset the tanks and make sure they can't move. | |
ResetAllTanks (); | |
DisableTankControl (); | |
// Snap the camera's zoom and position to something appropriate for the reset tanks. | |
// m_CameraControl.SetStartPositionAndSize (); | |
// Increment the round number and display text showing the players what round it is. | |
m_RoundNumber++; | |
m_MessageText.text = "ROUND " + m_RoundNumber; | |
// Wait for the specified length of time until yielding control back to the game loop. | |
yield return m_StartWait; | |
} | |
private IEnumerator RoundPlaying () | |
{ | |
// As soon as the round begins playing let the players control the tanks. | |
EnableTankControl (); | |
// Clear the text from the screen. | |
m_MessageText.text = string.Empty; | |
// While there is not one tank left... | |
while (!OneTankLeft()) | |
{ | |
// ... return on the next frame. | |
yield return null; | |
} | |
} | |
private IEnumerator RoundEnding () | |
{ | |
// Stop tanks from moving. | |
DisableTankControl (); | |
// Clear the winner from the previous round. | |
m_RoundWinner = null; | |
// See if there is a winner now the round is over. | |
m_RoundWinner = GetRoundWinner (); | |
// If there is a winner, increment their score. | |
if (m_RoundWinner != null) | |
m_RoundWinner.m_Wins++; | |
// Now the winner's score has been incremented, see if someone has one the game. | |
m_GameWinner = GetGameWinner (); | |
// Get a message based on the scores and whether or not there is a game winner and display it. | |
string message = EndMessage (); | |
m_MessageText.text = message; | |
// Wait for the specified length of time until yielding control back to the game loop. | |
yield return m_EndWait; | |
} | |
// This is used to check if there is one or fewer tanks remaining and thus the round should end. | |
private bool OneTankLeft() | |
{ | |
// Start the count of tanks left at zero. | |
int numTanksLeft = 0; | |
// Go through all the tanks... | |
for (int i = 0; i < m_Tanks.Length; i++) | |
{ | |
// ... and if they are active, increment the counter. | |
if ( (m_Tanks[i].m_Instance ) && m_Tanks[i].m_Instance.activeSelf ) | |
numTanksLeft++; | |
} | |
// If there are one or fewer tanks remaining return true, otherwise return false. | |
return numTanksLeft <= 1; | |
} | |
// This function is to find out if there is a winner of the round. | |
// This function is called with the assumption that 1 or fewer tanks are currently active. | |
private TankManager GetRoundWinner() | |
{ | |
// Go through all the tanks... | |
for (int i = 0; i < m_Tanks.Length; i++) | |
{ | |
// ... and if one of them is active, it is the winner so return it. | |
if ( (m_Tanks[i].m_Instance != null) && (m_Tanks[i].m_Instance.activeSelf) ) | |
return m_Tanks[i]; | |
} | |
// If none of the tanks are active it is a draw so return null. | |
return null; | |
} | |
// This function is to find out if there is a winner of the game. | |
private TankManager GetGameWinner() | |
{ | |
// Go through all the tanks... | |
for (int i = 0; i < m_Tanks.Length; i++) | |
{ | |
// ... and if one of them has enough rounds to win the game, return it. | |
if ( (m_Tanks[i].m_Instance != null) && (m_Tanks[i].m_Wins == m_NumRoundsToWin)) | |
return m_Tanks[i]; | |
} | |
// If no tanks have enough rounds to win, return null. | |
return null; | |
} | |
// Returns a string message to display at the end of each round. | |
private string EndMessage() | |
{ | |
// By default when a round ends there are no winners so the default end message is a draw. | |
string message = "DRAW!"; | |
// If there is a winner then change the message to reflect that. | |
if (m_RoundWinner != null) | |
message = m_RoundWinner.m_ColoredPlayerText + " WINS THE ROUND!"; | |
// Add some line breaks after the initial message. | |
message += "\n\n\n\n"; | |
// Go through all the tanks and add each of their scores to the message. | |
for (int i = 0; i < m_Tanks.Length; i++) | |
{ | |
message += m_Tanks[i].m_ColoredPlayerText + ": " + m_Tanks[i].m_Wins + " WINS\n"; | |
} | |
// If there is a game winner, change the entire message to reflect that. | |
if (m_GameWinner != null) | |
message = m_GameWinner.m_ColoredPlayerText + " WINS THE GAME!"; | |
return message; | |
} | |
// This function is used to turn all the tanks back on and reset their positions and properties. | |
private void ResetAllTanks() | |
{ | |
for (int i = 0; i < m_Tanks.Length; i++) | |
{ | |
if( m_Tanks[i].m_Instance != null ) { | |
m_Tanks[i].Reset(); | |
} | |
} | |
} | |
private void EnableTankControl() | |
{ | |
for (int i = 0; i < m_Tanks.Length; i++) | |
{ | |
if( m_Tanks[i].m_Instance != null ) { | |
m_Tanks[i].EnableControl(); | |
} | |
} | |
} | |
private void DisableTankControl() | |
{ | |
for (int i = 0; i < m_Tanks.Length; i++) | |
{ | |
if( m_Tanks[i].m_Instance != null ) { | |
m_Tanks[i].DisableControl(); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment