おっしゃるとおり変形後のメッシュの頂点座標は取得できるものの、変形後の画像を取得する機能は用意されていなさそうですね。
自前で別途レンダリングしてやらないといけないかもしれません。レンダリング用のスクリプトとして、下記のようなものを作ってみました。
C#
1using UnityEngine;
2using UnityEngine.Rendering;
3using UnityEngine.U2D.Animation;
4
5public static class SpriteSkinUtility
6{
7 public static Sprite CaptureDeformedSprite(this SpriteSkin spriteSkin)
8 {
9 var renderer = spriteSkin.GetComponent<SpriteRenderer>();
10 if (renderer == null)
11 {
12 Debug.LogError($"{nameof(SpriteRenderer)} not found.");
13 return null;
14 }
15
16 var sourceSprite = renderer.sprite;
17 if (sourceSprite == null)
18 {
19 Debug.LogError($"{nameof(Sprite)} not found.");
20 return null;
21 }
22
23 // 変形されたスプライトのバウンディングボックスを取得する
24 var bounds = renderer.localBounds;
25 var boundingRect = new Rect(bounds.min, bounds.size);
26
27 // テクスチャのサイズを決める
28 var pixelsPerUnit = sourceSprite.pixelsPerUnit;
29 var textureWidth = Mathf.RoundToInt(boundingRect.width * pixelsPerUnit);
30 var textureHeight = Mathf.RoundToInt(boundingRect.height * pixelsPerUnit);
31
32 // スプライト撮影にあたってオブジェクトの配置を操作したいので、後で元に戻すために現在の配置を覚えておく
33 var transform = renderer.transform;
34 var spriteParent = transform.parent;
35 var spriteScale = transform.localScale;
36 transform.GetLocalPositionAndRotation(out var spritePosition, out var spriteRotation);
37
38 // スプライトの配置を調整する
39 // 中心をワールド空間原点に置き、2m四方の正方形になるよう伸縮する
40 var scale = new Vector3(2.0f / boundingRect.width, 2.0f / boundingRect.height, 1.0f);
41 transform.SetParent(null, false);
42 transform.localScale = scale;
43 transform.SetLocalPositionAndRotation(
44 Vector3.Scale(-bounds.min - bounds.extents, scale),
45 Quaternion.identity);
46
47 // レンダーテクスチャ上にスプライトをレンダリングする
48 var currentTarget = RenderTexture.active;
49 var renderTexture = RenderTexture.GetTemporary(textureWidth, textureHeight);
50 RenderTexture.active = renderTexture;
51 var commands = new CommandBuffer();
52 commands.SetViewProjectionMatrices(Matrix4x4.identity, Matrix4x4.identity);
53 commands.DrawRenderer(renderer, renderer.sharedMaterial);
54 Graphics.ExecuteCommandBuffer(commands);
55 commands.Dispose();
56
57 // スプライトの配置を元に戻す
58 transform.SetParent(spriteParent, false);
59 transform.localScale = spriteScale;
60 transform.SetLocalPositionAndRotation(spritePosition, spriteRotation);
61
62 // レンダリング結果をTexture2Dに読み取って、それを使ったスプライトを作る
63 var spriteName = $"{sourceSprite.name} (Captured)";
64 var texture = new Texture2D(textureWidth, textureHeight)
65 {
66 name = spriteName
67 };
68 var textureRect = new Rect(0.0f, 0.0f, textureWidth, textureHeight);
69 texture.ReadPixels(textureRect, 0, 0);
70 texture.Apply();
71 RenderTexture.active = currentTarget;
72 RenderTexture.ReleaseTemporary(renderTexture);
73 var sprite = Sprite.Create(texture, textureRect, -boundingRect.min / boundingRect.size, pixelsPerUnit);
74 sprite.name = spriteName;
75 return sprite;
76 }
77}
使用例として、下記のようにSpriteSkin
を撮影して別のSpriteRenderer
に結果をセットするスクリプトを試してみたところ、
C#
1using UnityEngine;
2using UnityEngine.U2D.Animation;
3
4public class SpriteSetter : MonoBehaviour
5{
6 [SerializeField] private SpriteSkin source;
7 [SerializeField] private SpriteRenderer destination;
8
9 private Sprite capturedSprite;
10
11 private void OnDestroy()
12 {
13 DestroySprite(this.capturedSprite);
14 }
15
16 private void OnGUI()
17 {
18 if ((this.source == null) || (this.destination == null))
19 {
20 return;
21 }
22
23 if (GUILayout.Button("Capture"))
24 {
25 // 古いスプライトを削除し...
26 DestroySprite(this.capturedSprite);
27
28 // SpriteSkinをキャプチャーしたスプライトを作り...
29 this.capturedSprite = this.source.CaptureDeformedSprite();
30
31 // 隣に配置してあるSpriteRendererにセットする
32 this.destination.sprite = this.capturedSprite;
33 }
34 }
35
36 // スプライトが使っているテクスチャも新しく作ったものなので、
37 // スプライトを削除したい時は併せてテクスチャも削除してやるといいでしょう
38 private static void DestroySprite(Sprite sprite)
39 {
40 if (sprite == null)
41 {
42 return;
43 }
44
45 Destroy(sprite.texture);
46 Destroy(sprite);
47 }
48}
下図のようにボタンクリック時のSpriteSkin
(左側)を撮影し、別のSpriteRenderer
(右側)に反映させることができました。

バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2024/02/04 10:13