【振り返り】unity1week「つたえる」に参加しました。

2023年3月に開催されたunity1weekに初めて参加してきました。
これまでは1人で1週間ゲームジャムは何度かしたことはあります*1が、このイベント自体には、初参戦です!
今回は祝日もあるし運よくタイミングがあって参加できました。

作成したゲーム

すぐ○されてしまうけど子供にステータスを引き継いでいき、何世代も修行と世代交代を繰り返して種族として強くなっていくゲーム。
最終的にボスを倒してジ・エンド。


▼unityroomで遊べます unityroom.com

振り返り⇒改善 満足度:25%(今まで作った1weekゲーでは一番良い)

【GOOD!】チュートリアルを期限内に入れることができ、(たぶん)ユーザーにもゲームルールが伝わった事
→ゲームの完成度にも関わるのでチュートリアルは今後の1weekゲームでも必ず入れる。
→これを入れ込めたのは良かったが、リリース2h前ぐらいだったので、もっと早めにはしたい。

【GOOD!】毎日19時目途で Twitterに進捗報告(可能な限り動画付き)
→これはやっぱりモチベに良い(なんとか逃げずにいられる)。日だけでなく、時間決めたのも◎

【GOOD!】データ量を増やさなくても遊べる仕様に出来たこと
→ループものにしてデータを増やさなくても遊べるゲームにできたこと && その1回のループがとても短い仕様にできたのもGOOD!

【BAD!】演出が足りてない<優先度:高>
→見本になるものを探してそれをまねる!!!(自分で考えられると思わないこと)

【BAD!】予定していた仕様が期間内に実装しきれない
→納得はいかない事ではあるから書いておくがある意味1週間で区切っているからおきていること。
 期限厳守が大事かどうかは微妙だと思っているので優先度は低め。

【BAD!】バグがある状態でリリースしてしまった(3回目)<優先度:高>
→未来の自分へ:これは一番恥ずいので次やるときはこれを優先して改善するようにしてください
→明らかにデバッグ時間とってない…。 ⇒5日目~バグとり時間を1日最低30分は取る

【BAD!】過去の1weekの記録(ブログや改善事項チェック表を作ってる)を見直してから挑め!
→以前にやっていた1Weekと同じBAD事項があるので見直してから挑むべし!
→予めどういう事を気を付けるとか過去の自分はメモしていたし、過去出来なかったことを改善しようと臨んだ方が価値があるものになる!

【希望】なるべく常にリリースできる状態を維持しつつ開発したい。
→半端なものはその日の内に消す。例えば未実装で押しても何も反応しないボタンとかは基本配置していない状態にしたい。
→リリースの状態がどういった状態であるかも考えるきっかけになれる。
→しかし、ある程度方向性と実装が終わってないと厳しいので、5日目から常にリリースできる状態にする。

【BAD!】生活がめちゃくちゃになった
ちっときつーって思う位にはメンタルが負けた。常に焦ってるけど全然手が動かないみたいな状態に陥った。
終わってないから寝れないけど、疲れたからちょっとごろごろしてる間にコンタクトつけっぱ+コタツで寝ちゃって起きたら最悪だったり。
最後の3hぐらいしかまともに集中できてない…焦ってる割に作業も進んでない。
→24時すぎたらコンタクトだけは取っておく。寝ちゃっても明日のダメージが少ない。

上記はチェック表に追記済み

制作期間 :2023/3/20~3/26(7日間) 21.5h

1日目 2日目 3日目 4日目 5日目 6日目 7日目 合計
1 3.25 0 3 6.75 4 3.5 21.5

素材作成 データ作成 プログラム その他*2 合計
1.75 0 16.5 3.25 21.5

※机に向かって作業している時間。そのため歩きながら考えたりしている企画や構想を練っている時間は含まれません。

1日目

「つたえる」というテーマ、全然思いつかなかったんだけどtwitter見てたら「継承」してくゲーム作ろうとか言ってる人いて、
「なるほど。つたえる→伝える→『伝』が入った言葉で考えたらいいんだ」となり、
自分の持っている能力を子に「伝承」していく…「俺屍」っぽいゲーム作ろうという方向に決まりました。

