NinaLabo

個人ゲーム開発者の技術メモ

【Unity】UIElementsの導入

Unity2020になってEditor利用だけだったUIElementsがランタイムのゲームUIとして使えるようになったようです。

 

UIElements 開発者ガイド - Unity マニュアル

f:id:ninagreen:20201116023428p:plain

 

原始的なIMGUIに始まり、NGUIが席巻したと思ったら、UGUIがUnityから出て、落ち着いてきた頃にUIElementsに変わるとか、UI領域は技術の陳腐化が早すぎて本当に大変です。

最終的にUIElementsがUGUIに取って変わるのか、それとも結局UGUIが残り続けるのかはわかりませんが、ローグスフィア2の開発はUIElementsでやってみようかと思ってます。

 

まずはインストールして簡単なものを表示してみるところまでやってみます。

環境は Unity2020.1.13f1を使用しています(2020/11/16時点の最新)

 

UIElementsをインストール

Window > PackageManager を開く

まだpreviewの状態のため、左上の+ボタンから「Add package from git URL」を選択して 「com.unity.ui」を入力してインストールします

*昔はcom.unity.ui.runtimeだったようですがそちらは古いようで、com.unity.uiが新しいようです。

 

Runtime package 0.0.4 - Unity Forum

com.unity.ui.runtime is not supported, it's the old version and name of the pacakge.

You need to use the new package going forward "com.unity.ui" (no .runtime)

"com.unity.ui": "1.0.0-preview.3"

 

しばらくするとUI ToolKitのインストールが完了します

f:id:ninagreen:20201116032158p:plain

 

同じく「com.unity.ui.builder」を入力してUI Builderもインストールします。

f:id:ninagreen:20201117011750p:plain

 

レイアウトの生成(UXML作成)

Window > UI ToolKit > UIBuilderを開いてレイアウトを生成

f:id:ninagreen:20201117013011p:plain

UIBuilderの詳細な使い方は追々調べることにして、ひとまずは簡単なレイアウトを作成して

f:id:ninagreen:20201117013146p:plain

File > Save で適当な場所にuxmlファイルを保存

f:id:ninagreen:20201117013233p:plain

 

UIDocumentのアタッチ

シーン上に適当なオブジェクトを作成してUIDocumentをアタッチ

f:id:ninagreen:20201117025248p:plain

・PanelSettingsには

Projectウィンドウで右クリック > Create > UI ToolKit > Panel Settings Asset

で作成したPanelSettingsを設定する

・Source Assetには先ほど保存したuxmlファイルを設定する

 

再生

Unityを再生するとGameSceneにUIが表示されます。

再生したまま、UI Builderのレイアウトを編集できるのは便利で良いですね。

 

参考資料 

www.youtube.com

 

【LeetCode】20. Valid Parentheses(Easy)

【最初に】

LeetCode 8個目に挑戦です

leetcode.com


 

 

【問題】

次の '('')''{''}''['']' の文字だけを含んだ文字列の括弧対応が正しいか判定せよ。空文字列は正しいと判定すること。 

Example 1:

Input: "()"
Output: true

Example 2:

Input: "()[]{}"
Output: true

Example 3:

Input: "(]"
Output: false

Example 4:

Input: "([)]"
Output: false

Example 5:

Input: "{[]}"
Output: true

 

【とりあえず】

思いつくのは左括弧の場合はStackに格納し、右括弧の場合はStackから取り出して括弧の対応が正しいか判定する、かな。

f:id:ninagreen:20191113020438p:plain

 

 できた!

f:id:ninagreen:20191113020503p:plain

【解答を見る】

だいたい↑と同じことやってた

 

【最後に】

最初に解いた内容と解答が同じだったのははじめてだな

 

【LeetCode】104. Maximum Depth of Binary Tree(Easy)

【最初に】

LeetCode 7個目に挑戦です

leetcode.com

 

 

【問題】

