TAKOYAKING’s blog 一覧

TAKOYAKING’s blog

たこ焼き系

unityのMonobehaviourの名前を変更する手順が以前と異なっている!?

unityのMonobehaviourの名前を変更する手順が以前と異なっているような気がします。

環境

Unity2019.3.9

手順

昔は

  1. UnityEditorからMonobehaviourの名前を変える
  2. テキストエディタで名前を変える

の手順だったのが、

  1. テキストエディタで名前を変える
  2. UnityEditorからMonobehaviourの名前を変える

になり逆になってました。

昔の手順で行ってしまうと、prefabのscriptがMissing状態になります。

感想

自分の記憶違いでしょうか?
Unityでスクリプトのクラス名を変更する手順 - Qiita
この記事によると記憶違いではなさそうです。
これが一時的な挙動なのかわからないので少し様子見です。

Rust: std::process::Commandを使ってvimを立ち上げる

やりたいこと

Rustで作ったスクリプトVimを実行して起動させたい。

失敗したこと

std::process::Command - Rust
ここのサンプルのようにしたらできるのかなと思って、やってみました。

結果は失敗

use std::process::Command;

Command::new("view")
        .arg("takoyaki.sh")
        .spawn()
        .expect("sh command failed to start");

これでも裏で動いてはくれているとは思うけど、vimがターミナル(前面)に現れない。

spawnしたらできませんでした。
子プロセスで実行するとドキュメントに書いてありましたので、子プロセスとして実行しない方法を探す必要があるみたいです。

うまくいった方法

process - Start another program then quit - Stack Overflow
結局、子プロセスにしないプロセスで実行すれば解決できそうっぽかったので、ここを参考にしてみました。

公式Docから
std::os::unix::process::CommandExt - Rust

fn exec(&mut self) -> Error

spawnと違って新しい子プロセスをフォークしない

と書いてあります。


成功(Unix Only)

use std::process::Command;
use std::os::unix::process::CommandExt;

fn view() {
    // Unix Only
    let _ = Command::new("view")
            .arg("takoyaki.sh")
            .exec();
}

いつものようにvimが表示されました。

Unity 2DでPhysics2D.OverlapBoxを使う

Physics2D.OverlapBoxを使おうと思った動機

敵との衝突判定に使おうと思いました。

  • 味方、敵は衝突しない(Layer Collision Matrixでチェックを外す)
  • rigidbodyは重力の影響を受ける。(地面からジャンプ、着地したりできる)

このときに、OnCollisionEnter2Dでは敵と衝突判定してくれないので、自前で衝突判定できるPhysics2D.OverlapBoxを使用しました。

Physics2D.OverlapBoxがうまく動かなかったとき

Physics2D.OverlapBoxを使おうとして初歩的な勘違いをしてしまいました。
Physics.OverlapBoxと勘違いして「なんで動かないんだろう?」というのを永遠とやってしまいました・・・

めっちゃはまった・・・

Rust: ファイル操作後はclose処理はしなくても良い

ファイル操作していた時に、ふとclose処理がないと思ったのですが、

How to close a file? : rust


スコープが終了するとdropが呼ばれ、ファイルが閉じてくれるので他の言語でよくあるcloseメソッドを呼ばなくても良い。

他の言語では

python
withをつけるとwithを抜けると閉じてくれる。

C#
usingをつけるとusingを抜けると閉じてくれる。

上記の言語では、withやusingを使えた時は閉じ忘れがなくなるので便利だなーと思っていましたが、rustではそもそもスコープを抜けると閉じてくれるのは想像以上に便利な気がします。(逆に最初不安になりました!)

Rust: ターボフィッシュ コロンコロン::<>

意味

型を具体的に明示するときに使用します。
呼び方はターボフィッシュ(turbofish)。

左辺に型を書くのか、それともターボフィッシュで書くのが良いか?

左辺に型を書くべきかそれともターボフィッシュを使うのかどちらが良いか?


Type Annotation in Binding vs Turbofish · Issue #90 · rust-dev-tools/fmt-rfcs · GitHub

