unity study

Unityでサクッとモックを作れるようになることを目指して、基本的なテクニックを抑えていく過程を残すブログのつもりだったけど、今はただ自分のトラブルシューティングメモになってるブログ

Mechanimでアニメーションしながら、SpriteRenderer.enabledをスクリプトで触る際の注意

敵がスプライトアニメーションしていて、やられると点滅する。ということを実装しようとした。
スクリプトからSpriteRendererのenabledをいじることで実現できるはずだったのだが、何故かenabledがfalseにならない。
一時停止して直接Inspectorからenabled=falseにしても、次のフレームではtrueにされてしまう。
同じような点滅を敵以外では実装できているのに何故?
試しにAnimatorを外してみるとうまくいく。

調べてみると敵の持つアニメーションの中に1つだけSpriteRenderer.enabledを触っているものがあった。
試しにそのアニメーションでSpriteRenderer.enabledを使うのをやめてみると、思い通りの結果になった。
これは推測だが、SpriteRenderer.enabledを触るアニメーションが一つでもあると、
その他のアニメーションは暗黙的にSpriteRenderer.enabled=trueとなるキーフレームを持つのと同じ扱いになり、
それがためにenabledをfalseにしても次フレームでtrueに書き換えられていたのではないだろうか。

う〜ん、今回はアニメーション側でSpriteRenderer.enabledを使わないことで対応できたけど、どうしても外せない場合はどうするんだろう?

C#のprotectedの扱いはJavaとちょっと違うんだな

ちょっとハマったのでメモ。
Javaのprotectedと違って、C#のは同一クラスの別インスタンスからアクセスできないみたい。
そういう場合にinternalを使う。
「アクセスは現在のアセンブリに制限されます。」って説明がイミフだったけど、そういうことか。

class Foo
{
    private int m1;
    protected int m2;
    protected internal int m3;
}

class Var : Foo
{
    void CopyFrom(Foo f)
    {
        m1 = f.m1; // これは当然NG
        m2 = f.m2; // NG m2はアクセスできるけど、f.m2はアクセスできない
        m3 = f.m3; // OK
    }
}

Editor拡張が地味に楽しい

ゲーム実行前にあらかじめシーン上にPrefabを並べておきたいことがあって、数が多いし後で変えたくなるから何とかできんかなぁ、とEditor拡張をやってみた。
個数指定してボタンを押すとGameObjectを生成する、みたいな。
触ってみるとなかなかEditor拡張は楽しいな。
便利なUtilityクラスも多いし。
開発効率あげたいところには、ガンガン使っていこう。

Animationで拡縮や移動が反映されない現象

Inspectorで、AnimatorのApplyRootMotionがfalseになっていると反映されない。
OnAnimatorMove()を実装していると、この部分がHandled By Scriptと表示される。
自分の場合だとObservableMonoBehaviourを継承しているコンポーネントがあったので、そのために発生していた。
UniRxをアップデートして、ObservableMonoBehaviourを継承するのをやめて、this.UpdateAsObservable()を使うようにして対応した。docs.unity3d.com

UniRxメモ:n秒後から始まるストリーム

Coroutine使う場合は

yield return new WaitForSeconds(n);

とするような処理を、UniRx使う場合はこんな感じになる。

observable.SkipUntil(Observable.Timer(TimeSpan.FromSeconds(n))

よく使いそうなパターンは、ひと通り書いてみて覚えるのが手っ取り早いんじゃないかと思った。