(間に合わず結局実装できなかったけど)主人公のお嫁さん=パートナー側にもステータスや能力を持たせて、
ステータスが高いパートナーと子供を残した方が有利になるという仕様を考えていたが、
これを人間でやるのがなんか気持ち悪いと感じ、
過去に作った気に入ってる自キャラにすることで自分の中の「気持ち悪さ」が消えたのでこのキャラクターを主役にする事に決まった。

2日目(祝日)

ここからようやくUnityでの作業開始。
いつも新しくゲームを作る時に取り込む自作ライブラリ群があるのだが、これがwebGLで使えないトラブル発生。
結局ライブラリ内の使えるものを抜粋して取り込む形で行くことにしたが、この調査で祝日を使いきってしまった。

3日目

仕事でまあムカつくこととかあってやれなかった。こういう日が1日ぐらいあることも予め考慮しておこう。うん。

4日目

ようやく見せれるものが少しできた。10回行動→ボスの簡易的な流れができた。メンタルが悪い…

5日目

全く考えるの忘れてたボス戦の仕様がようやく決まっておおよそのボス画面を実装した。
大昔にプレイしていた「ディノブリーダー」というゲームのルールをパクる。(実際には記憶違いで本家はもう少し仕様が凝ってた)
スマホ移植を考えているのでこんなカジュアル向けにこんなシンプルな戦闘でもありなんじゃないかと思ってやってみた。

6日目

素材(キャラの画像)を増やして、ホーム画面で出来る訓練と子供のステータスアップ。引き継ぐ仕組みを実装した。

7日目

この日でまとめないといけないので、中途半端な部分を全部閉じていく。
18時まで寝てしまい、18時~21時で投稿するまでの3hはまともに集中して作業できた。

今回作った企画書

この2枚のお絵描き。

本当はやりたかったこと( ..)φ

予定していたが間に合わず実装できなかった仕様や正式にリリースするならやりたいことをメモしとく。

・主人公がなぜボスと戦うのかの最初の演出
・ステータスだけでなくキャラクターには特殊能力を持たせてこれも引き継がせる。ダメージ1.2倍など。
・ボスと戦うまでの日数も可変にして幅を持たせる
・お嫁さんがランダムに家に訪れて、お嫁さんを決めるタイミングもプレイヤーが決めれる。
・お嫁さんにも能力を持たせる。子供が早く生まれる、たくさん生まれる。ダメージ1.2倍等。
・主人公が女の子の場合は、旦那さんを見つける。性別の矛盾を感じさせないように。
・子供が生まれるタイミングに幅を持たせる
・子供がいないままボスに倒されたらゲームオーバーにする
・ボスと戦うまでにやれることを増やす…お家づくりで訓練の内容が変わり、新しい特殊能力を覚えたり
・世代家系図の表示
・親の見た目も引きつぐ。ピンク+青の子は紫、1つ目の子は1つ目。みたいな。
・ボス戦で、闘う以外に能力を使えるようにする。ダメージ1.2倍にする等。
・すらいむの種類や特殊能力を増やしてコンプリート要素にもする
・ボスの数は全部で3体+ラスボス1体。最終的にボスを倒した3人の主人公でラスボスに挑む

今は、ただの連打ゲーになっているから、そこを脱却したい。(かもしれない?まあ、ターゲット層によるな…)

結果発表(2023年4/9 20:00)

unity1weekは結果発表があるので、記録として残しておきます。
結果はランク外(総合と各部門で50位まで発表される)で残念でしたが、
62件も評価を頂けた事はおおきいですし、次はランキングに乗ることを目指そうと思います。

楽しさ:3.6
絵づくり:4
サウンド:3.5
操作性:3.6
世界観:3.8
斬新さ:3.4

*1:www.snoopopo.com

*2:ブログまとめやプロジェクト作成、申請作業等

Addressableのことはじめ的な記事。

最近はResourcesをやめてAddressableを使う現場が増えてきたと自分の身の回りでも感じられるようになってきました。(遅いかな?^^;)
というわけでこの記事ではAddressableの基本をまとめてます。(全く使ったことない人が見るレベルね)

環境:Unity2021.3.3f1(win10)

Addressable何がいいの?

