うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】TextureImporterSetting を変更する

TextureImporter では Inspector で表示されている Texture の設定が全部行えない
そのため TextureImporterSettings を取得して、こちらを変更する

設定できる変数はこちらをご覧ください https://docs.unity3d.com/ja/2018.4/ScriptReference/TextureImporterSettings.html

var path = UnityEditor.AssetDatabase.GetAssetPath(asset);
var importer = UnityEditor.AssetImporter.GetAtPath(path) as UnityEditor.TextureImporter;
 
// TextureImporterSettings を取得するためにインスタンスを作成
var settings = new UnityEditor.TextureImporterSettings();
// Settings をロード
importer.ReadTextureSettings(settings);
  
/// なにかしら settings を変更する処理
  
// Settings を適応
importer.SetTextureSettings(settings);
 
importer.SaveAndReimport();

【Unity】Assertion failed on expression: 'gForceReimports->empty()'

※Unity2019.4.6f1

private void OnValidate()
{
    var path = UnityEditor.AssetDatabase.GetAssetPath(asset);
    var importer = UnityEditor.AssetImporter.GetAtPath(path) as UnityEditor.TextureImporter;
    if (!importer.isReadable)
    {
        importer.isReadable = true;
        importer.SaveAndReimport();
    }
}

上記の処理で下記エラーが発生していました おそらく OnValidate で Reimport するのがよくない?

Assertion failed on expression: 'gForceReimports->empty()'
UnityEditor.AssetImporter:SaveAndReimport()
ImageHitAlpha:OnValidate()
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)

SetDirty と SaveAssets を呼び出す方法に変えたところエラーは解決しました

private void OnValidate()
{
    var path = UnityEditor.AssetDatabase.GetAssetPath(asset);
    var importer = UnityEditor.AssetImporter.GetAtPath(path) as UnityEditor.TextureImporter;
    if (!importer.isReadable)
    {
        UnityEditor.EditorUtility.SetDirty(asset);
        UnityEditor.AssetDatabase.SaveAssets();
    }
}

【Unity】Image の 透明部分を クリックしても Raycast が反応しないようにする

Image の alphaHitTestMinimumThreshold を 0以上にすればタップした際に有効な Alpha の値を変更できる

alphaHitTestMinimumThreshold を 1にすると半透明な部分のタップが無効化される

しかしテクスチャが半透明かどうか判定するために Read/Write Enable を有効にし
SpriteMeshType を FullRect にする必要がある

そのため、有効 Alpha 値を変更したタイミングで テクスチャの設定を変更する処理も行っている

f:id:hacchi_man:20201006220918g:plain

using UnityEngine;
using UnityEngine.UI;
 
[RequireComponent(typeof(Image))]
public class ImageHitAlpha : MonoBehaviour
{
    [SerializeField, HideInInspector]
    private Image _image;
 
    [SerializeField, Range(0f, 1f)]
    private float _threshold = 0f;
 
#if UNITY_EDITOR
 
    private void Reset()
    {
        _image = GetComponent<Image>();
        _image.alphaHitTestMinimumThreshold = _threshold;
    }

    private void OnValidate()
    {
        _image.alphaHitTestMinimumThreshold = _threshold;
 
        if (_image.sprite == null)
            return;
 
        if (_threshold <= 0f)
            return;
 
        // GetPixel をするためにReadWriteが有効である必要がある
        var path = UnityEditor.AssetDatabase.GetAssetPath(_image.sprite);
        var importer = UnityEditor.AssetImporter.GetAtPath(path) as UnityEditor.TextureImporter;
        if (!importer.isReadable)
        {
            importer.isReadable = true;
            UnityEditor.EditorUtility.SetDirty(_image.sprite);
            UnityEditor.AssetDatabase.SaveAssets();
        }
 
        var settings = new UnityEditor.TextureImporterSettings();
        importer.ReadTextureSettings(settings);
        if (settings.spriteMeshType != SpriteMeshType.FullRect)
        {
            settings.spriteMeshType = SpriteMeshType.FullRect;
            importer.SetTextureSettings(settings);
            importer.SaveAndReimport();
        }
    }
 
#endif
}

【Unity】スクリプトからボタンのクリック処理を呼び出してみる

ボタンの実行処理自体は onClick に対して Invoke をすれば呼び出しはできます

Button.onClick.Invoke();

しかしこれはボタンが押せる状態じゃなくても実行することができてしまいます

そのためボタンに Ray が通ればボタンを押せると判定して押す処理を書いてみます



クリック処理は 下記順番で Handler を呼び出すことで可能になります 1. IPointerEnterHandler 2. IPointerDownHandler 3. IPointerClickHandler 4. IPointerUpHandler 5. IPointerExitHandler

/// <summary>
/// ボタンのクリック処理を実行してみる
/// </summary>
private bool ButtonClick(PointerEventData eventData)
{
    // ここは正しい座標等が必要です
    var eventData = new PointerEventData();
 
    var hits = new List<RaycastResult>();
    UnityEngine.EventSystems.EventSystem.current.RaycastAll(eventData, hits);
    if (hits.Length <= 0)
        return false;
     
    // ヒットした中で上位の Interface 継承 オブジェクトを探す
    var gameObject = FindParentIEventSystemObject(hits[0].gameObject);
    if (gameObject == null)
        return false;
     
    return true;
}
 
private GameObject FindParentIEventSystemObject(GameObject gameObject)
{
    var current = gameObject.transform;
    while (current != null)
    {
        var target = current.gameObject.GetComponent<IEventSystemHandler>();
        if (target != null)
            return current.gameObject;
         
        current = current.parent;
    }
    return null;
}
 
