ぱふの自由帳

週3更新(火・木・日)を目指すUnityブログ。良ければフォローお願いします(`・ω・´)

現在のSceneの再読み込みをスマートなコードで書く

はじめに

現在のSceneをもう一度読み込みたい時ってありますよね。もう一度ステージをプレイさせるためにステージを読み込み直す時とか...。
毎回、SceneManager.LoadScene("自分のシーン名");って書いても良いのですが...自分のSceneを書くのは変だなと思ったので少しスマートに書いてみました(`・ω・´)!

コード

// 現在のScene名を取得する
Scene loadScene = SceneManager.GetActiveScene();
// Sceneの読み直し
SceneManager.LoadScene(loadScene.name);

これで逐一、自分のシーン名を手書きしなくて済みますネ。

おわり

行数は長くなっちゃいますが結構気に入ってる書き方です(`・ω・´)!

初心者の方や熟練者の方を問わずTwitterのフォローお待ちしています...(`・ω・´) ヨロシク!

Scene画面で移動したオブジェクトが自動で中心にくる方法

はじめに

またタイトルだけでは「?」ですね。
というわけで動きを下に示しておきますー。

f:id:PafuOfDuck:20171005165056g:plain

結構役に立ちそうですね!
「こういった場面に使えるよ!」とハッキリ断言できませんが(笑)

やり方

オブジェクトを選択して《shift+F》