Addressableの登場前は、
パッケージに組み込む(ローカル)アセットはResources等の内部フォルダに置いていて、
パッケージ外(リモート)に置いてDLして使うアセットはアセットバンドルを使う。
というケースが大半だったと思います。

Resourcesはそんなに迷わずお手軽に使っちゃってました*1が、アセットバンドルは仕組みを実装するのが非常に複雑でした。
そんな時に出てきたのがAddressable!

Addressableを使うと、
・リモートでもローカルでもコードを変える必要がない(設定の切り替えだけで済む)
・リモートアセットもアセットバンドルで実装するよりも非常にわかりやすく実装できる。
という恩恵をすぐに得ることができます:)

PackageManagerからインストール

(環境によるかもしれないけど)現在はデフォルトで入っていないので、PackageManagerからインストールする必要があります!

インストールが終わるとすべてのアセットにAddressableを設定する欄↓ができます。

アドレスを登録

Addressableの入力欄にチェックを入れて、任意のアドレスを入力します。

Selectを押すか Window -> Asset Management -> Addressable -> Groups で出てくる「Addressable Group」ウィンドウで
設定されているアドレスとリソースの一覧が表示されます。
上で入力したアセットがあるか確認してみましょう:)
何もしていなければ 「Default Local Group」に入ります。

非同期ロードする

以下のようにしてアドレスを指定してからリソースを取得できます。(以下は画像を取得する例)

using UnityEngine;
using UnityEngine.AddressableAssets; //←これが必要
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UI;

public class TestAddressable : MonoBehaviour
{
    AsyncOperationHandle<Sprite> handle;

    async void Start()
    {
        handle = Addressables.LoadAssetAsync<Sprite>("bg/town_1"); //アドレスを指定してSpriteを取得
        await handle.Task;
        GetComponent<Image>().sprite = handle.Result;
    }

    private void OnDestroy()
    {
        Addressables.Release(handle); //使い終わったら解放してあげる必要あり!
    }
}

注意なのは、Addressableは基本、非同期ロードになることです。
今までResources.LoadAsync を使っていた箇所では、
Addressables.LoadAssetAsyncに単純に置き換えれられると思います。

同期ロードする

上述で基本Addressableは基本、非同期ロードになると言いましたが、同期ロードの仕組みも後から実装されたようです。
AsyncOperationHandle#WaitForCompletion でロードされるまで待機し、戻り値で結果を返してくれます。

using UnityEngine;
using UnityEngine.AddressableAssets; //←これが必要
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UI;

public class TestAddressable : MonoBehaviour
{
    AsyncOperationHandle<Sprite> handle;
    void Start()
    {
        handle = Addressables.LoadAssetAsync<Sprite>("bg/town_1"); //アドレスを指定してSpriteを取得
        GetComponent<Image>().sprite = handle.WaitForCompletion(); //同期ロード
    }

    private void OnDestroy()
    {
        Addressables.Release(handle); //使い終わったら解放してあげる必要あり!
    }
}

実機ビルドする時はアセットもビルドする必要があるけど、自動でやってくれるよ

Androidやios、Window版等パッケージでリソースをロードするには、アセットをビルドする必要があります。
※エディタでもPlay Mode Script を Use Existing Build にしている場合はビルドされたアセットを使うのでアセットのビルドをする必要があるよ!

手動で行う時は「Addressable Group」ウィンドウBuild -> New Build -> Default Build Scriptでアセットのビルドをしてから、
パッケージ(ゲーム本体)のビルドを行います。

(このような記事が多いですが↑)
最新のバージョンでは、自動で行う仕組みが既に実装されていて手動で行うケースはあまりなさそうです。
AddressableAssetSettingsというファイルの Build->Build Addressables on Player Build の項目が、
「Build Addressables content on Player Build」になっていればパッケージのビルドの際に、一緒にアセットバンドルもビルドされます。

ちなみに、「Use grobal Settings (stored in preferences)」になっている場合は、

Prefarences にある Addressables の項目で指定した値が使われます。

*1:正直Unity公式から非推奨という情報もかなり前から出ていたが…

【解像度対応】SafeAreaを跨ぐUIの配置

