20200404のUnityに関する記事は8件です。

[Unity] LineRenderer の頂点数を指定する際に旧型式と怒られた話

こんにちは。
今回はUnityで開発中に少しつまずいた事を紹介しようと思います。
とりあえず実装したかったのは、ただ線を描写したかったのです。しかし、Unityのバージョンアップの際にどうやら頂点数の指定方法に変更があったみたい。とりあえずどう変更されたのかを最初に書いていきます。

変更された構文

はい。見出し通り構文が変更されていたみたいです。下に比較して書いていきます。

バージョン 構文     例文
ver5.4以前 SetVertexCount([int]); Line.SetVertexCount(2);
ver5.5 numPositions = [int]; Line.numPositions = 2;
ver5.6以降 positionCount = [int]; Line.positionCount = 2;

上記の通りバージョン事に少しずつ違います。
何が厄介かというと、エラーではなく警告として怒られます。なので気づかない可能性があります。

例のソースコード

まずは警告されるコードを書いていきます。

sample.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DisplayLine : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        // 線オブジェクト設定
        LineRenderer line = gameObject.GetComponent<LineRenderer>();

        // 線の幅を指定
        line.startWidth = 0.1f;
        line.endWidth = 0.1f;

        // 頂点の数を指定
        line.SetVertexCount(2);

        // 開始位置と終了位置を指定
        line.SetPosition(0, Vector3.zero);
        line.SetPosition(1, new Vector3(1f, 1f, 0f));
    }

    // Update is called once per frame
    void Update()
    {

    }
}

このソースコードでは最新バージョンのUnityでは警告がでます。
頂点の数を指定のコメントアウトされているコードが問題のコードです。
では、警告が来ないソースコードに変更しましょう。

sample.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class addViewLine : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        // 線オブジェクト設定
        LineRenderer line = gameObject.GetComponent<LineRenderer>();

        // 線の幅を指定
        line.startWidth = 0.1f;
        line.endWidth = 0.1f;

        // 頂点の数を指定
        line.positionCount = 2;

        // 開始位置と終了位置を指定
        line.SetPosition(0, Vector3.zero);
        line.SetPosition(1, new Vector3(1f, 1f, 0f));
    }

    // Update is called once per frame
    void Update()
    {

    }
}

このように書くことで警告は消えます。

最後に

今回、このような事態がおきてしまった理由は筆者が参考にした資料(ググった)内のソースコードの書き方のバージョンが以前のものであったことです。実際、開発をしていく上でこんなの日常茶飯事なので警告がでたことにそんなにひるまなくてもいいと思いますが、言語の仕様変更に対しては敏感である必要があると改めて感じることができました。いい勉強になりました。

ついでになんですが、筆者は大学生です。はい。バイトでエンジニアしてます。
インスタでは情報発信や記事の投稿通知、役立つ情報、日常を垂れ流したりしてますのでよかったらフォローしてください。多分フォロー返します。沢山の方と繋がれたらなとか思っています。
アカウント→taaa_kundayo

では、記事は以上になります。
ありがとうございました!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity LineRenderer の頂点数を指定する際に旧型式と怒られた話

こんにちは。
今回はUnityで開発中に少しつまずいた事を紹介しようと思います。
とりあえず実装したかったのは、ただ線を描写したかったのです。しかし、Unityのバージョンアップの際にどうやら頂点数の指定方法に変更があったみたい。とりあえずどう変更されたのかを最初に書いていきます。

変更された構文

はい。見出し通り構文が変更されていたみたいです。下に比較して書いていきます。

バージョン 構文     例文
ver5.4以前 SetVertexCount([int]); Line.SetVertexCount(2);
ver5.5 numPositions = [int]; Line.numPositions = 2;
ver5.6以降 positionCount = [int]; Line.positionCount = 2;

上記の通りバージョン事に少しずつ違います。
何が厄介かというと、エラーではなく警告として怒られます。なので気づかない可能性があります。

例のソースコード

まずは警告されるコードを書いていきます。

sample.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DisplayLine : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        // 線オブジェクト設定
        LineRenderer line = gameObject.GetComponent<LineRenderer>();

        // 線の幅を指定
        line.startWidth = 0.1f;
        line.endWidth = 0.1f;

        // 頂点の数を指定
        line.SetVertexCount(2);

        // 開始位置と終了位置を指定
        line.SetPosition(0, Vector3.zero);
        line.SetPosition(1, new Vector3(1f, 1f, 0f));
    }

    // Update is called once per frame
    void Update()
    {

    }
}

