Unity Material에 Multiple Sprite를 설정하고 싶어요!

7542 단어 Unity
Material에서 Texture를 설정할 수 있습니다.
묘사 부하를 줄이기 위해 스prite를 TexturePacker 등으로 모으면 내용을 직접 설정할 수 없습니다.UGUI라면 Image에 설치하면 해결되지만, Partical의 Material로 사용하려면 이게 번거롭습니다.
유니티 표준 팩킹 태그도 있지만 팩킹 후 이미지를 압축하고 최적화하는 등 가공하려고 할 때 힘들겠죠?
그래서 방법을 생각해 봤어요.

우선 Multiple Sprite를 Material에 설정해 보세요.


유닛 스피릿 참고서 한번 볼게요.
https://docs.unity3d.com/ja/current/ScriptReference/Sprite.html
rect와texture를 참조할 수 있습니다.
Material에 Sprite를 설정하면 texture로 처리되며 이texture를 설정하세요.
rect에는 이미지의 X 위치, 이미지의 Y 위치, X 크기, Y 크기 매개변수가 저장됩니다.
Texture는 width와 Height를 통해 그림 크기를 얻을 수 있습니다.
https://docs.unity3d.com/ja/current/ScriptReference/Texture.html
이런 느낌으로 Texture에서 Sprite를 줄일 수 있을 것 같아요.
OffsetX = Sprite.rect.x/Sprite.texture.width
OffsetY = Sprite.rect.y/Sprite.texture.height
TilingX = Sprite.rect.width/Sprite.texture.width
TilingY = Sprite.rect.height/Sprite.texture.height

그럼 실제로 해보세요


· Shader의 실장 Partical Addive 사용
MultipleParticleAddtive.shader
Shader "Unlit/MultipleParticleAddtive" {
    Properties {
        _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
        _MainTex ("Particle Texture", 2D) = "white" {}
        _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
    }
    FallBack "Particles/Additive"
    CustomEditor "MultipleParticleAddtiveView"
}
· Material의 Editor 확장
MultipleParticleAddtiveView.cs
using UnityEngine;
using System.Collections;
using UnityEditor;
using UnityEngine.UI;
using System.Linq;

public class MultipleParticleAddtiveView : MaterialEditor
{
    [SerializeField]
    Material material
    {
        get { return (Material)target; }
    }

    private Sprite _sprite;

    public override void OnEnable()
    {
        //テクスチャ情報を確認
        RestoreSprite();        
        base.OnEnable();
    }

    public override void OnInspectorGUI()
    {
        if (isVisible == false) { return; }

        // 入力内容が変更されたかチェック
        EditorGUI.BeginChangeCheck();
        EditorGUILayout.BeginVertical(GUI.skin.box);
        EditorGUILayout.LabelField("MultipleSpriteをMaterialにセットします");
        _sprite =  EditorGUILayout.ObjectField(_sprite,typeof(Sprite),true) as Sprite;
        if (GUILayout.Button("SetTexture"))
        {
            var _rectSprite = SpriteToTextureRect(_sprite);
            material.SetTexture("_MainTex", _sprite.texture);
            material.SetTextureOffset("_MainTex", new Vector2(_rectSprite.x, _rectSprite.y));
            material.SetTextureScale("_MainTex", new Vector2(_rectSprite.width, _rectSprite.height));
        }

        if (GUILayout.Button("ResetParam"))
        {
            material.SetTextureOffset("_MainTex", new Vector2(0f,0f));
            material.SetTextureScale("_MainTex", new Vector2(1f,1f));
        }

        EditorGUILayout.EndVertical();
        GUILayout.Space(20);
        EditorGUILayout.BeginVertical(GUI.skin.box);
        base.OnInspectorGUI();
        EditorGUILayout.EndVertical();
    }