今回はセーフエリアを跨ぐUIをどう配置すれば、どの端末でもある程度キレイに見えるのかについて考えます。
セーフエリアを跨ぐUIって何?→具体的な例を見ていきましょう↓↓↓ :)

こういったレイアウトで、ノッチのない端末であれば単純にセーフエリア内で左上寄せにすれば問題ないのですが、

ノッチありの端末の場合はどうでしょう。
上で問題なかった状態のままノッチあり端末で見てみると、このように切れてしまうことがあると思います。

ノッチありの端末での期待値はこういう状態です。

引き延ばせる画像ならSliceで対応できる

対象の画像のSpriteEditorでスライスの設定をします。

この画像は横150pxの内の10px分を引き延ばす領域にしたので、width=140pxでぴったり左寄せ(x=0)にするとこのようになります。

どんなにセーフエリア外が広い端末でも問題ないように今度は、width=1000pxにして、xの値を1000-140px=860にすればこのようになります。

この状態でノッチなし端末で見てみても問題なさそうです。

引き延ばせない画像はSliceで対応できない→画像側で対応してもらおう

スライスで出来ない場合は、引き延ばせない画像の場合です。 今度はちょっと柄が入ってしまっているボタン画像を用意しました。

スライスでおなじ設定にしてみるとノッチあり端末で、このように汚くなってしまいます…

というわけで引き延ばせない画像の場合はセーフエリア外の領域分、画像に足します。
どの端末でもある程度カバーできるだけの余裕をもったサイズ用意しましょう。

ImageTypeをSimpleにして、widthは画像のサイズに。左寄せならxは画像サイズ-セーフエリア内に見せたいサイズ にすればOKです。

まとめ

まとめると、SafeAreaを跨ぐUIの解像度対応は、引き延ばせるかどうかで対応方法が変わる。
引き延ばせる画像の場合:Sliceで対応できる。画像側はとくに変更しなくてもいける場合が多い。
引き延ばせない画像の場合:画像側の対応も必須。

【PlayableAPI】アニメーションPlayableの使い方

PlayableAPIを使ってモーション(アニメーション)の再生してみます。
Unity側で用意されているモーションを再生する仕組みには、SimpleAnimationやTimelineやAnimationControllerを使う方法がありますが、
そういった高機能な仕組みでは実装しづらい、またはできない場合に使えそうです。

環境:Unity2021.3.3f1(win10)

モーションを再生する(基本)

モーションを再生するのにはAnimationClipPlayableAnimationPlayableOutputを使います。

using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Animations;

[RequireComponent(typeof(Animator))]
public class TestAnimationPlayableExample : MonoBehaviour
{
    [SerializeField] private AnimationClip animeClip; //予めアタッチしておくこと

    private void Start()
    {
        PlayableGraph _playableGraph = PlayableGraph.Create("Example Playable");

        // モーションを設定
        AnimationClipPlayable clip1Playable = AnimationClipPlayable.Create(_playableGraph, animeClip);
        AnimationPlayableOutput playableOutput 
                = AnimationPlayableOutput.Create(_playableGraph, "Animation", GetComponent<Animator>());
        playableOutput.SetSourcePlayable(clip1Playable);

        _playableGraph.Play();
    }

    private void OnDisable()
    {
        _playableGraph.Destroy();
    }

このスクリプトをAnimatorをアタッチされたゲームオブジェクトにアタッチすればモーションが再生されます。

AnimationPlayableUtilities で簡単に書くこともできる

単純に1つのモーションを再生するなら、AnimationPlayableUtilitiesを使って簡単に書くこともできるようになってた。お手軽!

using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Animations;

[RequireComponent(typeof(Animator))]
public class TestAnimationPlayableExample : MonoBehaviour
{
    private PlayableGraph _playableGraph;
    [SerializeField] private AnimationClip animeClip;

    private void Start()
    {
        Animator animator = GetComponent<Animator>();
        AnimationClipPlayable clip1Playable = AnimationPlayableUtilities.PlayClip(animator, animeClip, out _playableGraph);
    }