このソースコードでは最新バージョンのUnityでは警告がでます。
頂点の数を指定のコメントアウトされているコードが問題のコードです。
では、警告が来ないソースコードに変更しましょう。

sample.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class addViewLine : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        // 線オブジェクト設定
        LineRenderer line = gameObject.GetComponent<LineRenderer>();

        // 線の幅を指定
        line.startWidth = 0.1f;
        line.endWidth = 0.1f;

        // 頂点の数を指定
        line.positionCount = 2;

        // 開始位置と終了位置を指定
        line.SetPosition(0, Vector3.zero);
        line.SetPosition(1, new Vector3(1f, 1f, 0f));
    }

    // Update is called once per frame
    void Update()
    {

    }
}

このように書くことで警告は消えます。

最後に

今回、このような事態がおきてしまった理由は筆者が参考にした資料(ググった)内のソースコードの書き方のバージョンが以前のものであったことです。実際、開発をしていく上でこんなの日常茶飯事なので警告がでたことにそんなにひるまなくてもいいと思いますが、言語の仕様変更に対しては敏感である必要があると改めて感じることができました。いい勉強になりました。

ついでになんですが、筆者は大学生です。はい。バイトでエンジニアしてます。
インスタでは情報発信や記事の投稿通知、役立つ情報、日常を垂れ流したりしてますのでよかったらフォローしてください。多分フォロー返します。沢山の方と繋がれたらなとか思っています。
アカウント→taaa_kundayo
URL:https://www.instagram.com/p/B-j3-RJjPWJ/?igshid=poq7k5z6eo3n

では、記事は以上になります。
ありがとうございました!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Animation Rigging で 握手モーションをろくろ回しモーションに作り変える

Unityの公式動画でプロシージャルモーションを作る動画が配信されていたので試してみました。
gif_animation_001.gif

右下が元のアニメーション、中央が新しく作ったモーションになります。
腰にMuluti-Parent Constraintを、
両手にTwo Bone IK Constraintを使用しました。
ろくろアニメーション部分は、ベースとなるろくろピボットオブジェクト上に手のコントロールポイントピボットオブジェクトを置き、ろくろピボットオブジェクトをY,Zで適当に回しています。
gif_animation_002.gif
手の部分にも元のアニメーションを若干残すため、Weightを1より小さくしました。
2020-04-03_195646.png

動画の通りに両手のコントロールポイントを作成し、それをそのままろくろピボットオブジェクト上にのせてみたのですが、それではコントロールポイントがついてきてくれなかったため、ろくろピボットオブジェクトにスクリプトをアタッチし、手のコントロールポイントをピボットオブジェクトに追随させるようにしました。

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

namespace RokuroHand
{
    [System.Serializable]
    public class RokuroHandInfo{
        public Transform pivotTr;
        public Transform targetTr;
        public bool disablePosition;
    };

    public class RokuroHandCtrl : MonoBehaviour
    {
        [SerializeField] AnimationCurve m_acY=null;
        [SerializeField] AnimationCurve m_acZ = null;
        [SerializeField] RokuroHandInfo[] m_infoArr=null;
        float m_timer;

        // Start is called before the first frame update
        void Start()
        {
            m_timer = 0f;
        }

        // Update is called once per frame
        void Update()
        {
            m_timer += Time.deltaTime;
            float ty = m_acY.Evaluate((m_timer * 0.25f) %1f);
            float tz = m_acZ.Evaluate((m_timer * 0.33f) % 1f);
            transform.rotation = Quaternion.Euler(0f, ty * 200f, tz * 400f);

            foreach (RokuroHandInfo info in m_infoArr){
                if (!info.disablePosition){
                    info.targetTr.position = info.pivotTr.position;
                }
                info.targetTr.rotation = info.pivotTr.rotation;
            }
        }
    }
}

2020-04-03_200147.png

また、ろくろを回す際にIK制御の左腕が体にめり込んでいたのですが、空のオブジェクトを作成しHINTのところに入れ、適当なPositionを入れることでめり込まなくなりました。
2020-04-03_200627.png
2020-04-03_195646.png

他にもいろいろなプロシージャルモーションの例があるので、見てみると楽しいかと思います。
2020-04-03_201335.png
2020-04-03_201541.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コルーチンの書き方がうまくいかずエラーが出てしまいます

