EventSystems を 利用して Texture2D に絵をかけるスクリプト
スクリプト
using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; [RequireComponent(typeof(RawImage))] public class DrawTexture : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler { [SerializeField] private RawImage _rawImage; [SerializeField] private int _radius = 3; private Texture2D _texture; private Vector2 _screenPointMax; private Vector2 _screenPointMin; private Vector2 _lastScreenPosition; private const int DIVIDE = 20; private Dictionary<Vector2Int, float> _dictionary; public event Action<Texture2D> Drawn; #if UNITY_EDITOR private void Reset() { _rawImage = GetComponent<RawImage>(); } #endif private void Start() { var rectTransform = transform as RectTransform; var sizeDelta = rectTransform.sizeDelta; _texture = new Texture2D( (int) sizeDelta.x, (int) sizeDelta.y ); _texture.wrapMode = TextureWrapMode.Clamp; for (var x = 0; x < _texture.width; x++) { for (var y = 0; y < _texture.height; y++) { _texture.SetPixel(x, y, Color.white); } } _texture.Apply(); _rawImage.texture = _texture; var canvas = transform.GetComponentInParent<Canvas>().rootCanvas; var corners = new Vector3[4]; rectTransform.GetWorldCorners(corners); var screenPoints = new Vector3[4]; for (var i = 0; i < corners.Length; i++) { var screenPoint = RectTransformUtility.WorldToScreenPoint(canvas.worldCamera, corners[i]); screenPoints[i] = screenPoint; } _screenPointMax = new Vector2( screenPoints.Max(v => v.x), screenPoints.Max(v => v.y) ); _screenPointMin = new Vector2( screenPoints.Min(v => v.x), screenPoints.Min(v => v.y) ); _dictionary = new Dictionary<Vector2Int, float>(); for (var x = -_radius; x <= _radius; x++) { for (var y = -_radius; y <= _radius; y++) { var position = new Vector2Int(x, y); if (!_dictionary.ContainsKey(position)) { _dictionary.Add(position, 1f); } } } } private void OnDestroy() { Destroy(_texture); } private void Draw(Vector2 screenPosition) { var u = Mathf.InverseLerp(_screenPointMin.x, _screenPointMax.x, screenPosition.x); var v = Mathf.InverseLerp(_screenPointMin.y, _screenPointMax.y, screenPosition.y); var x = (int)Mathf.Lerp(0, _texture.width - 1, u); var y = (int)Mathf.Lerp(0, _texture.height - 1, v); foreach (var pair in _dictionary) { if (x < 0 || y < 0 || x >= _texture.width || y >= _texture.height) continue; _texture.SetPixel(x + pair.Key.x, y + pair.Key.y, Color.black); } } private void CompleteDraw(Vector2 screenPosition) { // 20分割で補間 for (var i = 0; i <= DIVIDE; i++) { var lerpScreenPosition = Vector2.Lerp(_lastScreenPosition, screenPosition, i / (float)DIVIDE); Draw(lerpScreenPosition); } } void IBeginDragHandler.OnBeginDrag(PointerEventData eventData) { Draw(eventData.position); _texture.Apply(); _lastScreenPosition = eventData.position; } void IDragHandler.OnDrag(PointerEventData eventData) { CompleteDraw(eventData.position); _texture.Apply(); _lastScreenPosition = eventData.position; } void IEndDragHandler.OnEndDrag(PointerEventData eventData) { Drawn?.Invoke(_texture); } }