Udemy学習記録 Unity2D脱出ゲーム開発入門(2日目)
えにあです。
島津さんUnity2D脱出ゲーム開発入門をやっていきます。 前回はNo38をやったので、No39、No40を進めていきます。
今回のゴール
前回作成した矢印ボタンを押したら、画面が切り替わるようにする。
パネルをまとめる
CreateEmptyでCanvasの下にPanelParentを作成する。 前回作成したPanel0~3をすべて下に移動。
親パネルは現在画面に映っている枠を表している。 枠の位置を変えていくことで、画面表示を切り替える作戦のようだ。
Canvasの下にPanelParentとArrowsが存在する状況だが、PanelParentを上に持ってくること。 後々なにか影響があるらしい。ドラッグアンドドロップで移動できる。
GameViewにして、PanelParentのX座標、Y座標をいじってみよう。 画面が動いていくのがわかる。
Scriptを作る
プログラムから画面移動できるようにしていこう
Assetsフォルダの下にScriptsフォルダを作成する。 PanelChangerという名前でスクリプトを作成。 作成したスクリプトをPanelParentのインスペクターにドラッグアンドドロップ。 これで関連付けがされる。
スクリプトの中身はこんな感じ。
public void OnRightArrow() { transform.localPosition = new Vector2(-1000, 0); }
Arrowに関数を紐づける
3つのArrowを全部選択。Add ComponentでButton。 これでArrowにボタン機能が備わる。
OnClickのオブジェクトにPanelParent、ファンクションにPanelChangerのOnRightArrowを選択。
同様に左もやる。
今日のポイント
・OnClickへの関連付けは、スクリプトがアタッチされているオブジェクト、スクリプトのファンクションの順番で張り付ける。直感的にはスクリプトを直接呼出しそうなものだが、なぜオブジェクトを介するのだろう。謎。
・ローカル座標とワールド座標。localPositionをいじっているのは、Canvasの下の座標系で移動させるため。使い分けは今後勉強しないといけない。
Udemy学習記録 Unity2D脱出ゲーム開発入門(1日目)
えにえあです。
島津さんUnity2D脱出ゲーム開発入門をやっていきます。 No36まではセットアップとC#基礎なので、 No37~はじめていきます。
ビルドセッティング
File => Build Setting Androidを選択して、Select Platformを押す
画面サイズの変更
GameViewで、アスペクトを1280×720 portraitにする。
パネルの追加
シーンビューで右クリック ->UI -> Panel追加
Canvasが自動的に追加になる。
Canvasを選択してInspectorでRenderMode -> 「Screen Space - Camera」に変更する。 Render CameraにヒエラルキーのMain Cameraをドラッグアンドドロップする。
サブパネルを作る
パネルを選択して右クリック => UI => パネル。 Backgroundに名前をかえる。
Backgroundを選択して、Inspectorを操作 ・Rect Transformで中心にする。 ・そして、背景画像を張り付ける ・縦に画像が伸びている場合はSet Native Sizeを押下する。 ・画像を張り付けた時に色が薄いので、colorのアルファを255に。
注意: 画像サイズが動画と異なっています。 Projectで画像を選択して、InspectorでPixels Per Unitを138に変更すれば動画の内容と合うようです。
親パネルの画像を消す
Backgroundに画像を設定したときに、親パネルにも背景画像が設定されてしまっている。 親パネルの画像はいらないので、ImageコンポーネントをRemove Componentする。
パネルをコピー
Panelを3つコピーして、それぞれに画像を張り付ける。
注意: 解説動画とファイル名が違います。 ファイル名ではなく、画像の中身を見て張り付けると良いです。
矢印を追加
Canvasを選択して、右クリック UI => Imageを追加 LeftArrowに名前を変えて、矢印の画像を張り付け ここでもサイズがおかしいので注意
コピーしてRightArrowを追加。Scaleのxを-1にすることで、向きを反転させる。
矢印をまとめるために、Canvasを選択して右クリック CreateEmpty。 名前をArrowsにする。 作成したArrowsの下にLeftArrow、RightArrowを移動させる。
LeftArrowをコピーしてDownArrowを追加 矢印を下に向けるには、Z軸方向のRotateionを90にすればよい。
今日のポイント
・空のオブジェクトを使って、オブジェクトをまとめることができる
・Z軸方向のRotationを使って画像を下に向ける
・X軸方向のスケールを-1にすることで左右を逆にできる
Unity操作方法メモ
えにあです
仕事が忙しくなってずいぶんさぼってしまいました。 またUnityを頑張ろうと思いますが、完全に忘れてしまったので操作方法から思い出し中です。
この記事はメモなので多分けします。
シーンビュー
Handツール
左ドラッグでカメラの移動 Alt + 左ドラッグで回転
Moveツール
物体の移動に使う Inspectorで左クリックでも位置移動できる。
ライティング
画面が暗いとき => Window => Rendering -> Lighting -> Auto generate LightingをOnにする。
フォントファイルをダウンロードしたらttfとotfの2つ入っていた話
えにあです。
ボードゲームを作成するにあたり、タイトル画面を作ろうとしています。 ゲームタイトルをデフォルトフォントのArialで描いたのでは味気ないですよね。
そこで、フリーのフォントを探していたところ、Phenomenaフォントが気に入りました! www.fontfabric.com
このサイトからフォントをダウンロードしたところ、.ttfと.otfの二つのファイルが含まれていました。 私はどちらを使えばよいのでしょう、というのが今回の話です。
.ttfと.otf
ttfはTrue Type Fontの略で、otfはOpen Type Fontの略です。
TrueTypeFontとOpernTypeFontの違いは下記のサイトに詳しく載っています。 fontnavi.jp
Unity自体はttfとotfのどちらもサポートしています。 タイトル文字に使うだけなれば、正直どちらでも問題ないと思われます。 私はttfファイルのほうを利用しました。
フォントのインポート
ttfファイルそのままではUnityで使うことができず、フォントをUnityのアセットに変換してあげる必要があります。
トップメニューから「Window」->「TextMeshPro」->「FontAssetCreator」を選択します。
以下のウィンドウが起動するので、SourceFontFileに利用したいフォントのttfファイル、またはotfファイルを指定します。 Atlas Resolutionは大きい数字にしておいたほうが良いらしいですが、意味はよくわかってません。
ここまで設定したら、Generate Font Atlasを押下します。
少し待つと、Save Asが押せるようになるので、任意の名前で保存しましょう。 私の場合、Assets/Resources/Fontsの下に保存しました。
以下のようにフォントのアセットファイルが作成されています。
Unityでシーン遷移時に画面が暗くなる問題への対応
SceneManager.LoadSceneを使って、別のシーンに移動した際に、 移動後のシーンで画面が暗くなってしまうの対処方法です。
移動後のシーンを開いている状態で、「トップメニュー」->「Rendering」->「Lighting」を選択します。
開いたウィンドウで、「Sceneタブ」の下部にある「AutoGenerate」のチェックを外した状態で、「Gemerate Lighting」をクリックします。
これで変更後のウィンドウでも画面が明るくなります。
猫でもわかるUnity入門(第22回 Photon PUN2を使ったマルチプレイゲームチュートリアル 最終回)
えにあです。 前回に続きUnit + Photon Pun2を使ったオンラインマルチプレイゲーム作成のチュートリアルを進めていきます。 二つのアプリで
スクリプトのアタッチ
シーン上に作成した空のオブジェクト「PhotonController」に、前回作成したスクリプト「RandomMatchMaker」をアタッチします。 アタッチの方法はスクリプトをオブジェクトにドラッグアンドドロップすればOKです。
PhotonControllerをインスペクターで表示します。 RandomMatchMakerスクリプトがコンポーネントとして追加されています。 スクリプトで定義したPhotonObjectプロパティが表示されていますね。 ここに、Unityちゃんのプレハブをアタッチします。プレハブの方をアタッチしますので、プロジェクトビューから「Assets」->「Demos」->「Resources」->「unitychan_dynamic_locomotion」を選択してアタッチしてください。
この状態で一度実行してみましょう。 コンソールに大量のエラーが表示されると思います。
NullReferenceException: Object reference not set to an instance of an object UnityChan.ThirdPersonCamera.setCameraPositionNormalView () (at Assets/unity-chan!/Unity-chan! Model/Scripts/ThirdPersonCamera.cs:57) UnityChan.ThirdPersonCamera.FixedUpdate () (at Assets/unity-chan!/Unity-chan! Model/Scripts/ThirdPersonCamera.cs:49)
このエラーをクリックして、該当のソースを表示します。 ThirdPersoncCamera.csの、setCameraPositionNormalViewメソッドで、starndardPosがnullになっていることが原因のようです。
void setCameraPositionNormalView () { if (bQuickSwitch == false) { // the camera to standard position and direction // ★starndardPosがnullになっている。 transform.position = Vector3.Lerp (transform.position, standardPos.position, Time.fixedDeltaTime * smooth); transform.forward = Vector3.Lerp (transform.forward, standardPos.forward, Time.fixedDeltaTime * smooth); } else { // the camera to standard position and direction / Quick Change transform.position = standardPos.position; transform.forward = standardPos.forward; bQuickSwitch = false; } }
standardPosを設定している箇所を見るとstartメソッドの中でGameObject.Findしていることが分かります。 Unityちゃんをプレハブ化したことで、CamPosが見つからなくなったことが原因のようです。
void Start () { // 各参照の初期化 standardPos = GameObject.Find ("CamPos").transform; if (GameObject.Find ("FrontPos")) frontPos = GameObject.Find ("FrontPos").transform; if (GameObject.Find ("JumpPos")) jumpPos = GameObject.Find ("JumpPos").transform; //カメラをスタートする transform.position = standardPos.position; transform.forward = standardPos.forward; }
このThirdPersonCameraスクリプトはMain Cameraにアタッチされていて、起動するとすぐにStartメソッドがコールされ、CamPosオブジェクトを探しに行ってしまいます。
今回はサーバに接続されたタイミングでUnityちゃんのインスタンスを作成しているので、そのタイミングでThirdPersonCameraを有効にすればこのエラーは防げそうです。
まず、Main Cameraをインスペクターで開いてThridPersonCameraをオフにします。 これで実行後すぐにこのスクリプトが呼ばれることを防げます。
次に、Unityちゃんのインスタンスを作成したタイミングでThridPersonCameraをオンにします。
前回作成した、RandomMatchMakerスクリプトの、OnJoinedRoomコールバックを再度確認してみましょう。
実は、既に入室が完了したタイミングでUnityちゃんのインスタンスを作成し、カメラをオンにするように実装されています。
public override void OnJoinedRoom() { PhotonNetwork.Instantiate( PhotonObject.name, new Vector3(0f, 1f, 0f), Quaternion.identity, 0 ); GameObject mainCamera = GameObject.FindWithTag("MainCamera"); mainCamera.GetComponent<UnityChan.ThirdPersonCamera>().enabled = true; }
もう一度実行して、エラーが発生しないことを確認しておきましょう。
マルチプレイ準備
マルチプレイのテストをするためには、最低でも二つの環境から同時にアクセスする必要があります。 PC上でアプリを二つ起動するのが最も簡単な方法なのでPC向けにビルドしておきます。 ビルド対象のシーンが追加されていることと、PC向けになっていることを確認して、ビルドボタンを押します。
保存場所は任意です私は「プロジェクトルート」->「Builds」->「PUN2_pc」というフォルダを作成して指定しました。
ビルドは完了しましたが、コンソールを見ると大量に警告が出ています。 しかし、文を読んでみるとエラーではなく「deprecated」による警告だけのようですので、ここでは無視します。
NOTE
チュートリアルではAutoBlink.csで以下のエラーが発生しています。error CS0234 The tyep or namespace name 'Policy' does not exist in the namespace 'System.Security' 私の環境ではバージョン差異によるものだと思いますがこのエラーは発生しませんでした。
もし発生した場合は公式のyoutubeチュートリアル22:40あたりを見ると解決策が載っています。
それではアプリを二つ起動していきます。 1つは通常通りUnityから実行します。 この時点ではUnityちゃんは一人しか表示されていませんね。
次に、エクスプローラで先ほどBuild結果を格納したフォルダに移動し、PUN2.exeを実行します。 二人目のUnityちゃんが登場しましたね!
オプション
矢印キーで操作できるので少し動かしてみましょう。 プレイヤー1の方で操作をすると、プレイヤー2のUnityちゃんが微妙に動いているように見えます。 次にこの動きを修正していきます。
プロジェクトウィンドウの検索ボックスに「UnityChanControl」と入力し、表示されたUnityChanControlScriptWithRgidBody.csを修正していきます。
まず、継承するクラスをMonoBehaiviourから、Photon.Pun.MonoBehaviourPunに変更します。
public class UnityChanControlScriptWithRgidBody : Photon.Pun.MonoBehaviourPun // ★継承クラスの変更
次にFixedUpdateを修正し、プレイヤーの入力が、他のプレイヤーのUnityちゃんに影響を及ぼさないようにしていきます。 修正は先頭に1行追加するだけです。自身の操作の場合だけFixedUpdateが実行されるようになります。
void FixedUpdate () { if(photonView.IsMine) return; // ★追加
さあ、再度Buildして試してみましょう。 確かに他のプレイヤーの影響は受けなくなったように見えますが、私の環境では逆に挙動がおかしくなったような気がします。
この3回で、プレイヤー間でネットワークを経由して位置情報などを共有する方法について学ぶことができました。チュートリアルに含まれなかったロビーの使い方や、部屋を指定して入室する方法などは今後実際にアプリを作りながら学んでいこうと思います。 今回はここまで!
猫でもわかるUnity入門(第21回 Photon PUN2を使ったマルチプレイゲーム作成 その2)
えにあです。 Unity + Photonを使ったオンラインマルチプレイゲームのサンプル作成の第2回を進めていきます。
**目次
Unityちゃんのプレハブ化
まず、Unityちゃんをプレハブ化しておきます。
ヒエラルキービューで「unitychan_dynamic_locomotion」をドラッグし、プロジェクトビューの「Assets」->「Demos」->「Resources」にドロップします。
プレハブの種類は原型プレハブを選択します。
ここまでの手順で、Resourcesの下と、Scenesの下にファイルが作られています。
プレハブ化したので、シーン上のUnityちゃんは削除します。
ここで一度シーンを保存しましょう。
UnityちゃんプレハブへのPhotonコンポーネント追加
プロジェクトビューで、プレハブ化した「unitychan_dynamic_locomotion」を選択し、インスペクターで「プレハブを開く」を選択します。
「コンポーネントを追加」から以下3つのコンポーネントを追加していきます。
- PhotonView
- PhotonTransformView
- PhotonAnimatorView
PhotonVIewを追加します。
PhotonTransformViewを追加します。
PhotonAnimatorViewを追加します。
PhotonViewコンポーネントをUnityちゃんにアタッチすることで、Unityちゃんの位置情報などをネットワーク経由での同期対象に含めることが可能になります。
PhotonViewコンポーネントのObservedComponentプロパティを割り当てることでどの情報を同期するかを指定することができます。 Photon TransformView、Photon AnimatorViewが設定されていることを確認してください。Observable SearchがAuto Find Allになっていれば自動で設定されているはずです。
PhotonTransformViewコンポーネントをObservedComponentに割り当てることで、transform(位置情報や回転)の同期が可能になります。
PhotonAnimatorViewコンポーネントをObservedComponntに割り当てることで、animatorのパラメータの同期が可能になります。
インスペクターで「Photon Transform View」を開きます。
「Syncrhonize Options」はどのTransform項目をプレイヤー間で同期するかを表しているようです。
「Position」と「Rotation」にチェックが入っていることを確認します。
おそらく、今回のサンプルではスケールは動的に変更されることがないので同期不要ということでしょう。
インスペクターで「Photon Animator View」を開きます。 AnimatorViewでは、項目ごとに3つの同期方法を選択できます。
- disable(同期しない)
- discrete(非連続的 = 一定間隔で同期)
- continuous(連続的 = 常に同期)
ここではdiscreteとcontinuousを使って、Synchronize Parametersを以下のように変更します。
オンラインマルチプレイ用スクリプト作成
Photonを使ったオンラインマルチプレイ用のスクリプトを作成していきます。
シーン上に接続スクリプトをアタッチするための空のオブジェクトを作成します。
トップメニューから「ゲームオブジェクト」->「空のオブジェクトを作成」を選択します。「PhotonControlelr」という名前に変更します。
作成したオブジェクトにアタッチするためのスクリプトを作成します。
「Assets」->「Demos」->「Scripts」の下に、RandomMatchMakerという名前でC#スクリプトを作成します。
次にスクリプトを開いて編集していきます。 今回のサンプルでは部屋は1つしかありません。 プレイヤーがランダムに部屋に入室するメソッドを用いるのですが、部屋が1つしかないため、全員が1つの部屋に入室することになります。
まずusingにPhoton関連のパッケージを追加します。
using System.Collections; using System.Collections.Generic; using UnityEngine; using Photon.Pun; // ★追加 using Photon.Realtime; // ★追加
次に、継承元クラスであるMonoBehaiviourをMonoBehaiviourPunCallbacksに変更します。 「イベントが発生した時」というのは、例えば「サーバに接続した時」、「部屋への入室が完了した時」といったものです。
public class RandomMatchMaker : MonoBehaviourPunCallbacks // ★変更
次に、ゲームオブジェクトを設定するためのフィールドを作成しておきます。 このフィールドは後でインスペクターから設定されます。
// インスペクターから設定 public GameObject PhotonObject;
次にStartメソッドを修正します。ConnectUsingSettingsメソッドを使うことで、先ほど設定した「PhotonServerSettings」を用いてサーバに接続することができます。
void Start()
{
PhotonNetwork.ConnectUsingSettings();
}
Updateメソッドは利用しないので削除します。※コメントアウトにしていますが、削除でOKです。
// void Update() // { // }
次に、MonoBehaviourPunCallbacksクラスが提供する4つのコールバックメソッドをオーバーライドしていきます。
- OnConnectedToMaster
- OnJoinedLobby
- OnJoinRandomFailed
- OnJoinedRoom
ではまず、OnConnectedToMasterメソッドをオーバーライドします。このメソッドは、サーバへの接続が完了すると呼ばれるコールバックです。サーバへの接続が完了したら、ランダムで部屋に入室するように実装します。
public override void OnConnectedToMaster() { PhotonNetwork.JoinRandomRoom(); }
次に、OnJoinedLobbyメソッドをオーバーライドします。このメソッドはロビーへの入室が完了した時に呼ばれるコールバックです。今回のサンプルではロビーは使いませんが、ロビーに入室したら即座に部屋に入室するように実装しています。
public override void OnJoinedLobby() { PhotonNetwork.JoinRandomRoom(); }
次に、OnJoinRandomFailedをオーバーライドします。このメソッドは入室に失敗した時に呼ばれるコールバックです。一人目は部屋がないので、確実に入室に失敗します。そのため、このメソッドの中で部屋を作成しています。
部屋を作成するメソッドはCreateRoomです。第1引数にはルーム名を指定します。ルーム名は部屋を識別する場合に使いますが、今回は部屋が1つしかないのでnullを指定しています。
第2引数にはRoomOptionsを渡します。MaxPlayersを指定することで1部屋の最大に員数を制限することができます。
// 入室に失敗した場合に呼ばれるコールバック // 1人目は部屋がないため必ず失敗するので部屋を作成する public override void OnJoinRandomFailed(short returnCode, string message) { RoomOptions roomOptions = new RoomOptions(); roomOptions.MaxPlayers = 8; // 最大8人まで入室可能 PhotonNetwork.CreateRoom(null, roomOptions); //第一引数はルーム名 }
最後に、OnJoinedRoomメソッドをオーバーライドします。このメソッドは入室が完了した時に呼ばれるコールバックです。この後でインスペクターで設定するPhotonObjectプロパティに指定したオブジェクトの名前と、初期位置と回転を渡すことで、サーバ側にオブジェクトを同期します。
後半のカメラについては後ほど説明します。
public override void OnJoinedRoom() { PhotonNetwork.Instantiate( PhotonObject.name, new Vector3(0f, 1f, 0f), //ポジション Quaternion.identity, //回転 0 ); GameObject mainCamera = GameObject.FindWithTag("MainCamera"); mainCamera.GetComponent<UnityChan.ThirdPersonCamera>().enabled = true; }
スクリプトの修正は以上です。 今回はここまで!
最終的なスクリプトは以下に記載しておきます。
using System.Collections; using System.Collections.Generic; using UnityEngine; using Photon.Pun; using Photon.Realtime; public class RandomMatchMaker : MonoBehaviourPunCallbacks { // インスペクターから設定 public GameObject PhotonObject; void Start() { PhotonNetwork.ConnectUsingSettings(); } public override void OnConnectedToMaster() { PhotonNetwork.JoinRandomRoom(); } public override void OnJoinedLobby() { PhotonNetwork.JoinRandomRoom(); } public override void OnJoinRandomFailed(short returnCode, string message) { RoomOptions roomOptions = new RoomOptions(); roomOptions.MaxPlayers = 8; PhotonNetwork.CreateRoom(null, roomOptions); } public override void OnJoinedRoom() { PhotonNetwork.Instantiate( PhotonObject.name, new Vector3(0f, 1f, 0f), Quaternion.identity, 0 ); GameObject mainCamera = GameObject.FindWithTag("MainCamera"); mainCamera.GetComponent<UnityChan.ThirdPersonCamera>().enabled = true; } }