与えられたバイナリツリー(二分木)の最大深度を求めよ

Example:

Given binary tree [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

return its depth = 3.

 

【とりあえず】

再帰処理で全探索する。左と右で深度の大きいほうを返し続ければ最大深度になるはず。

f:id:ninagreen:20191112023129p:plain

 

できた!

f:id:ninagreen:20191112023152p:plain

 

【解答を見る】

と思ったらPremiumに加入してないと解答が見れないようになってる!仕方ないので、Discussionを見てみる。あ、そうか別にCheckChildとか別関数を作らなくても、もともとのmaxDepth関数を再帰させればいいのか。

 

f:id:ninagreen:20191112024114p:plain

引数が子要素を持たないノードの場合、maxDepth(root->left) も maxDepth(root->right) も0が帰ってくる。その状態から+1ずつしていけば深さを求めることができる。

 

できた!

f:id:ninagreen:20191112024439p:plain

余計なメソッド呼び出しがなくなったからか、実行速度も16msから8msにあがってる!

 

【最後に】

 Solutionは無料で全部見れると思ってたのに・・(TーT

【LeetCode】83. Remove Duplicates from Sorted List(Easy)

【最初に】

LeetCode 6個目に挑戦です

leetcode.com

 

 

【問題】

与えられたLinkedListから重複を排除せよ

Example 1:

Input: 1->1->2
Output: 1->2

Example 2:

Input: 1->1->2->3->3
Output: 1->2->3

 

【とりあえず】

ぱっと思いつくのは、前回の↓と同様にLinkedListをループで回して過去に調べた数字は可変長配列に保存しておき、重複した数字が出現した場合はnextを次の次のノードに書き換えるというもの。

ninagreen.hatenablog.com

 

f:id:ninagreen:20191110042015p:plain

 

できた!

f:id:ninagreen:20191110042043p:plain

 

【解答を見る】

どうやら問題のLinkedListはソートされている前提らしい。であれば、過去に調べた値をvectorに入れて比較せずとも、前の値と次の値を比較するだけで問題ない。

f:id:ninagreen:20191112020405p:plain

こちらのほうがvectorに値を保存しないので、空間計算量がO(n) → O(1) になる。
 

【最後に】

問題文の最初に"sorted"って書いてありました。

Given a sorted linked list, 

よく読まないと.. ですね

 

 

【LeetCode】141. Linked List Cycle(Easy)

【最初に】

LeetCode 5個目に挑戦です

 

leetcode.com

 

 

【問題】

与えられたLinkedListが循環しているかどうか判定せよ  

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the second node.

Example 2:

Input: head = [1,2], pos = 0
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the first node.

Example 3:

Input: head = [1], pos = -1
Output: false
Explanation: There is no cycle in the linked list.

 

【1.とりあえず】

ぱっと思いついたのは、LinkedListをループさせて可変長配列に詰めていく。過去のノードと同じノードが出てきたら循環参照していると判定する。

 

f:id:ninagreen:20191110025557p:plain

できた!

f:id:ninagreen:20191110025956p:plain

 

【2.違うパターン】

問題文の最後に

Can you solve it using O(1) (i.e. constant) memory?

とあるので、空間計算量がO(1)になるように考えてみる(今はLinkedListを全件ループして配列に格納しているのでO(n)になっている)

 

時間計算量はO(n)→O(n^2) になっちゃうけど、とにかく保存せずにループ回しまくってみる。

 

f:id:ninagreen:20191110031450p:plain

 

ひどいコードだけど一応できた!

f:id:ninagreen:20191110031549p:plain

 

【3.解答を見てみる】

2つの異なるスピードのポインターを持てばいいのでは?とあるが、個人的にはなかなか馴染みのない考え方。要は足の速い選手と遅い選手がいて、遅い選手が1進むたびに速い選手が2進むとすると、循環参照していた場合、足の速い選手が1ずつ周回遅れの遅い選手との距離を縮めて行っていつか追いつくというもの。やってみた。

 

f:id:ninagreen:20191110034015p:plain

 

できた!

f:id:ninagreen:20191110034029p:plain

 

これだと2のパターンよりループ回数も少なくて済むし、1のパターンよりメモリ使用量も少なくても済む。

 

【最後に】

最初に考えた人、頭いいなあ

 

 

【LeetCode】13. Roman to Integer(Easy)

【最初に】

LeetCode 4個目に挑戦です

leetcode.com


 

 

 

【問題】

https://leetcode.com/problems/roman-to-integer/

ローマ数字を整数に変換せよ

Example 1:

Input: "III"
Output: 3

Example 2:

Input: "IV"
Output: 4

Example 3:

Input: "IX"
Output: 9

Example 4:

Input: "LVIII"
Output: 58
Explanation: L = 50, V= 5, III = 3.

Example 5:

Input: "MCMXCIV"
Output: 1994
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.
 

【とりあえず】

文字から数字に置き換えて足していく。前の文字より数字が小さければ前の文字から引いた数字を足していく。

f:id:ninagreen:20191108015257p:plain

f:id:ninagreen:20191108015315p:plain

 

できた!

f:id:ninagreen:20191108015355p:plain


【解答をチラ見..】

しようと思ったら、この問題には解答がない!そんな問題あるんですね。簡単だからいらないでしょ?ってこと??

 

【LeetCode】9. Palindrome Number (Easy)

【最初に】

LeetCode 3個目に挑戦です

leetcode.com

 

 

 

【問題】

https://leetcode.com/problems/palindrome-number/

回文の整数(前から読んでも後ろから読んでも同じ数値になっている)かどうかを判定せよ。

Example 1:

Input: 121
Output: true

Example 2:

Input: -121
Output: false
Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.

Example 3:

Input: 10
Output: false
Explanation: Reads 01 from right to left. Therefore it is not a palindrome.

 

【とりあえず】

数値を文字列にして前からと後ろからで比較してみる

f:id:ninagreen:20191107233351p:plain

 

できた!

f:id:ninagreen:20191107233439p:plain

 

【違うパターン】

Coud you solve it without converting the integer to a string?

問題の最後に、integerをstringに変換せずに解いてみない?とある。

うーん、これって前回やった数値を逆にするのを使えばいけるんじゃない?

ninagreen.hatenablog.com

 

ということで、やってみた。

f:id:ninagreen:20191107235432p:plain

 

マイナスの場合は判定するまでもなくfalse、オーバーフローの場合もfalseにしつつ、数値を逆に並び替える。最後に入力された数字と並び替えた数字を比較して同じかどうかを返す。

 

できた!

f:id:ninagreen:20191107235601p:plain

 

 

【解答をチラ見する】

解答は数値を半分だけ逆順にすれば、回文であれば残りの数字と同じになるよねという考え方のよう。例えば、1221であれば1桁目と2桁目の21を逆順にした12は、残りの3桁目と4桁目と同じになる。

 

f:id:ninagreen:20191108004646p:plain

最後の判定で10で割った値と比較しているのは、数字が奇数だった場合、例えば入力値が12321の場合、x=12、result=123になるのでこのままだとfalseになってしまうから。真ん中の値は何でもいいので、resultを10で割って12に無理やりしている。

また、最初に10で割り切れる数を除外しているのは、例えば入力値が10の場合、最終的にx <= resultにならないとwhileループを抜けないので、ループを抜ける頃には x=0、result=1 になっている。このままだと回文でないにも関わらず、奇数計算用の x == result / 10 で true になってしまうので事前に除外する必要がある。

 

全部並べ換えるよりループは半分で済むけど、なんかわかりにくいように思うのは私だけ...?

 

【最後に】

以前やった問題とほぼ同じ問題かと思ったけど、そんなの出ないよね。