UnityでジョイスティックのようなUIを作成したい!
Unity
でモックを作成するときに仮想コントローラを作る機会がありました。仮想コントローラで少し大変なジョイスティックを実装した時にどのような感じで実装するかUIのみになりますが簡単に記述します。間違っている、もっといい方法があるかもしれないということを念頭に置いて参考にしてください( ´Ꙩωꙩ` )
以下画像のようにCanvas
内でゲームオブジェクトを作成します。CanvasのImageのJostickFrame
とButtonのJoystickButton
を追加します。
JoystickButton
ゲームオブジェクトにJoystick.cs
スクリプトとEvent Trigger
を追加します。Joystick.cs
の内容については以下に記述します。以下記述するスクリプトの今回の内容は、ゲームコントローラにあるようなジョイスティックのような挙動になるような制御になります。
using System.Collections; using System.Collections.Generic; using UnityEngine.Events; using UnityEngine.EventSystems; using UnityEngine; public class Joystick : MonoBehaviour, IPointerUpHandler, IdragHandler { private GameObject joystickButtonObject; private Vector2 initialJoystickButtonPosition; void Start() { joystickButtonObject = this.gameObject; initialJoystickButtonPotision = joystickButtonObject.transform.position; } void Update() { } // ボタンをリリース public void OnPointerUp(PointerEventData ped) { joystickButtonObject.transform.position = initialJoystickButtonPosition; } // OnPointerDown実行後に移動した時 public void OnDrag(PointerEventData ped) { // JoystickButtonが移動する前にtransformを取得 Vector2 beforeMovePosition = joystickButtonObject.transform.position; // JoystickButtonゲームオブジェクトの移動 joystickButtonObject.transform.position = new Vector2( joystickButtonObject.transform.position.x + ped.delta.x, joystickButtonObject.transform.position.y + ped.delta.y ); // 初期位置からの移動距離を算出 float moveX = joystickButtonObject.transform.position.x - initialJoystickButtonPosition.x; float moveY = joystickButtonObject.transform.position.y - initialJoystickButtonPosition.y; // 三平方の定理(a^2+b^2=c^2)で移動距離を算出 float moveDistance = Mathf.Sqrt(Mathf.Pow(moveX, 2) + Mathf.Pow(moveY, 2)); // 移動距離を超えている場合は移動前に戻す if (moveDistance >= MaxEnableDistance) { joystickButtonObject.transform.position = beforeMovePosition; } } }
ゲームのジョイスティックはJoystickButton
の移動反映は円形になります。そこで、中心点から反映内の直線距離を算出するために、三平方の定理を使うことにします。
これを使用するとうまいことジョイスティックみたいになります( ´Ꙩωꙩ` )b
Jenkinsから対話式のシェルを実行
Jenkins
からあるサーバに置いてあるシェルスクリプトを実行しなくてはいけないことになりました。
実行するだけならジョブのシェル実行にssh $HOSTNAME $SHELL_PATH
を記述すれば良いですが、
実行しなくてはいけないシェルは対話式になっていました(◞‸◟)
ということで、対話式のシェルを実行するためのシェルを作成してJenkins
からでも実行できるようにしました。
#!/bin/bash SHELL_PATH="/usr/local/bin/deploy.sh" TARGET_ENV="develop" TARGET_BRANCH="master" expect -c " set timeout -1 spawn $SHELL_PATH expect -re \"Select Environment?.*\" send \"${TARGET_ENV}\n\" expect -re \"Select Branch?.*\" send \"${TARGET_BRANCH}\n\" expect eof exit "
対話式に対応させるためにexpect
コマンドを使用して実現させました。細かく説明しますと、
expect -c "[コマンド群]"
:スクリプトを実行する前に、実行するコマンドを指示する。コマンドはシェルに壊されないようにクオートで囲むべきとされている。
set timeout -1
:タイムアウトにする時間を設定できる。無制限にしたい場合は-1
を設定する
spawn [実行コマンド]
:ここで実行するシェルを指定する。
expect -re "[対話の対象となる文字文字列]"
:対話の対象になる文字列を指定する。
send "[対象の応答]"
:対話に対する応答の文字列を指定する。
expect eof
,exit
:cronやjenkinsから実行する場合はexpect eof
とexit
とする必要がある。
このシェルを使用すると対話式のシェルでもJenkins
から実行できるようになります。うむ、超絶便利!
Ruby on RailsにてRedisにマスタデータのModelをキャッシュ
とあるシュミレータをruby on rails
上で作成することになり、ある処理を何万回、
何百万回と動作させなければいけなくなった。例えば以下の処理が本番環境で動作している。
def cards (1..1000).each do |index| index.to_s + ": " + Card.all[Random.rand(Card.all.size)].name end end
1000回ほど、カードというマスタデータのnameカラムをランダムに1件ずつ取得している処理だが、
Completed 200 OK in 17243ms (Views: 29.3ms | ActiveRecord: 2451.8ms)
ぐらいの処理時間になってしまう。特にActiveRecord: 2451.8ms
は1回の処理でmysqlに
アクセスしてしまうためにモデルデータをなんとかキャッシュできないかと考えなければいけない....!
というわけでruby on rails
にredis
を導入し、モデルデータをキャッシュしてしまおうと対応にでた。
def cards (1..1000).each do |index| cache = Rails.cache.fetch("card_data", expires_in: 1.hour) do Card.all.to_a end index.to_s + ": " + cache[Random.rand(cache.size)].name end end
card_data
というkeyのvalueにCardモデルの内容を全てキャッシュするように記述してみました。
(expires_in
に関してはTTL
時間で1時間だけキャッシングするという記述)
これで処理してみると
Completed 200 OK in 16713ms (Views: 94.6ms | ActiveRecord: 0.4ms)
という結果を得ることができました。なんとActiveRecord: 0.4ms
という速度になり、log
を確認すると
mysqlログ
もなくなりキャッシュからデータを取得できていることも確認できました。
(Views: 94.6msになってるのはなぜ・・)
ちなみに実際、どのようにデータがキャッシュされているかは以下コマンドで確認することができます。
$ redis-cli // redisコンソールの起動 127.0.0.1:6379> keys * // キャッシュされているkey一覧 1) "card_data" 127.0.0.1:6379> get card_data // valueの取得
コマンドは大変!クライアントソフトないの!?っという人もいると思います。(自分のことです...)
そういう方はRedis Desktop Manager
を使用してみてはいかがでしょうか。
以下のような感じでredis
を確認することができます。これは便利!
Modelファイルにスキーマ情報を簡単記述「annotate」
業務でruby on rails
に触れて半年目。いろいろな便利なgemに触れてきました。
ということで今回、あったら便利だなぁというgemを紹介いたします。
今回紹介するgemはannotate
です。
導入の仕方はGemfile
に以下1文を記述して$ bundle install
います。
gem "annotate"
annotate
をインストールした後に以下コマンドを入力します。
$ bundle exec annotate
そうすると、Annotated (1): Player
みたいな文言がmodelの分出力され、
app/models/
以下にあるmodelのファイルにスキーマ情報が以下のようにコメントとして追記されます。
# == Schema Information # # Table name: cards # # id :integer not null, primary key # character_id :integer not null # name :string(255) not null
いちいちテーブルの情報を見なくても、このmodelにはこういうカラムが存在しているんだなぁというのが 一目瞭然になります。非常に便利なgemですので是非入れてみてください。
crystal-langのファイルをAtomで開く準備
最近、crystal-lang
に触れています。ruby
のように書けて実行速度が爆速なのはありがたいですね。
さて、crystal-lang
はAtom
エディタで主にプログラミングしているのですが、カラーシンタックスがPlain Text
を選ばれてわざわざruby
に変更するのが面倒くさいと思いました。cr
という拡張子をruby
のカラーシンタックスになるように以下パッケージを導入しました。
設定はメニューバーから[Atom]->[Open Your Config]を選択して以下のように追記をします。
"*": "file-types": cr: "source.ruby" tx: "text.html.basic"
この設定により、cr
がruby
のカラーシンタックスになります。(ついでににtx
をhtml
に設定しています。)
※Atom
はバージョン1.5.3
に書いた記事です。
Unity5.3にしたときのシーン切り替えで暗くなる
Unity5.3
がリリースしてすんなり動くかと思った第2弾。今度はSceneManager.LoadScene
でシーン切り替えを実施した際に、急に画面が暗くなります。
それを解決するためには、以下手順を踏んで設定を変更する。
- メニューバーから
Window
=>Lighting
を選択し、Lightmaps
を3つのタブから選択する。 Auto
のチェックを外して、Build
をクリックする。
この手順を踏むとSceneManager.LoadScene
した際に画面が暗くなりません。情報を提供していただいたクライアントエンジニアさんに感謝。
Unity5.3にしたときのシーンの切り替えで警告文
12月上旬にUnity5.3
がリリースされました。新しい2DツールやJSON
の公式サポート、カスタムコルーチン等、魅力的な機能が
多く追加されたのですぐにアップデートしました。5.2
から5.3
のアップデートなのですんなり動くだろう(根拠なし)と思っていましたが、
以下エラーが発生しました。
"UnityEngine.Application.LoadLevel(int)' is obsolete: `Use SceneManager.LoadScene'".
シーンファイルの切り替えはApplication.LoadLevel([シーンナンバー])
で実施していましたが、なんとこれはもう時代遅れだ!SceneManager.LoadSceneを使えや!というUnityの警告が出力されました。ということで以下のように書き換え。
using UnityEngine.SceneManager;
// Application.LoadLevel([シーンIDまたはシーン名]); SceneManager.LoadScene([シーンIDまたはシーン名]);
これでUnity
に怒られなくなります。