    private void OnDisable()
    {
        _playableGraph.Destroy();
    }
}

モーションをブレンドする

ブレンド?

モーションの切り替わりによく使われる仕組みで、
複数のモーションを同時に再生し、その割合(ウェイトと呼ばれることの方が多い)を決めることができる仕組み。
例えば、歩行モーション→走るモーションに切り替わる際に、すぐに切り替えてしまうと不自然な場合が多い。
そこで走るモーションの割合を少しずつ増やしていって、徐々にモーションを切り替えることで自然に見せることができる。


ブレンドするにはAnimationMixerPlayableを使って複数のモーションを登録します。

以下のソースの例は、インスペクタのRangeで2つのモーションの割合を切り替える例です。
AnimationMixerPlayable#SetInputWeight でウェイト設定できます。

AnimationMixerPlayable#ConnectInputの1つ目の引数にいれている数字は、
AnimationMixerPlayable#SetInputWeight の1つ目の引数の数字と対応していて、対象のモーションに対してウェイトを設定します。

using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Animations;

[RequireComponent(typeof(Animator))]
public class TestAnimationPlayableExample : MonoBehaviour
{
    private PlayableGraph _playableGraph;

    [SerializeField] [Range(0, 1)] private float weight;

    AnimationMixerPlayable mixer;

    [SerializeField] private AnimationClip animeClip;
    [SerializeField] private AnimationClip animeClip2;

    private void Start()
    {
        _playableGraph = PlayableGraph.Create("Example Playable");

        AnimationClipPlayable clip1Playable = AnimationClipPlayable.Create(_playableGraph, animeClip);
        AnimationClipPlayable clip2Playable = AnimationClipPlayable.Create(_playableGraph, animeClip2);

        //ブレンド
        mixer = AnimationMixerPlayable.Create(_playableGraph, 2);
        mixer.ConnectInput(0, clip1Playable, 0);
        mixer.ConnectInput(1, clip2Playable, 0);

        AnimationPlayableOutput playableOutput
                 = AnimationPlayableOutput.Create(_playableGraph, "Animation", GetComponent<Animator>());

        //ブレンドしたmixerを設定する
        playableOutput.SetSourcePlayable(mixer);

        _playableGraph.Play();
    }

    private void Update()
    {
        //2つのモーションのブレンド割合を切り替える
        mixer.SetInputWeight(0, weight);
        mixer.SetInputWeight(1, 1 - weight);
    }

    private void OnDisable()
    {
        _playableGraph.Destroy();
    }
}


▼Weightを1にすると静かめの待機モーションで、0にすると激しめ(笑)のモーションに徐々に切り替わる。

▼PlayableGraph Visualizerでみると複数のAnimationClipをMixerしてるのがわかりやすい

レイヤーごとにモーションを設定する

レイヤー?

ブレンドの他にも複数のモーションを同時に再生する仕組みとしてレイヤーがあります。
上半身と下半身でモーションを分けてる場合だったり…
AnimationControllerを使っている人は一発でわかりますが、これ↓のことです。


というわけで、上半身用と下半身用のモーションを用意してみました。


レイヤーの設定するにはAnimationLayerMixerPlayableを使います。ソースはほとんどブレンドと変わらないのでわかりやすいと思います。

using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Animations;

[RequireComponent(typeof(Animator))]
public class TestAnimationPlayableExample : MonoBehaviour
{
    private PlayableGraph _playableGraph;

    [SerializeField] private AnimationClip topAnimeClip;
    [SerializeField] private AnimationClip bottomAnimeClip;

    private void Start()
    {
        _playableGraph = PlayableGraph.Create("Example Playable");

        //レイヤー
        AnimationClipPlayable topClipPlayable = AnimationClipPlayable.Create(_playableGraph, topAnimeClip);
        AnimationClipPlayable bottomClipPlayable = AnimationClipPlayable.Create(_playableGraph, bottomAnimeClip);
        AnimationLayerMixerPlayable layerMixer = AnimationLayerMixerPlayable.Create(_playableGraph, 2);
        
        layerMixer.ConnectInput(0, topClipPlayable, 0, 1);//最後の引数はウェイト
        layerMixer.ConnectInput(1, bottomClipPlayable, 0, 1);//最後の引数はウェイト
        AnimationPlayableOutput playableOutput 
                = AnimationPlayableOutput.Create(_playableGraph, "Animation", GetComponent<Animator>());
        playableOutput.SetSourcePlayable(layerMixer);

        _playableGraph.Play();
    }