はい!とても簡単です(`・ω・´)!やり方の説明終わり!

おまけ

他のオブジェクトを選択しない限り、オブジェクトの選択を解除しても効果は持続しますヨ!

f:id:PafuOfDuck:20171005165542g:plain

おわり

最初に言えよな内容ですが..Macでの動作となるので気をつけてください(´・ω・`。)
Windowsは確かめれておりませぬ。(借りたPCではデフォルトでこの機能がついていたような...いなかったような...

P.S. 小技ネタ書くの楽しい!だって...短いし...(笑)

初心者の方や熟練者の方を問わずTwitterのフォローお待ちしています...(`・ω・´) ヨロシク!

Scene画面でオブジェクトをある単位ずつずらす方法

はじめに

タイトルだけでは「?」が浮かぶ方もいると思いますので...
こういう動きのことでーす。

f:id:PafuOfDuck:20171004183808g:plain

何かを均等に並べる時に便利です。例えば、2DのSpriteを等間隔に並べてマップを作る時に使えたりしますヨ。
ちなみにですが、この移動方法は"Snap"という名前だと思います!(多分。きっと。おそらく。)

ではさっそく使い方をば...

使い方

Ctrl(Macはcommand)を押しながら操作すると
ある単位(初期値は1)ずつずれる

と、まぁ簡単に使用できるので試して見てください ^^。

おまけ

設定画面

間隔を設定する設定画面はEdit > Snap Settingsを選択すれば表示されます。

f:id:PafuOfDuck:20171004190230p:plain

その他

拡大/縮小や回転も同様にある単位ずつ変更できます。特に使い方が思いつきませんが...。

f:id:PafuOfDuck:20171004184659g:plain

おわり

こういった便利機能って他にもあるのでちょこちょこ記事に出来たらなーと思っています。「こういう機能知ってる?」というコメントやDMもどしどし受け付けてますので是非教えてくださいまし(`・ω・´)v

初心者の方や熟練者の方を問わずTwitterのフォローお待ちしています...(`・ω・´) ヨロシク!

Animationを使う時の注意 -Root Motion編-

はじめに

Root Motionを使う場面は様々あると思います。実際にオブジェクトを移動するアニメーションを作成したい場合や、Animatorで動かすオブジェクトをスクリプトでも動かす場合(参考サイトはこちら)等々...
しかし、注意が必要な場面が出てきます。というかハマりました。

では、さっそく見て行きましょう〜。

Root Motionの落とし穴

Root Motionなしパターン

下のGIFを見てください。これはpositionを(-2,0,0)→(2,0,0)に移動するアニメーションを設定しています。

  • Scale(1,1,1)のオブジェクト
    f:id:PafuOfDuck:20171002121407g:plain

  • Scale(0.5,0.5,0.5)のオブジェクト
    f:id:PafuOfDuck:20171002121402g:plain

どちらも同じようにX軸方向に+4だけ移動していることが確認できます。
一応、Animatorの設定については下の画像のようになっています。

f:id:PafuOfDuck:20171002123613p:plain

f:id:PafuOfDuck:20171002121958p:plain

Root Motionありパターン

さて、また下のGIFを見てください。これも同様にpositionを(-2,0,0)→(2,0,0)に移動するアニメーションを設定しています。
しかし、Root Motionを設定している点で異なっています。Root Motionの使い方についてはこちらで少し説明していますのでどうぞ。

  • Scale(1,1,1)のオブジェクト
    f:id:PafuOfDuck:20171002124621g:plain

  • Scale(0.5,0.5,0.5)のオブジェクト
    f:id:PafuOfDuck:20171002124616g:plain

今回はX軸の移動量が異なっていることが確認できると思います。数値で確認するとScale(0.5,0.5,0.5)の方が移動量が半分になっています。これは「Scaleを考慮した移動量に補完されているからかな?」と考えていますが...。真相は闇の中です。

注意点
Root Motionを使用するとAnimtionで設定した数値がオブジェクトのScaleによって変化(補完?)してしまうので注意!!

解決方法?

うーん...これを解決方法としても良いのかどうか分からないのですが二つほど。

  • 補完を考慮した数値をあらかじめ設定する(とてもじゃないが計算が面倒なのでオススメしません)

  • Scaleが(1,1,1)オブジェクトを作成し、Scale(0.5,0.5,0.5)のCubeを子オブジェクトに設定します。そして親オブジェクトにAnimatorを設定します。そうすることで間接的に子オブジェクトを動かします。

おわり

「なんで上手く動かないんじゃー!!」となって調べて見たところRoot Motionが原因でした(´・ω・`。)
解決策がとても微妙なので他の方法をご存知の方がいれば是非教えてください!

初心者の方や熟練者の方を問わずTwitterのフォローお待ちしています...(`・ω・´) ヨロシク!

【unity2017】Animationで設定した値を相対的な値として扱う方法

はじめに

Animtionの使い方は ”unity Animation 使い方” で素晴らしいサイトが沢山ありますのでそちらを参考にしてください!今回はAnimationの小技(?)の話です。

「前置きはいいから、解決方法だ早く教えて!」という方は《解決したいこと》を読み飛ばしてください(`・ω・´)b

解決したいこと

では早速ですが、下の写真の赤枠の箇所をみてくださいー。

f:id:PafuOfDuck:20171001143152p:plain

枠内の値を変更することでアニメーションを作成していきますよね。この値がアタッチされているオブジェクトのTransformを書き換えてくれることでアニメーションとなっているのですが...

f:id:PafuOfDuck:20171001144730p:plain

このままでは大変不便に感じますね。
例えば、原点で(親を持たない)Cubeがジャンプするようなアニメーションを作ったとします。その後、「このCubeを隣にもう一つ並べたい!」と思った時にこのままでは使えません。(Animationで設定した値でTransformを書き換えているので、配置時にずらしていても同じ場所で同じ動きをします。)

問題点
同じAnimation Clipを設定すると同じ場所で同じ動きをするオブジェクトになってしまう

さて、これを解決するためには配置時のTransformを基準としてAnimationで設定した値を適用してくれればOKですね。その方法について説明します。

解決方法

"Root Motion"という機能を使用して問題を解決していきます。

まず、適用したいAnimation Clipを選択してください。選択するとInspectorが以下の画像のようになるので、赤線の箇所をクリックしてください。

f:id:PafuOfDuck:20171001150635p:plain

次に、アニメーション予定のオブジェクトにアタッチされているAnimatorの設定を変更します。赤線の箇所にチェックを入れてください。(画像はチェック後です。)

f:id:PafuOfDuck:20171001151020p:plain

はい。たったこれだけで完了です!
実際にGIFを用意すればちゃんと意図通りに動いてるのをお見せできるのですが、GIFを用意するのが面倒くさ.. 今回は用意できていません(´・ω・`。)

小噺

この機能を知るまで私がどのように実装していたかという話に興味があれば読んでみてください。(笑)

「Transformが書き換わるのかー。ってことは親を設定してあげるとLocalPositionが書き換わるってことでしょ?じゃあ親を設定してあげれば(無駄なオブジェクトにはなるけど)実装できるじゃん。」ってな訳で...ほいっとな。

f:id:PafuOfDuck:20171001152325p:plain

こうすることで"JumpCubeSet"の位置を動かせばその位置を基準としてアニメーションしてくれます。めでたしめでたし...?

・・・。

はい。これはAnimationの遷移に対応するのが面倒でした。(おかげで"Root Motion"に辿り着けたのですがネ。)

おわり

"Root Motion"を上手く使えば、Animationだけで移動させることも簡単です!是非お試しをば(`・ω・´)b

ブログの書き方を試行錯誤して、分かりやすい構成を模索中です...。今回も迷走している気がしますが優しく見守ってください(´・ω・`。)

初心者の方や熟練者の方を問わずTwitterのフォローお待ちしています...(`・ω・´) ヨロシク!

Actionを使おうとして「あれ?エラー...?」となった話

はじめに

現環境でもActionを使うのが良いのか分かりませんが、Action使ってみたい!と思った時に少しだけ時間を無駄にしたのでメモ。

メイン

「コルーチンとAction組み合わせてみよう!Qiitaに良き記事があるね。良きかな良きかな。」カキカキ

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Hoge : MonoBehaviour {

    void Start(){
        //n秒後に実行する
        StartCoroutine (DelayMethod (n, () => {
            Debug.Log ("Delay call");
        }));
    }

    private IEnumerator DelayMethod(float waitTime, Action action){
        yield return new WaitForSeconds (waitTime);
        action ();
    }
}

「さて実行...あれ?Actionが存在しないですよエラーが出てる(´・ω・`)

解決方法

using System;

これを忘れずにつけときましょう。
ちなみにFuncを使用する際にも必要だそうです。

おわり

usingが足りないんだろうなぁと思っていたにもかかわらず【unity Action 使い方】とググってしまいました。(笑)
今調べてみると【unity Action using】で1発で出ますね...(´・ω・`。)ググり力が足りないZE...

初心者の方や熟練者の方を問わずTwitterのフォローお待ちしています...(`・ω・´) ヨロシク!

Admobの動画広告を連続で表示したい

はじめに

「Admobの動画広告を何度も表示させたい!でも、公式サイトのサンプルのままじゃ1回しか読み込めない…」ということがあったのでメモついでの記事になります。
もっとスマートな方法があると思いますが…ネ

実装

細かいAdmobの使用方法は以下のサイトを参考にしてください。

さて、色々説明する前にコードを貼っときます!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GoogleMobileAds.Api;


public class Admob : MonoBehaviour {

    private RewardBasedVideoAd rewardBasedVideo;

    private string videoId;

    void Start(){
        RequestRewardBasedVideo ();
    }

    // 動画広告リクエスト(最初に呼びます)
    private void RequestRewardBasedVideo() {

        #if UNITY_ANDROID
        videoId = "ca-app-pub-3940256099942544/5224354917";
        #elif UNITY_IPHONE
        videoId = "ca-app-pub-3940256099942544/1712485313";
        #else
        videoId = "unexpected_platform";
        #endif

        rewardBasedVideo = RewardBasedVideoAd.Instance;
        AdRequest request = new AdRequest.Builder().Build();
        rewardBasedVideo.LoadAd(request, videoId);
        rewardBasedVideo.OnAdRewarded += HandleRewardBasedVideoRewarded;
    }

    // 動画広告が最後まで視聴されたら呼び出される
    void HandleRewardBasedVideoRewarded(object sender, System.EventArgs e){
        // 動画広告再取得
        StartCoroutine ("RequestRewardBasedVideoAgain");
    }

    // 動画広告再取得関数
    IEnumerator RequestRewardBasedVideoAgain(){
        while (true){
            // 適当な時間を設定します(失敗時の再取得時間)
            yield return new WaitForSeconds(10.0f);
    
            // 通信ができない場合は、リロードしない
            if (Application.internetReachability != NetworkReachability.NotReachable){
                rewardBasedVideo = RewardBasedVideoAd.Instance;
                AdRequest request = new AdRequest.Builder().Build();
                rewardBasedVideo.LoadAd(request, videoId);
                break;
            }
        }
    }
}

コードを読むとある程度分かると思うので、軽く流れを説明しておきます。

まず動画広告を流すことが出来るように用意をします。私も詳しくは分からないのですが、この処理をリクエスト処理と呼ぶらしいです。そして、動画広告を最後まで視聴すると動画広告を再取得する関数が呼び出されるようになっています。
工夫点(?)はRequestRewardBasedVideoAgain関数内で動画広告が取得出来なかった際に再取得する処理を行っている点です。なぜか視聴後すぐにリクエスト処理を行うとすると失敗するんですよね…。しかも、リクエスト処理が成功する間隔が一定じゃない気もする…。(原因が分かる方はコメントに書いていただけると助かります!)

!使用する際の注意!
上記のコードは動画が最後まで視聴された場合しか想定していませんが、実際は途中で視聴をキャンセルした場合等も考慮してコードを完成させる必要があります。上記のサイトを参考にイベントハンドラを追加してください。

おわり

同じ処理してるコードまとめないの?恥ずかしくないの?という声が聞こえてきそうなコードですが…そこは目を瞑ってください(´・ω・`。) 良い関数名が思いつかなかったんです…(笑)

なお、「こういう手軽な方法があるよ」や「間違ったこと書いているよ」等ありましたらコメントやtwitterのDMで教えて下さると助かります( ´ ▽ ` )

初心者の方や熟練者の方を問わずTwitterのフォローお待ちしています…(`・ω・´) ヨロシク!

DateTimeを文字列から生成する

はじめに

文字列のセーブは出来るけどDateTime型をセーブでが出来ない!そんな場面に出くわしたのでDateTime→文字列や文字列→DateTimeに変換する方法をメモして置きます。

変換方法

DateTime→文字列

ToString()を使用するだけですー。下のような感じで…。

DateTime.Now.ToString ();

文字列→DateTime

DateTime.Parse(String s)という便利な関数があります。文字列を渡すとDateTime型に変換してくれます。なお、適当な文字列を渡すとどうなるかは調べていません><。

String time = DateTime.Now.ToString ();
Debug.Log(DateTime.Parse(time).GetType());

//出力結果
System.DateTime

おわり

DateTime.Parse(String s)という便利な関数の存在を知らずに少し手間取りました。ちゃんと、「変換関数ぐらいあるのでは?」とリファレンスを読むべきでした(´・ω・`。)

あ。DateTime使うときにusing Systemを忘れずに!では!

初心者の方や熟練者の方を問わずTwitterのフォローお待ちしています…(`・ω・´) ヨロシク!

型変換メソッドのConvert.ToXXX() を使用する

はじめに

型変換であるConvert.ToInt32()Convert.ToBoolean()を使用する時に少しエラーを出してしまったので使い方メモです

使い方

using System;

を追加してからConvert.ToXXX()を実装しましょう。

おわり

ググればすぐ見つかりますが、とりあえずメモしときました。

初心者の方や熟練者の方を問わずTwitterのフォローお待ちしています…(`・ω・´) ヨロシク!

Prefab変更したのにPrefabから生成したオブジェクトが変更されない件

はじめに

「Prefabを変更することで一括で値を変えて…っと。あれ?反映されない…(´・ω・`)」という実話を元に作成しました(笑
理解してしまえば当たり前のことだったので、内容は入門者向けです。

注意:D&Dという用語を多用しますが、ドラッグ&ドロップのつもりです

メイン

現象説明

冒頭だけではいまいちどういう話をしているか分からないと思うので、簡単に説明します。

  1. Prefabを元にD&DでオブジェクトAを生成
  2. オブジェクトAをもぞもぞ弄る
  3. オブジェクトAをコピーしてオブジェクトB~Zを作成
  4. オブジェクトA~Zの値を一括変更したいのでPrefabを変更
  5. 「あれ。値変わらないんだけど」

という感じの現象です。2のもぞもぞ弄る際にどれだけもぞもぞ弄るかで結果が変わってきます。

Let's確認

文字よりも実際に画像で見た方がわかりやすと思うので画像を交えて説明します。

BoxというPrefabを用意しました。BoxのTransformは以下の図のようになっています。

f:id:PafuOfDuck:20170908204705p:plain

例1

D&Dでもして、このBoxを元に適当な場所にAという(インスタンス)オブジェクトを生成します。AのTransformは以下の図のようになっています。

f:id:PafuOfDuck:20170908205135p:plain

AからコピーであるBを作成しました。BのTransformは以下の図のようになっています。

f:id:PafuOfDuck:20170908205154p:plain

実際のオブジェクトを見ると下図のように見えます。

f:id:PafuOfDuck:20170908205426p:plain

ここでPrefabのPositionとRotation、Scaleを変更するとどうなると思いますか?
実は変更されるのはScaleのみなのです。

〈適当に弄った後の図〉 f:id:PafuOfDuck:20170908205826p:plain

ここで、一つ知識の紹介です。
《Prefabの値から一度でも修正した値はPrefabを変更しても自動で適用されない》
当たり前と言えば当たり前ですね。Prefabに従い続けるのであれば位置の修正も出来ませんよね。というわけで、D&Dした瞬間に修正されるPositionは変更が適用されなかったのです。
逆に修正を加えていないScaleは変更が適用されました。

あれ?Rotationは?と思った方。そうです。
《RotationもD&Dの際に修正されたものとして扱われる》
これ知らなかった方もいるんじゃないでしょうか?(私のように..orz

例2

例1と同様にD&Dでもして、Boxを元に適当な場所にAという(インスタンス)オブジェクトを生成します。そして、Scaleを弄ります。AのTransformは以下の図のようになっています。

f:id:PafuOfDuck:20170908211106p:plain

Scaleを弄った後のAからコピーであるBを作成しました。
実際のオブジェクトを見ると下図のように見えます。

f:id:PafuOfDuck:20170908211048p:plain

ここでPrefabのScaleを変更するとどうなると思いますか?AはScaleを修正してしまっているので変更は適用されませんよね?Bはどうでしょうか?
以下の図で見てみましょう。

f:id:PafuOfDuck:20170908211852p:plain

はい。何も変わりませんね。そもそも変更前、PrefabのScaleが(1, 1, 1)だったのにBは(1, 0.1, 1)というように既に修正された値になってます。なので、変更はAと同じく適用されません。

まとめる

例1&2から分かったことは以下の事柄です!

  • Prefabの値から一度でも修正した値はPrefabを変更しても自動で適用されない
  • RotationはD&Dで生成の際に(値が同じでも)値を修正したものとして扱われる
  • そもそもPositionとRotationは常にPrefabから変更できない
  • 値を修正したオブジェクトから複製されるオブジェクトも値を修正したオブジェクトとして扱われる
  • よく見ると、修正した値の変数名が太字になっている

例1&2では挙げていませんが、Inspectorで設定したpublic変数の値も同様の扱いを受けるので気にかけておきましょう。

解決方法は?

私が考えているのは"オブジェクトからオブジェクトを複製する前に必ずApply押そうね!じゃないとPrefabで一括変更しようとした時に痛い目見るよ!”というぐらいです。Apply押せばPrefabが更新されるので基本的にうまくいくはずです…きっと…。
他に良い方法があれば是非教えてください。

おしまい

長くてすいません。私も長い文章書くの面倒なので分かりやすいサイトになるようにもっと簡単に説明できるようになりたいものです。

なお、「こういう手軽な方法があるよ」や「間違ったこと書いているよ」等ありましたらコメントやtwitterのDMで教えて下さると助かります( ´ ▽ ` )

初心者の方や熟練者の方を問わずTwitterのフォローお待ちしています…(`・ω・´) ヨロシク!