/// <summary>
/// ボタンのクリック処理を実行
/// </summary>
private void DoClick(GameObject gameObject, PointerEventData eventData)
{
    ExecuteEvents.Execute<IPointerEnterHandler>(gameObject, eventData, (handler, ev) => handler.OnPointerEnter((PointerEventData)ev));
    ExecuteEvents.Execute<IPointerDownHandler>(gameObject, eventData, (handler, ev) => handler.OnPointerDown((PointerEventData)ev));
    ExecuteEvents.Execute<IPointerClickHandler>(gameObject, eventData, (handler, ev) => handler.OnPointerClick((PointerEventData)ev));
    ExecuteEvents.Execute<IPointerUpHandler>(gameObject, eventData, (handler, ev) => handler.OnPointerUp((PointerEventData)ev));
    ExecuteEvents.Execute<IPointerExitHandler>(gameObject, eventData, (handler, ev) => handler.OnPointerExit((PointerEventData)ev));
}

【Unity】Lego® Tutorial をやってみる

※ Unity 2019.4.6f

Unity Hub の Template に Lego® が追加されたようなので触ってみました

blogs.unity3d.com

テンプレートのインストール

※ Unity Hub v2.4.0以上

Unity Hub の新規作成から テンプレートに Lego® を選択する

f:id:hacchi_man:20201007233155p:plain:w400

年齢入力が必要なので入力する

f:id:hacchi_man:20201007233517p:plain:w400

利用規約を読んで同意する

f:id:hacchi_man:20201007233548p:plain:w400

Unity が開いてチュートリアルを見るかどうかの確認ダイアログが表示されるので

すでに Unity を使ったことがあれば「Explore Your Own」
一度も使ったことがなければ「Start Tutorial」

f:id:hacchi_man:20201007234155p:plain:w400

閉じてしまってもヘッダーメニューからチュートリアルを開くことができます

f:id:hacchi_man:20201007235812p:plain:w200

プレイ

Unity が開いてすぐに Play ボタンを押すことで チュートリアルをプレイすることができます

f:id:hacchi_man:20201008000452p:plain:w400

ゲーム内容は草を集める?

f:id:hacchi_man:20201008001811p:plain:w300

操作

f:id:hacchi_man:20201008001903p:plain:w300

チュートリアル

操作してみるとどうしても進めないところがあり

f:id:hacchi_man:20201008002333p:plain:w300

チュートリアルの「Add a Platform」を見ることで先に進めるようにできます

f:id:hacchi_man:20201008002156p:plain:w250

こんなふうにプレイしていると進行できない部分があって、そこをチュートリアルでどうすれば進めるようになるのかを教えてくれるのだと思います

ブロックの設置

f:id:hacchi_man:20201008002727p:plain

Lego® Tools の BrickBuilding 有効になっている場合

Project Window から ブロックの Prefab を Scene にドラッグすると
下にあるブロックに沿ってブロックを移動することができます

置きたいときはクリックで置けます

f:id:hacchi_man:20201008002608p:plain:w300

その他の チュートリアル

Unity の中でちゃんとハイライトしてくれるので、すごく分かりやすいチュートリアルでした

もし Unity に興味があれば やってみることをおすすめします

ただ英語だったので、英語を読めない場合は分かりづらいのかもしれません

しかし重要な単語は太字で記述してくれているのでちゃんと見ていれば分からないこともないかなと
※下図は Explode の Prefab を Scene 上に設置するチュートリアル

f:id:hacchi_man:20201008003413p:plain:w200


日本語チュートリアルも近日中にでるみたい

RectTransform の Pivot が Center の位置の座標を取得する

public static Vector2 GetCenterPosition(RectTransform rect)
{
    var position = rect.transform.position;
    
    // 真ん中Pivotじゃなければ真ん中を計算する
    if (rect.pivot != new Vector2(0.5f, 0.5f))
    {
        var scaleX = rect.transform.lossyScale.x;
        var scaleY = rect.transform.lossyScale.y;
        var x = rect.rect.width / 2f * scaleX;
        var y = rect.rect.height / 2f * scaleY;
        position.x += Mathf.Lerp(x, -x, rect.pivot.x);
        position.y += Mathf.Lerp(y, -y, rect.pivot.y);
    }
    
    return position;
}

【Unity】演出を Animator じゃなくて Inspector で設定するツール ~3~

https://hacchi-man.hatenablog.com/entry/2020/10/05/220000

の記事の続きです

動きの共通化

動きのパラメータは ScriptableObject として保存することができるので
同じ動きをデータを読み込むことでできます

Animator のようにパスで対象を操作する訳じゃないので、毎回 Targets の登録は必要になってきますが
パスが違うから動かないということないようにしてあります

現在の動きの保存

f:id:hacchi_man:20201005015923p:plain

これを押すと現在のパラメータを保存先を選んで保存することができます

既存の動きの流用

f:id:hacchi_man:20201005020007p:plain

こちらに保存してあるデータをアタッチすることで、動きを流用することができます
同じ ScriptableObject を利用しているため、一つが変更されると全体的に変更されるので注意が必要です

AnimationCurve のカスタマイズ

f:id:hacchi_man:20201005020404p:plain:w300

EaseType を Custom にすると Animation Curve が空になるので好きなパラメータを設定できます
※ 他の場合でも変更はできます

f:id:hacchi_man:20201005020439p:plain

ループ

f:id:hacchi_man:20201005020549p:plain

ループ処理は3種類あります

Loop

最初から最後をずっと繰り返す

PingPong

最初から最後、最後から最初をずっと繰り返す

PingPongOnce

最初から最後、最後から最初を行う