- 投稿日:2020-02-07T18:04:41+09:00
UnityAcceleratorをLinux上に立ててサービス化する
Unity2019.3からアセットのキャッシュ管理にUnityAcceleratorの使用が推奨されており、
サーバに立てたときの備忘録UnityAccelerator: v1.0.90+gd82184f
OS: AmazonLinux2インストール
インストールスクリプトを落として実行する
curl https://unity-accelerator-prd.storage.googleapis.com/unity-accelerator-linux-installer.run --output unity-accelerator-linux-installer.run sudo ./unity-accelerator-linux-installer.run --mode unattended ※ 「--mode unattended」を付与しない場合は対話式で設定変更が可能 一度試した場合は入力項目が多く面倒だったので付与してデフォルトインストールにしたサーバ再起動時の自動起動化
インストールスクリプト実行時にサービス登録されてるので有効化しておく
/sbin/chkconfig unity-accelerator on対象ポートの変更
設定ファイルは/root/.config/unity-accelerator/に展開されている
vi /root/.config/unity-accelerator/unity-accelerator.cfg →ProtobufPort、LastUsedProtobufPortを任意のポートに変更 service unity-accelerator restart参考サイト
https://docs.unity3d.com/2019.3/Documentation/Manual/UnityAccelerator.html
https://forum.unity.com/threads/accelerator-options.784514/
- 投稿日:2020-02-07T15:38:31+09:00
Unity で SQLite を使う基本的な使い方まとめ
Unity で SQLite を使う基本的な使い方まとめ
Unity の更新がはやいのと Android が x64 対策でいろいろと設定方法が変わっているように思いました。
困ったのは、今でも.so
ファイル形式をインポートして設定する方法がよく検索にあがることです。Windows 環境だと
.so
ファイルをコンパイルして用意するのは、なかなか困難ですが、現在はAAR
形式を公式の SQLite.org からダウンロードして、そのままインポートすれば OK になってました。記事にまとめたので、ショートカットをメモ。
Android の 64 ビット対策
Unity はビギナーなので、間違いがあったらすいません。(おしえてください)
- 投稿日:2020-02-07T14:43:08+09:00
【Unity】独自コンポーネントをCreate/AddComponentの既存カテゴリ階層に追加する
はじめに
以前書いた『描画負荷がかからない透明なuGUI Imageを作る【Unity】』の中で紹介している
NoRenderImage
というコンポーネントをHierarchyのCreate/UI
以下から追加できるようにしたり、AddComponentのUI
以下から追加できるようにしました。新しく追加するだけなら簡単ですが既存のカテゴリに追加する方法が少しだけややこしかったので、簡単に解説します。
AddComponentの既存カテゴリ階層に追加する
こっちの方が簡単なので先に紹介します。
クラスの先頭に
[AddComponentMenu()]
をつけるだけです。既存カテゴリ以下にしたければ/
で区切って指定してください。第二引数は表示順ですが、コンポーネントについているAddComponentメニューの方では反映されなくて、メニューバーのComponentの方のみに適用されます。[AddComponentMenu("UI/NonRenderImage", 14)] public class NoRenderImage : Graphic { }例えば
RectMask2D
の下に追加したい場合はRectMask2D
の定義を調べます(コードエディタから辿れます)。(抜粋)RectMask2D.csnamespace UnityEngine.UI { [AddComponentMenu("UI/Rect Mask 2D", 13)] [DisallowMultipleComponent] [ExecuteAlways] [RequireComponent(typeof(RectTransform))] public class RectMask2D : UIBehaviour, IClipper, ICanvasRaycastFilter { } }
13
が指定されていることが確認できるため、14
を指定してその直後に表示させることができました。ちなみに表示順指定は
int
型なので、連番の中に挟む際の細かい表示順は指定できなさそうです。(RawImage
が12
、Mask
とRectMask2D
が13
なので、その間は多分辞書順とかでしか制御できない)Createの既存カテゴリ階層に追加する
Hierarchyの
Create/UI
以下などに追加する方法です。Canvasの扱いについても簡単に紹介します。こちらはコンポーネント自体の指定ではなく、生成するメソッドが登録されているメニューになります。以下のような
static
メソッドを用意し、[MenuItem()]
アトリビュートを追加します。[MenuItem("GameObject/UI/NoRender Image", false, 2003)] public static void CreateNoRenderImage() { var go = new GameObject("NoRenderImage"); go.AddComponent<NoRenderImage>(); }^実行すると
NoRenderImage
がアタッチされたGameObjectが生成されるメソッドこちらは第三引数で表示順の指定をします。既存のCreateメソッドは
UnityEditor.UI
のinternal
クラス内にありコードエディタからでは辿れないため、Bitbucket上で公開されているリポジトリから確認します。
Unity-Technologies / ui / UnityEditor.UI / UI / MenuOptions.cs — Bitbucket(抜粋)MenuOptions.cs[MenuItem("GameObject/UI/Raw Image", false, 2002)] static public void AddRawImage(MenuCommand menuCommand) { }例えば
RawImage
は2002
が指定されているため、直後に表示したい場合は2003
などを指定すれば良いです。また、生成時に他のコンポーネントと同様に選択中のGameObject以下に生成するようにしてみましょう。Canvas以下でなかった場合は生成する処理も書きました。
[MenuItem("GameObject/UI/NoRender Image", false, 2003)] public static void CreateNoRenderImage() { // 選択状態のGameObjectを取得する var parent = Selection.activeGameObject?.transform; // 親や祖先にCanvasが存在しない場合 if (parent == null || parent.GetComponentInParent<Canvas>() == null) { // 新規Canvasの生成 var canvas = new GameObject("Canvas"); canvas.transform.SetParent(parent); // Canvasの初期化 canvas.AddComponent<Canvas>().renderMode = RenderMode.ScreenSpaceOverlay; canvas.AddComponent<CanvasScaler>(); canvas.AddComponent<GraphicRaycaster>(); // 親の付け替え parent = canvas.transform; } var go = new GameObject("NoRenderImage"); // RectTransformの初期化 var rectTransform = go.AddComponent<RectTransform>(); // 親コンポーネントの指定 (nullの場合はルートになるので問題ない) rectTransform.SetParent(parent); rectTransform.sizeDelta = s_ImageElementSize; rectTransform.anchoredPosition = Vector2.zero; // 生成したGameObjectを選択状態にする Selection.activeGameObject = go; // コンポーネントの追加 go.AddComponent<NoRenderImage>(); }簡易的ですが、これで他のUIコンポーネントと同様の振る舞いをするようになったと思います。
^生成後のGameObjectが選択状態になる / Canvas下でない場合は生成するスクリプト全文
Gist: NoRenderImage.cs
NoRenderImage.csusing UnityEditor; namespace UnityEngine.UI { /// <summary> /// 描画しない透明Imageコンポーネント /// </summary> [AddComponentMenu("UI/NonRenderImage", 14)] public class NoRenderImage : Graphic { protected override void OnPopulateMesh(VertexHelper vh) { vh.Clear(); } #if UNITY_EDITOR [UnityEditor.CustomEditor(typeof(NoRenderImage))] class NonRenderImageEditor : UnityEditor.Editor { public override void OnInspectorGUI() { } private static Vector2 s_ImageElementSize = new Vector2(100f, 100f); [MenuItem("GameObject/UI/NoRender Image", false, 2003)] public static void CreateNoRenderImage() { // 選択状態のGameObjectを取得する var parent = Selection.activeGameObject?.transform; // 親や祖先にCanvasが存在しない場合 if (parent == null || parent.GetComponentInParent<Canvas>() == null) { // 新規Canvasの生成 var canvas = new GameObject("Canvas"); canvas.transform.SetParent(parent); // Canvasの初期化 canvas.AddComponent<Canvas>().renderMode = RenderMode.ScreenSpaceOverlay; canvas.AddComponent<CanvasScaler>(); canvas.AddComponent<GraphicRaycaster>(); // 親の付け替え parent = canvas.transform; } var go = new GameObject("NoRenderImage"); // RectTransformの初期化 var rectTransform = go.AddComponent<RectTransform>(); // 親コンポーネントの指定 (nullの場合はルートになるので問題ない) rectTransform.SetParent(parent); rectTransform.sizeDelta = s_ImageElementSize; rectTransform.anchoredPosition = Vector2.zero; // 生成したGameObjectを選択状態にする Selection.activeGameObject = go; // コンポーネントの追加 go.AddComponent<NoRenderImage>(); } } #endif } }最後に
CreateやAddComponentに追加する記事はいくつかありましたが、既存のカテゴリ階層に追加する方法は見当たらなかったので簡単にまとめてみました。
もし参考になったら「いいね」やTwitterのフォローよろしくお願いします!
Twitter: @nkjzm参考
【Unity】AddComponentMenuでスクリプトを整理して表示 │ エクスプラボ
https://ekulabo.com/add-component-menu
- 投稿日:2020-02-07T14:25:12+09:00
Unity ARkitのFaceTrackingでシーン遷移するとクラッシュする
どんな問題か
UnityでFaceTrackingのアプリを作ったら起こった問題
FaceTrackingシーンから他のシーンに遷移するとき、IOS実機だと落ちるlibc++abi.dylib: terminating with uncaught exception of type Il2CppExceptionWrapper
(lldb)こんなのを残してさよなら
解決方法
ios - Unity Switch between ARKit Face Tracking and Rear Camera? - Stack Overflow
↑
これで治った。
ExampleのUnityARFaceAnchorManager.cs を改変した人は注意永遠悩んでた。海外質問フォームって偉大だなぁ、
- 投稿日:2020-02-07T14:06:26+09:00
【Unity】カレンダーの作成【Android/ios】
はじめに
ある日、アプリの制作にカレンダーを使用したくなりました。
「Unity カレンダー」で先生に尋ねてもあまり自分の用途に合った記事が出てこない…
あまりというかほぼ出てこない…なんで?カレンダーになんか恨みあるの?というわけで適当にパパっと作ってみました。
意外に詰まったので同じ境遇の方がいれば参考にしていただければ幸いです。こんな感じのです。
ボタンを並べる
カレンダー自体は、GameObjectにプレハブのButtonを7*6の42個配置していてそこに数字を入れている感じなのでまずはButtonのプレハブを作成します。
作成方法はこちらなど参考にしてください。
大きさなどはGameObjectでそろえるので適当で大丈夫ですがデフォルトの画像だと集合体恐怖症さんが発狂してしまうので無地の画像を適当に作成し、使用したほうがいいと思います。
作るのめんどい人はどうぞ。そしてPanelを新規作成し好みの大きさに合わせて、その子として新規オブジェクトを配置します。
このGameObjectにグリットレイアウトグループ
コンポーネントを追加します。これをすることでこのオブジェクトに配置されたボタンがサイズを合わせて並ぶようになります。
そして、オブジェクトを配置するスクリプトを書いていきます。Calendar.csusing System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using System; public class Calender : MonoBehaviour { public GameObject canvas;//エディタから指定 public GameObject prefab;//エディタから指定 void Start() { for (int i = 0; i < 42; i++) { GameObject button = Instantiate(prefab, canvas.transform); button.GetComponent<Button>(); } } }これをGameObjectに追加し、プレハブにはボタンのプレハブをCanvasにはGameObjectを追加してください。この状態で一度再生してみます。
ボタンが白のため死ぬほど見づらいですが42個配置されました。ちゃんと確認したい場合はプレハブのボタンの画像を変更してみてください。GameObjectの幅が狭いと横に7個配置されない場合があるので適宜調整してください。日付を入れる
このままでは白いボタンが42個配置されただけなのでここに日付を入力していきます。先ほど作ったCalender.csに以下を追加してみてください。
Calendar.cspublic static DateTime SelectDate; private DateTime D_Date; private int startday; private void CalendarController() { int days = 1; int overday = 1; D_Date = new DateTime(SelectDate.Year, SelectDate.Month, 1); //SelectDateの月の最初の日付 int year = SelectDate.Year; //年 int month = SelectDate.Month; //月 int day = SelectDate.Day; //日 //最初の日付の曜日を取得 DayOfWeek firstDate = D_Date.DayOfWeek; //何日まであるか int monthEnd = DateTime.DaysInMonth(year, month); //前月が何日まであるか SelectDate = SelectDate.AddMonths(-1); month = SelectDate.Month; SelectDate = SelectDate.AddMonths(1); int lastmonth = DateTime.DaysInMonth(year, month); switch (firstDate) { case DayOfWeek.Sunday: startday = 0; break; case DayOfWeek.Monday: startday = 1; break; case DayOfWeek.Tuesday: startday = 2; break; case DayOfWeek.Wednesday: startday = 3; break; case DayOfWeek.Thursday: startday = 4; break; case DayOfWeek.Friday: startday = 5; break; case DayOfWeek.Saturday: startday = 6; break; } int lastmonthdays = lastmonth - startday + 1; for (int i = 0; i < 42; i++) { if (i >= startday) { if (days <= monthEnd) { //文字を入れる Transform DAY = GameObject.Find("GameObject").transform.GetChild(i); DateTime tmp = D_Date;//一時変数 DayOfWeek num = tmp.DayOfWeek; //土曜日青・日曜日赤 switch (num) { case DayOfWeek.Sunday: DAY.GetChild(0).GetComponent<Text>().color = Color.red; break; case DayOfWeek.Saturday: DAY.GetChild(0).GetComponent<Text>().color = Color.blue; break; default: DAY.GetChild(0).GetComponent<Text>().color = Color.black; break; } DAY.GetChild(0).GetComponent<Text>().text = D_Date.Day.ToString(); D_Date = D_Date.AddDays(1); days++; } else { Transform DAY = GameObject.Find("GameObject").transform.GetChild(i); DAY.GetChild(0).GetComponent<Text>().color = Color.gray; DAY.GetChild(0).GetComponent<Text>().text = overday.ToString(); GameObject button = GameObject.Find("GameObject").transform.GetChild(i).gameObject; button.GetComponent<Button>().onClick.RemoveAllListeners(); overday++; } } else { Transform DAY = GameObject.Find("GameObject").transform.GetChild(i); DAY.GetChild(0).GetComponent<Text>().color = Color.gray; DAY.GetChild(0).GetComponent<Text>().text = lastmonthdays.ToString(); GameObject button = GameObject.Find("GameObject").transform.GetChild(i).gameObject; button.GetComponent<Button>().onClick.RemoveAllListeners(); lastmonthdays++; } } }死ぬほど見づらいコードだしなんか気持ち悪い箇所もあるかと思うのですが備忘録として書いているのものなのでお手柔らかにお願いします。(白目)
そしてvoid Start()
にSelectDate = DateTime.Now; CalendarController();はい、日付が登録されました。
SelectDate
をDateTime.Nowにしているので実行した月のカレンダーができていると思います。ここを変更すれば変更した月のカレンダーが表示されます。
カレンダーを表示したいだけの方はこれにて完了になります。ボタン押下時に値を保存する
自分はカレンダーで選択した値を使いたかったのでボタンを押した際の処理を追記していきます。
上のコードのFor分を以下に変更し、関数も追加してください。Calendar.csfor (int i = 0; i < 42; i++) { if (i >= startday) { if (days <= monthEnd) { //文字を入れる Transform DAY = GameObject.Find("GameObject").transform.GetChild(i); DateTime tmp = D_Date;//一時変数 DayOfWeek num = tmp.DayOfWeek; //土曜日青・日曜日赤 switch (num) { case DayOfWeek.Sunday: DAY.GetChild(0).GetComponent<Text>().color = Color.red; break; case DayOfWeek.Saturday: DAY.GetChild(0).GetComponent<Text>().color = Color.blue; break; default: DAY.GetChild(0).GetComponent<Text>().color = Color.black; break; } DAY.GetChild(0).GetComponent<Text>().text = D_Date.Day.ToString(); //以下3行追加 GameObject button = GameObject.Find("GameObject").transform.GetChild(i).gameObject; button.GetComponent<Button>().onClick.RemoveAllListeners(); button.GetComponent<Button>().onClick.AddListener(() => { set_Date(tmp); }); D_Date = D_Date.AddDays(1); days++; } else { Transform DAY = GameObject.Find("GameObject").transform.GetChild(i); DAY.GetChild(0).GetComponent<Text>().color = Color.gray; DAY.GetChild(0).GetComponent<Text>().text = overday.ToString(); GameObject button = GameObject.Find("GameObject").transform.GetChild(i).gameObject; button.GetComponent<Button>().onClick.RemoveAllListeners(); overday++; } } else { Transform DAY = GameObject.Find("GameObject").transform.GetChild(i); DAY.GetChild(0).GetComponent<Text>().color = Color.gray; DAY.GetChild(0).GetComponent<Text>().text = lastmonthdays.ToString(); GameObject button = GameObject.Find("GameObject").transform.GetChild(i).gameObject; button.GetComponent<Button>().onClick.RemoveAllListeners(); lastmonthdays++; } } void set_Date(DateTime date) { Debug.Log(date); //値を保存する処理など }これで実行してみます。
自分はわかりやすいようにテキストで表示していますが上のコードだとログで表示されるはずです。
以上になります。わかりづらいかもしれませんがお役に立てたら幸いです。
- 投稿日:2020-02-07T04:02:35+09:00
Unityでシューティングゲームを作る(4)
ここまでの進捗
- 背景がループするようにした。
- 普通の敵の動作を作成し、その敵が3秒ごとに生成される。
- 瞬間移動する敵の動作を作成し、5秒ごとに生成する。
- プレイヤーが画面の範囲外に行かないようにした。
- 敵とプレイヤーが衝突したらプレイヤーが消滅する。
- 分散攻撃の敵を実装する。
- タイトルシーンとエンディングシーンを追加する。
今後やること
- ボスキャラの動作を実装する。
- エフェクトとBGMを追加する。
- プレイヤーが横に移動すると機体が傾くアニメーションをつける
- プレイヤーがダメージ受けると点滅して数秒だけ無敵状態になる
この記事では赤い部分を作成した。
プレイヤーがダメージを受けると点滅する
点滅するコルーチンを作成してプレイヤーの衝突判定の中でコルーチンを実行するようにした
コルーチンは関数内で時間を空けて処理をさせたいときに使われる点滅するコルーチンの作成に関してはこのサイトがとても参考になった。
ftvlog/オブジェクトを点滅させるスクリプト以下がコルーチンとなる
//ダメージを受けた時に点滅する IEnumerator Blink() { for(int i=0;i < 4; i++) { renderer.enabled = !renderer.enabled; yield return new WaitForSeconds(0.2f); } }この中でオブジェクトの点滅を0.2秒間隔で4回行っている
これによってダメージを受けると以下のようになった
プレイヤーがダメージを受けて点滅してる間は無敵になる
今回はプレイヤーが攻撃を受けてから点滅している間だけプレイヤーのレイヤーを変更することによって衝突判定を無効化した。
teratailに質問があったので参考にした。
teratail/衝突判定を一定時間無効化したいですまずレイヤーを追加するために[Edit]→[Project Settings]を選択する。
この設定画面がでるので左の欄から[Tags and Layers]を選択し、Layersの中からUser Layerのどれかに名前を付ける
今回はUser Layer 9にInvisibleという名前を付けた。最後に左の欄からPhysicsを選択し、衝突を無効化したいオブジェクトがあるレイヤーと先ほど作成したレイヤーのチェックを外す。
これによってInvisibleのレイヤにあるオブジェクトとDefaultにあるオブジェクトの衝突が無効化される。ちょっと見ずらいかもしれないけど、点滅時間が1.2秒で短いので一瞬しか無効にならない。
今後調整していこうと思う。これで弾を受けたときの点滅と無敵時間を作ることができた。
難易度をあげるにつれて点滅時間の延長も検討していきたい。次回はアニメーションをつけてボスを作成して完成させたい。
ちなみにここからこだわるつもり