let query_result = users.load::<User>(&db_connection);
// VS
let users_result: QueryResult<Vec<User>> = user.load(&db_connection);

上と下では上の方が修正しやすいので個人的には良い

確かに、下の例だと全部型を書かないといけないので面倒です。

他の意見では

場合による。collectを使う場合は左辺に明示するのが好み。

もあり、確かに左辺に書いた方が便利な時もあるみたいです。

なぜ必要か

Rustのturbofishを理解する | κeenのHappy Hacκing Blog
ここに書いてありました。
記法がかぶるかららしいです。
小なりと大なりの記法と区別がつかない時があるみたいです。

びっくりした記法

Rustのturbofishを理解する | κeenのHappy Hacκing Blog

let v = Vec::<u32>::new();

ここの例から用いると、vecの初期化で使用するときはこのような記法になりますが、最初これを使用する場面に出会したときに、コロンがいっぱいすぎて、コードを書いていて、正しい記法なのか不安になりました。

感想

ターボフィッシュってなんか響きが良い!

Unity: 着地した時の判定 (2D)

着地したときの判定をどうするかの備忘録。

環境

Unity 2D

OnCollisionEnter2DとOnCollisionExit2D (ちょっと微妙)

  • OnCollisionEnter2D
  • OnCollisionExit2D

を使って、判定してみようと思いました。
基本コンセプトはイベントが呼ばれたときに、Physics2D.OverlapAreaを実行して、自身の下側と地面が衝突していれば着地判定できるので、これでいいかなと思ったのですが、OnCollisionExit2Dの時ではExitされるGameObjectはまだExitされていないので衝突判定で衝突ありと判定されてしまうので、除かないといけません。

全対象をチェックする
Physics2D.OverlapAreaAllを使って、そこからExitされるCollisionを除いてチェックすればOkです。

ただちょっと面倒だなと思ったので微妙かなと思いました。

あとなんでいちいちExitの時にチェックするかというと、地面のブロックが2つ合ってキャラクターが2つのブロックの間の上に立っている場合に、片方のブロックが無くなっても、もう片方のブロックが存在しているので、チェックしないと片方のブロックの上に着地しているのに、着地していない判定になってしまうからです。


調べてみた

初心者がUnity2Dでアクションゲームを作るチュートリアル その3 【接地判定編】 | Go-Nextブログ
この記事がわかりやすくて、Physics2D.OverlapAreaを使って、FixedUpdateで常にチェックしているというコードでした。

こっちの方がシンプルで良いかなと思いました。

感想

FixedUpdateとOnCollision系イベントだと負荷はどのくらい違うかとか気になるところでしたが、とりあえず、プロトタイプの完成を優先したいので、シンプルな方を選択したいです。

Rust: 匿名ライフタイム

structにライフタイム付けたらimpl側でもライフタイムが必要です。
その時のライフタイムの記述は匿名ライフタイムとして記述できるようです。(Rust 2018)

現象

struct SysConfig<'a> {
    dir: String,
    extension: String,
    blacklist: &'a Vec<String>,
}

impl SysConfig {
    fn parse(&self) {

    }
}

上記のようなコードを書くとimpl側でもライフタイムの指定が必要なので、以下のようなエラーがでます。

struct SysConfig<'a>
implicit elided lifetime not allowed here

help: indicate the anonymous lifetime: `<'_>`

解決方法

impl SysConfig<'_> {
    fn parse(&self) {

    }
}

エラ〜メッセージの通り記述してあげれば、直ります。
以下に匿名ライフタイムの記述がありました。(Anonymous Lifetime)
'_, the anonymous lifetime - The Edition Guide

ここによると推測可能なのでライフタイムは_(アンダースコア)で記述できると書いてあります。

もし、明示的に書く場合は以下のような記述になります。

impl<'a> SysConfig<'a> {
    fn parse(&self) {

    }
}

(2個書かないといけない・・・)

感想

ライフタイムの記述を簡略できるイメージで良い?