Unityを使ってノベルゲームの制作に挑戦しているのですが1文字ずつ表示させるためのコルーチンでエラーが出てしまいます。エラーは
Assets\Scripts\Story\WriteTxt.cs(23,29): error CS0120: An object reference is required for the non-static field, method, or property 'WriteTxt.Timer()'
です。
コルーチン部分をコメント化すると正常に作動するのでたぶんコルーチン部分が間違っていると思うのですがアドバイスをお願いします。
Unityのバージョンは2019.3.71.fです。

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

//文字送りに必要な者たち
using UnityEngine.UI;
using System.Text.RegularExpressions;

public class WriteTxt : MonoBehaviour
{
public static void Write_Txt(int num)
{
//表示中の文字数を示す変数
int msg_count=0;

    //メッセージの初期化
    MnageSt.messageText.text="";

    while(MnageSt.senario[num].Length>msg_count)
    {
        MnageSt.messageText.text+=MnageSt.senario[num][msg_count];
        msg_count++;
        StartCoroutine (Timer());
    }
} 

IEnumerator Timer () {
    yield return new WaitForSeconds (1);
}

}

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

簡単リモートアセット(Unity Addressable Asset System)を試してみた (その2)

前提

やったこと

  • エディタ拡張で、デフォルトグループ内のサブアセットをルートに展開します。
  • Addressable Assets Systemを完全に理解する ~ Addressablesウィンドウから設定する」で紹介されていたスクリプトが最近のバージョンには整合しないようでした(Addressables 1.7.5で確認)ので、書き直しました。
  • なお、アセットがルートになくてもアクセスはできるので、ルートに展開する必然性はありません。
  • また、このスクリプトは、デフォルトグループだけを対象にしています。
Assets/~/Editor/MoveToRoot.cs
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.AddressableAssets;
using UnityEngine;

public static class AddressableAssetsUtil {

    // サブエントリをルートへ展開して空になったフォルダを削除
    [UnityEditor.MenuItem ("Assets/Addressables/MoveSubEntryToRoot")]
    public static void MoveSubEntryToRoot () {
        var entriesCount = 0;
        var assetsCount = 0;
        var settings = AddressableAssetSettingsDefaultObject.Settings;
        var entries = new List<UnityEditor.AddressableAssets.Settings.AddressableAssetEntry>  (settings.DefaultGroup.entries);
        var assets = new List<UnityEditor.AddressableAssets.Settings.AddressableAssetEntry> { };
        foreach (var entry in entries) {
            entry.GatherAllAssets (assets, false, true, true);
            if (assets.Count > 0 && entry.MainAsset.GetType () == typeof (UnityEditor.DefaultAsset)) {
                entriesCount++;
                Debug.Log ($"MoveSubEntryToRoot: entry {entriesCount}: {entry.address}");
                foreach (var asset in assets) {
                    assetsCount++;
                    Debug.Log ($"MoveSubEntryToRoot: asset {assetsCount}: {asset.address}");
                    settings.MoveEntry (asset, entry.parentGroup);
                    if (asset.address.StartsWith ("Assets/")) {
                        asset.address = asset.address.Remove (0, 7);
                    }
                }
                assets.Clear ();
                settings.RemoveAssetEntry (entry.guid);
            }
        }
        AssetDatabase.Refresh (); // アセットを更新
        Debug.Log ($"MoveSubEntryToRoot: done (entries: {entriesCount}, assets: {assetsCount})");
    }

}

公式ドキュメント

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

UnityのSliderで作ったHPバーが、角丸になってしまう時の解決方法

最近Unityを触りはじめて学習をしていたところ、本来長方形で作りたいSliderのHPバーが、なぜか角丸になってしまうという事態に陥り1時間程ハマってしまいました。

Unity初心者だと地味に解決しづらい問題だと思うので、書き残したいと思います。

何故か角丸になるHPゲージ

問題のHPゲージはこちらです。
スクリーンショット 2020-04-04 14.38.28.png
角丸というより、もはや楕円形です...

解決方法

Sliderのコンポーネント「Rect Transform」の拡大/縮小の値を小さくしてあげて、Sliderの幅と高さを大きめに設定してあげることで無事に解決できました。

スクリーンショット 2020-04-04 14.50.39.png
スクリーンショット 2020-04-04 15.02.55.png