    /// <summary>
    /// MainTexとOffset、ScaleからセットされているSpriteを見つけます
    /// </summary>
    private void RestoreSprite()
    {
        //今 Materialにセットされている画像を所得
        var _setTexObject = material.mainTexture;
        Rect _setTexRect = TexRect(material, _setTexObject);

        //画像のInstanceIDを所得
        var _texObjectID = AssetDatabase.GetAssetPath(_setTexObject.GetInstanceID());
        //InstanceIDからMultipleSpriteかどうかを判定 nullなら単体のSpriteか普通の画像
        Sprite[] _setSprites = AssetDatabase.LoadAllAssetsAtPath(_texObjectID).OfType<Sprite>().ToArray();

        //Spriteではないということで何も処理しない 通常Textureです
        if (_setSprites == null) return;

        if (_setSprites.Length > 1)
        {
            for (var i = 0; i < _setSprites.Length; i++)
            {
                if (_setTexRect == _setSprites[i].rect)
                {
                    _sprite = _setSprites[i];
                }
            }
        }
        else
        {
            //MultipleSpriteではないただのSpriteです
            _sprite = _setSprites[0];
        }
    }

    /// <summary>
    /// OffsetとScaleからRectを生成します
    /// </summary>
    /// <param name="_mat">material</param>
    /// <param name="_tex">texture</param>
    /// <returns></returns>
    private Rect TexRect(Material _mat,Texture _tex)
    {
        Vector2 _offset = _mat.GetTextureOffset("_MainTex");
        Vector2 _Scale = _mat.GetTextureScale("_MainTex");
        return new Rect(
            _offset.x * _tex.width,
            _offset.y * _tex.height,
            _Scale.x * _tex.width,
            _Scale.y * _tex.height);
    }

    /// <summary>
    /// SpriteのRectからTextureのOffsetとScaleを生成します
    /// </summary>
    /// <param name="_sp">Sprite</param>
    /// <returns></returns>
    private Rect SpriteToTextureRect(Sprite _sp)
    {
        var offset_x = _sprite.rect.x / _sprite.texture.width;
        var offset_y = _sprite.rect.y / _sprite.texture.height;
        var tiling_x = _sprite.rect.width / _sprite.texture.width;
        var tiling_y = _sprite.rect.height / _sprite.texture.height;
        return new Rect(offset_x,offset_y,tiling_x,tiling_y);
    }

}

설명


/SetTexture 버튼을 사용하여 Sprite 를 설정합니다.
· ResetParam 버튼, Reset에서 설정한 Tiling 및 Offset
Multiple이 아닌 Sprite와 텍스쳐는Particle Texture에 직접 설정할 수 있습니다.
메이터리얼 제작
· 설정


・MultipleSprite 설정
· 일반적인 Texture 설정


힘든 곳


RestoreSprite()에서 여기(↓)는 힘들었어요.
        //画像のInstanceIDを所得
        var _texObjectID = AssetDatabase.GetAssetPath(_setTexObject.GetInstanceID());
        //InstanceIDからMultipleSpriteかどうかを判定 nullなら単体のSpriteか普通の画像
        Sprite[] _setSprites = AssetDatabase.LoadAllAssetsAtPath(_texObjectID).OfType<Sprite>().ToArray();
Editor 확장 설정의 값을 유지하지 않으면 Material의 Inspector를 닫을 때(MultipleSprite) 정보가 손실됩니다.
이번에는 머티리얼즈, 세리라이즈의 target은 머티리얼즈가 유지한다.
"Multiple Sprite 설정은 무엇입니까?"이런 Sprite 형식의 Object는 Material에 저장되지 않았습니다. 
또 새로 제작된 스크립트테이블 Object 때는 이곳이 독특한 Object가 되지 않았기 때문에 이를 사용한 확장된 모든 머티리얼즈가 정보를 공유한다.
그 결과 멀티플렉스 스프릿을 유지하는 정보를 포기하고 머티리얼에 설정된 Texture에서 인스타그램 ID를 얻었고, Asse Database를 통해 이 인스타그램 ID를 유지하는 Object에 스프릿형ary가 있는지 확인하고 멀티플렉스 스프릿이 있는지 판단과 멀티플렉스 스프릿의 정보 복원을 결정했다.
이 더 좋은 방법을 아는 사람이 있다면 알려주세요.

사이트 축소판 그림

좋은 웹페이지 즐겨찾기