プレイグランドを改造する
Improvement Playground
今回はUNITYの練習用アセットPlaygroundの改良をしてみましょう。今回は時間制限機能をつけてみましょう。
LEVEL
開発環境
UNITY (2D)

対応デバイス:PC
方向変更:WADS
レーザー発射:スペース
プレイグランドに時間制限機能をつける
プレイグランドは、色々なアセットで簡単な操作でゲームを作れるようになっていますが、通常のUnityプロジェクトと同じように色々なオリジナル機能を追加することができます。今回は、時間制限の機能をつけてみましょう。
編集しよう
変更箇所
【プレファブ】Prefabs
・Userinterface
【スクリプト】Scripts
・UIScript
・UIScriptInspector
プレファブの変更
Userinterfaceプレファブを編集していきます。「Time Up」を表示するためのPanel(パネル)をつくります。

ゲームオブジェクト「TimeUp」の設定

UI TEXT「TimeUpText」の設定

スクリプトの変更
UIScript.cs
時間を計測するための各種変数を定義して、Update()メソッドを追加して、そのなかで時間を計測させています。
変更箇所は「改良のための追加..」を書かれています。
using UnityEngine; | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine.UI; | |
[AddComponentMenu("")] | |
public class UIScript : MonoBehaviour | |
{ | |
[Header("Configuration")] | |
public Players numberOfPlayers = Players.OnePlayer; | |
public GameType gameType = GameType.Score; | |
// If the scoreToWin is -1, the game becomes endless (no win conditions, but you could do game over) | |
public int scoreToWin = 5; | |
public int gameTime = 30; | |
//改良のための追加1 START | |
public Text timeText;//時間表示Textエリア | |
public GameObject timeUpPanel;//タイムアップ用Window | |
public Text timeUpText;//タイムアップ用Windowの表示Text | |
private bool onetime = true; | |
//改良のための追加1 END | |
[Header("References (don't touch)")] | |
//Right is used for the score in P1 games | |
public Text[] numberLabels = new Text[2]; | |
public Text rightLabel, leftLabel; | |
public Text winLabel; | |
public GameObject statsPanel, gameOverPanel, winPanel; | |
public Transform inventory; | |
public GameObject resourceItemPrefab; | |
// Internal variables to keep track of score, health, and resources, win state | |
private int[] scores = new int[2]; | |
private int[] playersHealth = new int[2]; | |
private Dictionary<int, ResourceStruct> resourcesDict = new Dictionary<int, ResourceStruct>(); //holds a reference to all the resources collected, and to their UI | |
private bool gameOver = false; //this gets changed when the game is won OR lost | |
private void Start() | |
{ | |
if(numberOfPlayers == Players.OnePlayer) | |
{ | |
// No setup needed | |
} | |
else | |
{ | |
if(gameType == GameType.Score) | |
{ | |
// Show the 2-player score interface | |
rightLabel.text = leftLabel.text = "Score"; | |
// Show the score as 0 for both players | |
numberLabels[0].text = numberLabels[1].text = numberLabels[2].text = "0"; | |
scores[0] = scores[1] = 0; | |
} | |
else | |
{ | |
// Show the 2-player life interface | |
rightLabel.text = leftLabel.text = "Life"; | |
// Life will be provided by the PlayerHealth components | |
} | |
} | |
} | |
/* | |
* 改良のための追加2 START | |
* Add Time Rule | |
*/ | |
private void Update() | |
{ | |
if (gameTime > 0) | |
{ | |
//Debug.Log("経過時間" + Time.time); | |
int timeInt = gameTime - (int)Time.time; | |
timeText.text = timeInt.ToString(); | |
if (0 == timeInt) | |
{ | |
TimeUp(); | |
} | |
} | |
else if (gameTime == 0) | |
{ | |
int timeInt = (int)Time.time; | |
timeText.text = timeInt.ToString(); | |
} | |
} | |
//改良のための追加2 END | |
//version of the one below with one parameter to be able to connect UnityEvents | |
public void AddOnePoint(int playerNumber) | |
{ | |
AddPoints(playerNumber, 1); | |
} | |
public void AddPoints(int playerNumber, int amount = 1) | |
{ | |
scores[playerNumber] += amount; | |
if(numberOfPlayers == Players.OnePlayer) | |
{ | |
numberLabels[1].text = scores[playerNumber].ToString(); //with one player, the score is on the right | |
} | |
else | |
{ | |
numberLabels[playerNumber].text = scores[playerNumber].ToString(); | |
} | |
if(gameType == GameType.Score | |
&& scores[playerNumber] >= scoreToWin) | |
{ | |
GameWon(playerNumber); | |
} | |
} | |
//currently unused by other Playground scripts | |
public void RemoveOnePoint(int playerNumber) | |
{ | |
scores[playerNumber]--; | |
if(numberOfPlayers == Players.OnePlayer) | |
{ | |
numberLabels[1].text = scores[playerNumber].ToString(); //with one player, the score is on the right | |
} | |
else | |
{ | |
numberLabels[playerNumber].text = scores[playerNumber].ToString(); | |
} | |
} | |
public void GameWon(int playerNumber) | |
{ | |
// only set game over UI if game is not over | |
if (!gameOver) | |
{ | |
gameOver = true; | |
winLabel.text = "Player " + ++playerNumber + " wins!"; | |
statsPanel.SetActive(false); | |
winPanel.SetActive(true); | |
} | |
} | |
public void GameOver(int playerNumber) | |
{ | |
// only set game over UI if game is not over | |
if (!gameOver) | |
{ | |
gameOver = true; | |
statsPanel.SetActive(false); | |
gameOverPanel.SetActive(true); | |
} | |
} | |
//改良のための追加3 START | |
// タイムズ・アップ | |
public void TimeUp() | |
{ | |
if (onetime) | |
{ | |
timeUpText.text = "Time UP! Score=" + scores[0].ToString(); | |
onetime = false; | |
} | |
statsPanel.SetActive(false); | |
timeUpPanel.SetActive(true); | |
} | |
//改良のための追加3 END | |
public void SetHealth(int amount, int playerNumber) | |
{ | |
playersHealth[playerNumber] = amount; | |
numberLabels[playerNumber].text = playersHealth[playerNumber].ToString(); | |
} | |
public void ChangeHealth(int change, int playerNumber) | |
{ | |
SetHealth(playersHealth[playerNumber] + change, playerNumber); | |
if(gameType != GameType.Endless | |
&& playersHealth[playerNumber] <= 0) | |
{ | |
GameOver(playerNumber); | |
} | |
} | |
//Adds a resource to the dictionary, and to the UI | |
public void AddResource(int resourceType, int pickedUpAmount, Sprite graphics) | |
{ | |
if(resourcesDict.ContainsKey(resourceType)) | |
{ | |
//update the dictionary key | |
int newAmount = resourcesDict[resourceType].amount + pickedUpAmount; | |
resourcesDict[resourceType].UIItem.ShowNumber(newAmount); | |
resourcesDict[resourceType].amount = newAmount; | |
} | |
else | |
{ | |
//create the UIItemScript and display the icon | |
UIItemScript newUIItem = Instantiate<GameObject>(resourceItemPrefab).GetComponent<UIItemScript>(); | |
newUIItem.transform.SetParent(inventory, false); | |
resourcesDict.Add(resourceType, new ResourceStruct(pickedUpAmount, newUIItem)); | |
resourcesDict[resourceType].UIItem.ShowNumber(pickedUpAmount); | |
resourcesDict[resourceType].UIItem.DisplayIcon(graphics); | |
} | |
} | |
//checks if a certain resource is in the inventory, in the needed quantity | |
public bool CheckIfHasResources(int resourceType, int amountNeeded = 1) | |
{ | |
if(resourcesDict.ContainsKey(resourceType)) | |
{ | |
if(resourcesDict[resourceType].amount >= amountNeeded) | |
{ | |
return true; | |
} | |
else | |
{ | |
//not enough | |
return false; | |
} | |
} | |
else | |
{ | |
//resource not present | |
return false; | |
} | |
} | |
//to use only before checking that the resource is in the dictionary | |
public void ConsumeResource(int resourceType, int amountNeeded = 1) | |
{ | |
resourcesDict[resourceType].amount -= amountNeeded; | |
resourcesDict[resourceType].UIItem.ShowNumber(resourcesDict[resourceType].amount); | |
} | |
public enum Players | |
{ | |
OnePlayer = 0, | |
TwoPlayers | |
} | |
public enum GameType | |
{ | |
Score = 0, | |
Life, | |
Endless, | |
Time | |
} | |
} | |
//just a virtual representation of the resources for the private dictionary | |
public class ResourceStruct | |
{ | |
public int amount; | |
public UIItemScript UIItem; | |
public ResourceStruct(int a, UIItemScript uiRef) | |
{ | |
amount = a; | |
UIItem = uiRef; | |
} | |
} |
UIScriptInspector.cs
このスクリプトは、UIScriptのインスペクターの表示を編集するためのスクリプトです。ですから、このスクリプトにUIScriptインスペクタで今回追加した変数をインスペクタに表示するコードを追加します。変更箇所は「改良のための追加..」を書かれています。
using UnityEngine; | |
using UnityEditor; | |
using System.Collections; | |
[CustomEditor(typeof(UIScript))] | |
public class UIScriptInspector : InspectorBase | |
{ | |
private string explanation = "Use the UI to visualise points and health for the players."; | |
private string lifeReminder = "Don't forget to use the script HealthSystemAttribute on the player(s)!"; | |
private int nOfPlayers = 0, gameType = 0; | |
private string[] readablePlayerEnum = new string[]{"One player", "Two players"}; | |
private string[] readableGameTypesEnum = new string[]{"Score", "Life", "Endless"}; | |
// Inspector GUI OnInspcetorGUIをオーバライドしてカスタマイズ | |
public override void OnInspectorGUI() | |
{ | |
GUILayout.Space(10); | |
EditorGUILayout.HelpBox(explanation, MessageType.Info); | |
nOfPlayers = serializedObject.FindProperty("numberOfPlayers").intValue; | |
gameType = serializedObject.FindProperty("gameType").intValue; | |
nOfPlayers = EditorGUILayout.Popup("Number of players", nOfPlayers, readablePlayerEnum); | |
gameType = EditorGUILayout.Popup("Game type", gameType, readableGameTypesEnum); | |
// GameTypeにより表示をScoreToWinを表示・非表示を切り替える | |
if (gameType == 0) //score game | |
{ | |
EditorGUILayout.PropertyField(serializedObject.FindProperty("scoreToWin")); | |
} | |
if(gameType == 1) //life | |
{ | |
EditorGUILayout.HelpBox(lifeReminder, MessageType.Info); | |
} | |
// 改良のための追加 START | |
EditorGUILayout.PropertyField(serializedObject.FindProperty("gameTime")); | |
EditorGUILayout.PropertyField(serializedObject.FindProperty("timeText")); | |
EditorGUILayout.PropertyField(serializedObject.FindProperty("timeUpPanel")); | |
EditorGUILayout.PropertyField(serializedObject.FindProperty("timeUpText")); | |
// 改良のための追加 END | |
//write all the properties back | |
serializedObject.FindProperty("gameType").intValue = gameType; | |
serializedObject.FindProperty("numberOfPlayers").intValue = nOfPlayers; | |
//serializedObject.FindProperty("gameTime").intValue = gameTime; | |
if (GUI.changed) | |
{ | |
serializedObject.ApplyModifiedProperties(); | |
} | |
} | |
} |
コードを書くとUserInterfaceのインスペクタに以下のように変数が追加されますので、該当のGameObjectをアタッチしてください。Game Time変数に0を入力するとカウントアップしていきます。また、0より大きな数字をいれるとカウントダウンして、0になると「タイムアップ」と表示されうます。

これで改良のおわりです。下のように時間表示は追加されるとおもいます。