    private void OnDisable()
    {
        _playableGraph.Destroy();
    }
}


▼結果:こんな風に両方のモーションが再生されます

▼PlayableGraph Visualizerでみると複数のAnimationClipをLayerMixerしてるのがわかる

関連記事

www.snoopopo.com

【PlayableAPI】カスタム(User)Playableの作り方

2023年現在、Unity側が用意しているPlayable APIには
アニメーションとAudioを再生するAPI(クラス群)が用意されており、これに加えて、
自分でPlayable APIの機構を使って何かを再生したい場合にカスタムするためのAPIが用意されている。 *1

この記事では、このカスタム(User)Playableの作り方をまとめました。

環境:Unity2021.3.3f1(win10)

PlayableBehaviourを継承したクラスを作成する

まずカスタムPlayableを作成するためにはPlayableBehaviourを継承したクラスを作ります。
このクラスには実際にPlayableで行いたい処理を書きます。

必要に応じて各メソッドをoverrideして行いたい処理を実装しよう。
よく使われれるのは以下の3つのメソッドです。

public class TestPlayableBehaviour : PlayableBehaviour
{
    public override void OnBehaviourPlay(Playable playable, FrameData info)
    {
        //開始時に一度だけ呼ばれる
    }

    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
        //このPlayableを実行している間、毎フレーム呼ばれる
    }

    public override void OnBehaviourPause(Playable playable, FrameData info)
    {
        //このPlayableが終了した時に1度だけ呼ばれる
    }
}

Playableには処理を実行している時間*2を設定でき(やり方は後術)、
各メソッドのパラメータで渡ってくるPlayableクラスのGetDurationでこの値を取得することができます。

またこのPlayableを開始してからの時間*3Playable#GetTimeで取得できます。


これを基本にここではImageの透過を調整してフェードインするPlayableを作ってみます。

public class FadePlayableBehaviour : PlayableBehaviour
{
    public Image fadeLayer;

    public override void OnBehaviourPlay(Playable playable, FrameData info)
    {
        this.fadeLayer.color = new Color(0, 0, 0, 1); //初期化:はじめは真っ暗に
    }

    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
        //全体時間÷実行時間で徐々に透過
        double alpha = playable.GetTime() / playable.GetDuration();
        this.fadeLayer.color = new Color(0, 0, 0, (float)1f - alpha);
    }

    public override void OnBehaviourPause(Playable playable, FrameData info)
    {
        //ProcessFrameで必ずアルファ値が0になることは保証されないので最後に必ず完全に透過
        this.fadeLayer.color = new Color(0, 0, 0, 0); 
    }
}

注意したいのは、OnBehaviourPauseで必ず終了処理を実装するということです。
ProcessFrameは毎フレーム呼ばれると書きましたが、仮に処理落ちした場合は
アルファ値が半端な状態でPlayableが終わってしまいますし、1度も呼ばれない可能性もあります。

作成したPlayableを実行する

作成したPlayableを実行するには
ScriptPlayableScriptPlayableOutputを使って、PlayableGraphに登録します。

   protected override void DoExecute()
    {
        //PlayableGraph を生成
        PlayableGraph playableGraph = PlayableGraph.Create("Example Playable");

        //ScriptPlayableを使って、自作したカスタムPlayableを生成
        ScriptPlayable<FadePlayableBehaviour > fadePlayable = 
                ScriptPlayable<FadePlayableBehaviour >.Create(playableGraph , 0);

        //ScriptPlayableOutputへ登録
        ScriptPlayableOutput output = ScriptPlayableOutput.Create(_playableGraph, "fader");
        output.SetSourcePlayable(fadePlayable);

        //カスタムPlayableに渡したい情報がある場合はこんな風に書けるよ
        fadePlayable.GetBehaviour().fadeLayer = fadeLayer; //この例ではフェード用のImage

        //実行時間を設定
        fadePlayable.SetDuration(2f); //この例では2秒かけてフェードする

        //実行!
        playableGraph.Play();
    }

