본문 바로가기
개발/Unity

Unity) 특정 영역 스크린샷 (RectTransform ScreenShot)

by 테샤르 2022. 11. 1.

특정 영역 스크린샷 (RectTransform ScreenShot)

특정 영역에 대해서 스크린샷(Screen Shot)을 찍는 코드이다.

Image를 기반으로 해당 영역을 기준으로 해상도와 사이즈를 계산한다.


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

public class CanvasInImagePosition : MonoBehaviour
{
    [SerializeField]
    private Canvas Canvs = default;
    [SerializeField]
    private CanvasScaler scaler = default;

    [SerializeField]
    private Image Image = default;


    private Camera Camera
    {
        get
        {
            return Camera.main;
        }
    }



    [ContextMenu("계산")]
    public void GetCalcPosition()
    {
        //Debug.Log($" Camera.WorldToViewportPoin: {Camera.WorldToViewportPoint(Image.transform.position)}");
        StartCoroutine(TakeSnapShotAndSave());
            
    }



    //Using a Coroutine instead of normal method
    public IEnumerator TakeSnapShotAndSave()
    {
        //Code will throw error at runtime if this is removed
        yield return new WaitForEndOfFrame();

        //Get the corners of RectTransform rect and store it in a array vector
        Vector3[] corners = new Vector3[4];
        RectTransform _objToScreenshot = Image.GetComponent<RectTransform>();
        _objToScreenshot.GetWorldCorners(corners);


        Vector3[] worldToScreenPointCorners = new Vector3[4];
        for(int i=0;i< corners.Length;i++)
        {
            Vector3 screenPoint = Camera.WorldToScreenPoint(corners[i]);

            /*Vector2 result;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(transform.parent.GetComponent<RectTransform>(), screenPoint, Camera, out result);*/

            //worldToScreenPointCorners[i]= new Vector3(result.x, result.y, 0f);
            worldToScreenPointCorners[i] = screenPoint;
        }

        /*
        RectTransform mCanvas = Canvs.GetComponent<RectTransform>();
        float scalerX = mCanvas.rect.width / (float)Camera.pixelWidth;//(float)Screen.width / 1080f;
        float scalerY = mCanvas.rect.height / (float)Camera.pixelHeight;//(float)Screen.height / 1920f;
        */
        float scalerX = GetScale(Screen.width,Screen.height,scaler.referenceResolution, scaler.matchWidthOrHeight);
        float scalerY = GetScale(Screen.width, Screen.height, scaler.referenceResolution, scaler.matchWidthOrHeight);

        //Remove 100 and you will get error
        int width = (int)(_objToScreenshot.rect.width * scalerX);//((int)corners[3].x - (int)corners[0].x) - 100;
        int height = (int)(_objToScreenshot.rect.height* scalerY);// (int)corners[1].y - (int)corners[0].y;
       /* int width = ((int)worldToScreenPointCorners[3].x - (int)worldToScreenPointCorners[0].x);
        int height =  (int)worldToScreenPointCorners[1].y - (int)worldToScreenPointCorners[0].y;*/

        var startX = worldToScreenPointCorners[0].x;
        var startY = worldToScreenPointCorners[0].y;

        //Make a temporary texture and read pixels from it
        Rect pixelsRect = new Rect(startX, startY, width , height);
        //Rect pixelsRect = new Rect(startX , startY , width , height);
        Texture2D ss = new Texture2D(width, height, TextureFormat.RGB24, false);
        ss.ReadPixels(pixelsRect, 0, 0);
        ss.Apply();

        Debug.Log("Start X : " + startX + " Start Y : " + startY);
        Debug.Log("Screen Width : " + Screen.width + " Screen Height : " +
        Screen.height);
        Debug.Log("Texture Width : " + width + " Texture Height : " + height);


        Debug.Log($"Draw Rect : {pixelsRect}");

        //Save the screenshot to disk
        byte[] byteArray = ss.EncodeToPNG();
        string savePath = Application.persistentDataPath + "/ScreenshotSave.png";
        System.IO.File.WriteAllBytes(savePath, byteArray);
        Debug.Log("Screenshot Path : " + savePath);

        // Destroy texture to avoid memory leaks
        if(Application.isPlayer)
            Destroy(ss);
    }
    private float GetScale(int width, int height, Vector2 scalerReferenceResolution, float scalerMatchWidthOrHeight)
    {
        return Mathf.Pow(width / scalerReferenceResolution.x, 1f - scalerMatchWidthOrHeight) *
               Mathf.Pow(height / scalerReferenceResolution.y, scalerMatchWidthOrHeight);
    }
}

내용

 

반응형

 

 

 

사진

 

★☆

 

반응형

댓글