早くUnityの使い方に慣れていきたいと思います(´・ω・`)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GitLab Runner で Unity の Android SDK が見つからない場合の対処法

GitLab Runner で Unity の Android SDK が見つからない場合の対処法

症状

GitLab Runner で Unity の Androidアプリのビルド時に、下記のエラーが発生。

DisplayProgressbar: Detecting Android SDK
UnityException: Android SDK not found
Unable to locate Android SDK.

解決法

  • システム環境変数に「ANDROID_SDK_ROOT」を追加。
  • サービス「gitlab-runner」を再起動。

説明

Unity 2018.4.20f1 の Preferences -> External Tools で Android SDK の設定はしているが、GitLab Runner でコマンドラインビルドを実行すると、上記のエラーが発生。
サービス「gitlab-runner」は別のアカウントで Windows 10 にログインしているため、レジストリに保存されている Android SDK の設定は参照されていない模様。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】オンデマンドレンダリングで描画処理負荷を抑える

はじめに

Unity 2019.3からオンデマンドレンダリング(On-demand rendering)なるものが追加されました。1
レンダリングのパフォーマンスには苦労することの多いモバイルアプリ開発などで特に有用そうな機能でしたのでご紹介します。

どういうもの?

ゲームループ(MonoBehaviour.Updateとか)のフレームレートは通常通りに、レンダリングを一定間隔でスキップできる機能です。
normal_rendering.png

ondemand_rendering.png

これの一番の使いどころは(特にモバイル端末での)「レンダリング処理負荷低減」でしょう。
例えばユーザー入力待機画面のような画面の動きが激しくない(=見た目のフレームレートを落としても影響が小さい)場面なら、レンダリングを適度にスキップすることでクオリティそのままに端末の発熱や消費電力を減らすことが期待できます。

また、従来からあるフレームレート調節方法であるApplication.targetFrameRateを変える方法よりも、入力の応答性という点でより良い選択になると考えられます。2
例として、入力がない間はフレームレートを落としておき、入力があったタイミングでフレームレートを上げて応答することを考えた際に下の違いがあります。

target_frame_rate_interaction.png

ondemand_rendering_interaction.png

あとは、シミュレーションや機械学習といったシチュエーションでも望まれていた機能ではないかと思います。
それらは実際はレンダリングを必要としないことがほとんどなので、この機能を活用してレンダリングにリソースを割かないようにすればより早く結果を得られると考えられます。

使用方法

制御はスクリプトから行います。
名前空間UnityEngine.RenderingOnDemandRenderingというクラスに3つのStaticなAPIが用意されています。

OnDemandRendering.renderFrameInterval

私たちが直接変更できる唯一のプロパティであり、これでレンダリングをおこなう間隔を設定します。
例えばこれに3を代入すれば、ゲームループの3フレーム中に1回レンダリングするようになります。(レンダリング更新頻度が1/3)

タッチ入力があるまで20[fps]にしておき、タッチがあったらそこから60[fps]にする例はこんな感じです。

OnDemandRenderingTest.cs
using UnityEngine;
using UnityEngine.Rendering;

public class OnDemandRenderingTest : MonoBehaviour
{
    private void Start()
    {
        QualitySettings.vSyncCount = 0;
        Application.targetFrameRate = 60;

        // 20 (= 60 / 3) fps
        OnDemandRendering.renderFrameInterval = 3;
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            // 60 fps
            OnDemandRendering.renderFrameInterval = 1;
        }
    }
}

OnDemandRendering.effectiveFrameRate

現在の設定から想定されるレンダリングフレームレート値です。
例えばゲームループを60fpsで動かしている端末なら、通常はレンダリングも60fpsですが、renderFrameIntervalを3に設定しているときは20(=60 / 3)が返ってきます。

OnDemandRendering.willCurrentFrameRender

現在のゲームループフレームがレンダリング対象かを返します。

will_current_frame_render.png

これは何に使えるのか…ということですが、レンダリングにリソースを割かなければならないフレームかどうかが判断できるので、「見た目のフレームレートを安定させつつ、高負荷な処理を裏で回す」的なことに使えるっぽいです。
なかなか使う場面は限られそうですが、使い方のイメージとしてはこんな感じでしょうか。

OnDemandRenderingTest2.cs
using UnityEngine;
using UnityEngine.Rendering;

public class OnDemandRenderingTest2 : MonoBehaviour
{
    private void Update()
    {
        if (OnDemandRendering.willCurrentFrameRender)
        {
            // レンダリングするので重い処理はしない
        }
        else
        {
            // レンダリングしてないので重い処理を実行
        }
    }
}

おわりに

今回は特に検証などはしていないですが、上手に使えば高い効果が得られそうです。
モバイルアプリ開発なんかでは積極的に取り入れていきたい機能だと感じました。

参考


  1. オンデマンドは「要求に応じて」の意味。 

  2. そもそもApplicationクラスの値は頻繁に変えることになんか抵抗があります…。 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む