ポイントは、ScriptPlayable<カスタムPlayable>#Createで作成すること
ScriptPlayable.GetBehaviourでカスタムPlayableが取得できるので外部から渡す情報があれば渡せることです。

またカスタムPlayableに限った話ではありませんが、
ScriptPlayable.SetDurationで実行時間を設定することができます。

*1:docs.unity3d.com

*2:アニメーションならアニメーションしている時間

*3:deltaTimeでもゲームを開始してからの時間でもないので注意

Androidビルドで「Android SDK is missing required platform API」エラー出た時の対処法

起きた事象

普段使っているPCではないPCで、
androidでビルドしようとしたら以下のエラ―出てビルドできなかったのでメモ。

一番左の「Update Android SDK」を押す!これで解決する人はおしまい。


対処法

「Update Android SDK」おしたら、以下のエラーがUnityのコンソールに吐き出された。
AndroidSDKのUpdateもうまく行かなかったらしい。
その理由が「JAVA_HOMEがなく、javaのPathが通ってないよ 」とエラーが出てる。

Exception: Unable to install additional SDK platform. Please run the SDK Manager manually to make sure you have the latest set of tools and the required platforms installed. 
C:\Program Files\Unity\Hub\Editor\2020.3.35f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\tools\bin\sdkmanager.bat "platforms;android-33", exit code 1
Powershell non elevated output:

Arguments are "C:\Program Files\Unity\Hub\Editor\2020.3.35f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\tools\bin\sdkmanager.bat" "platforms;android-33" 
�x��: WARNING: Administrative privileges required
Command finished with exit code: 1

Powershell elevated output:
<psElevated-null>
Batch output:


ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

①JDKのインストールをしているか確認

Unity Hub を起動します。
Installs から 使っているUnityの歯車をクリックして「Add modules」を開きます。

「Android Build Support」の「Android SDK & NDK Tool」、「OpenJDK」がインストールされているかを確認します。
されてなかったらしよう。

②Unity で SDK の設定がされているか確認

Edit -> External Tools の Android の設定項目の各パスが設定されていることを確認。

されていない場合は、設定します。(普通は自動でされている)
既にJDKがインストールされているので、windowsなら以下あたりにインストールされているはず。

【Unit Hub のインストールパス】\Unity\Hub\Editor\【使っているUnityのバージョン】\Editor\Data\PlaybackEngines\AndroidPlayer\

③JAVA_HOME,Path の設定をする

環境変数の設定をします。

win10なら以下を参照。 qiita.com

JAVA_HOME・・・上述した②で設定した「JDK Installs with Unity」に設定したパスを設定
・Path・・・%JAVA_HOME%\bin を追加

コマンドプロンプト等で、set JAVA_HOME で設定したパスが表示されれば、正常に設定されてます。


ここまでやったらandroidビルドできるようになると思われる。
ちなみにAndroid Studio を別途インストールしたりする必要は今現在はないです。
(一時そういう時代があった気がする)

【Live2D入門②】Live2Dで作られたモーションをUnityで再生する

▼前回の続き。引き続きサンプルデータとしてマークくん「mark_free_jp」を使います。 www.snoopopo.com


Live2D Cudisum エディタ をDL

今回からLive2D Cudisum エディタ側も使っていくので、以下からダウンロードしておく。

www.live2d.com


モーションファイルを追加

サンプルの「mark_free_jp」の中(mark_free_jp\runtime\motion)にモーションファイル(json)があるので、Unityにインポートしておきます。
無事インポートが終わると自動でアニメーションClipのファイルが作成されます。

サンプルでは「mark_m01.motion3」~「mark_m06.motion3」まで6つのモーションがあるようです。
このjsonファイルを出力したLive2dのプロジェクトファイルを Live2D Cudisum エディタで見てみるとどういったモーションなのかがわかります。

とりあえずAnimatorでモーションの再生する

モーションの再生方法は色々あるが、とりあえず手っ取り早くAnimatorで再生してみる。

モーションを、前回の記事で作ったゲームオブジェクトにドラックアンドドロップする

Animatorが自動で作られる。

とりあえずこのままなにもせずゲームを再生すればモーションが再生されます。