Jump to content
UnitySpain
Sign in to follow this  
Cappa

Ejecutar Align with view desde script

Recommended Posts

Necesito que una cámara instanciada en la escena se alinee con la vista del viewport mediante un script que se ejecuta en editor mode.
Ya existe una acción que logra esto, se encuentra en Gameobject -> Align With View cuando se tiene un objeto de escena seleccionado.

Es posible realizar esa instrucción por script? sino, que alternativas tengo?
 

Align With View

Share this post


Link to post
Share on other sites
34 minutes ago, pioj said:

Ya anduve por ahí, en lo practico no pude lograr nada con lo que se comenta.

Encontré una manera de ejecutar acciones del menú de Unity (https://docs.unity3d.com/ScriptReference/EditorApplication.ExecuteMenuItem.html), pero lamentablemente la acción que necesito depende de una selección manual previa de un objeto de la escena.

Entonces estuve haciendo unas pruebas locas

[MenuItem( "VisualDebugging/Align Camera With Viewport %Q" )]
    public static void AlignCameraWithView()
    {
        Object[] aux = Selection.objects;
        GameObject[] newSelection = new GameObject[1] { FindObjectOfType<Camera>().gameObject };

        Selection.objects = newSelection;
        EditorApplication.ExecuteMenuItem( "GameObject/Align With View" );

        Selection.objects = aux;
    }

Esto funciona, pero no es nada lindo, técnicamente lo que hace ese método es buscar la cámara de la escena y decirle a Unity que se trata de un GameObject seleccionado por el usuario.
Luego ejecuto el mismo "Align With View" de la interfaz del engine, y para no perder la selección que pudo haber hecho el usuario antes de ejecutar este método, restablezco Selection.objects usando la variable auxiliar (aux).

Lo se, es horrible, sigo haciendo pruebas e investigando...

EDIT:

Y por cierto, el objetivo final es que esto se haga en bucle durante un tiempo en editor mode, de manera que la cámara del juego copie lo que el usuario hace con el viewport.

Edited by Cappa

Share this post


Link to post
Share on other sites

Bueno, lo logré pero por alguna razón no funciona de forma fluida, dejo el código fuente por si a alguien le interesa encontrarle la vuelta que le falta.
 

using UnityEditor;
using UnityEngine;

public class ViewportSceneCameraManager: EditorWindow
{
    private static Camera auxiliaryCamera;
    private RenderTexture renderTexture;

    [MenuItem( "Test/Create viewport scene camera" )]
    private static void Init()
    {
        EditorWindow editorWindow = GetWindow( typeof( ViewportSceneCameraManager ) );
        editorWindow.autoRepaintOnSceneChange = true;
        editorWindow.Show();
    }

    public void Awake()
    {
        renderTexture = new RenderTexture( (int)position.width,
            (int)position.height,
            (int)RenderTextureFormat.ARGB32 );
    }

    public void OnEnable()
    {
        CreateAuxiliaryCamera();
    }

    public void Update()
    {
        AlignAuxiliaryCameraWithViewport();
        if ( auxiliaryCamera != null )
        {
            auxiliaryCamera.targetTexture = renderTexture;
            auxiliaryCamera.Render();
            auxiliaryCamera.targetTexture = null;
        }
        if ( renderTexture.width != position.width ||
            renderTexture.height != position.height )
            renderTexture = new RenderTexture( (int)position.width,
                (int)position.height,
                (int)RenderTextureFormat.ARGB32 );
    }

    private void OnGUI()
    {
        if ( renderTexture )
            GUI.DrawTexture( new Rect( 0.0f, 0.0f, position.width, position.height ), renderTexture );
    }

    private static void CreateAuxiliaryCamera()
    {
        GameObject camObj = Instantiate(Camera.main.gameObject);
        camObj.name = "Debug Camera";
        Component[] camComponents = camObj.GetComponents<Component>();
        for ( int i = 0; i < camComponents.Length; i++ )
        {
            if ( camComponents[i].GetType() != typeof( Camera ) && camComponents[i].GetType() != typeof( Transform ) )
            {
                if ( BL.DebugManager.DebugManager.isEditorMode )
                    DestroyImmediate( camComponents[i] );
                else
                    Destroy( camComponents[i] );
            }
        }
        auxiliaryCamera = camObj.GetComponent<Camera>();

        auxiliaryCamera.clearFlags = CameraClearFlags.SolidColor;
        auxiliaryCamera.depth = -100;
    }

    private static void AlignAuxiliaryCameraWithViewport()
    {
        Object[] backupSelections = null;
        if ( Selection.objects != null )
            backupSelections = Selection.objects;
        GameObject[] newSelection = new GameObject[1] { auxiliaryCamera.gameObject };

        Selection.objects = newSelection;
        EditorApplication.ExecuteMenuItem( "GameObject/Align With View" );

        if ( backupSelections == null )
            Selection.objects = new Object[0];
        Selection.objects = backupSelections;
    }

    private void OnDestroy()
    {
        if ( isEditorMode )
            DestroyImmediate( auxiliaryCamera.gameObject );
        else
            Destroy( auxiliaryCamera.gameObject );
    }

    public static bool isEditor => Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.LinuxEditor;
    public static bool isEditorMode => isEditor && !Application.isPlaying;
}

Este script crea una versión modificada de Camara.Main.
Muestra lo que esa cámara ve en una ventana nueva de unity.
Cuando el usuario se "mueve" en el viewport, esta cámara hace exactamente lo mismo.

Ejemplo de utilidad:

A diferencia de lo que se ve en el video, mi sistema tiene su propia cámara y su propia ventana (al cerrar la ventana se borra la cámara auxiliar).

Problemas:

Horrible performance en el Update, todavía no identifico que es exactamente.

 

ViewportSceneCameraManager.cs

Edited by Cappa
Cambio en el script (habia una linea que les iba a tirar error porque se usaba una propiedad externa que ustedes no tienen xD)

Share this post


Link to post
Share on other sites

Alguien que lo probo me esta diciendo que lo ve fluido, entonces cree un proyecto nuevo para probar y funciona bien... no se que estará pasando.

Creo que se puede dar por resuelto el thread.

Share this post


Link to post
Share on other sites
3 hours ago, Cappa said:

Problemas:

Horrible performance en el Update, todavía no identifico que es exactamente.

El método "AlignAuxiliaryCameraWithViewport" está haciendo cosas como:

GameObject[] newSelection = new GameObject[1] { auxiliaryCamera.gameObject };

probablemente estés generando cuadro a cuadro más basura que homero simpson como alcalde :3_grin:, medilo con el profiler pero igual, la funcionalidad que buscás no me suena tan rebuscada. Viendo el video (que todavía no entiendo la utilidad de tener una cámara que haga eso, quizás habría que entender el proceso de fondo) lo que hace probablemente funcione con algún mensaje o delegate estilo "OnSelectionChange" ( https://docs.unity3d.com/ScriptReference/EditorWindow.OnSelectionChange.html )una vez ocurre esto moves la cámara (que previamente catcheaste) a la posición correcta.

Y el AlignObjectWithView (dedicado a la mainCamera) lo unico que hace es algo así:

if( viewportCamera == null )
	viewportCamera = SceneView.GetAllSceneCameras()[0];
		
if( mainCamera == null )
	mainCamera = Camera.main;				
		
mainCamera.transform.position = viewportCamera.transform.position;
mainCamera.transform.rotation = viewportCamera.transform.rotation;

En tiempo real funciona, aunque no recuerdo si lo usé en un OnSceneGUI, Update (con [ExecuteInEditMode] ) o parecido, la verdad ya borré todo xD, osea sería una variante en tiempo real de "AlignObjectWithView", pero no es lo mismo que lo que aparece en el video.

Share this post


Link to post
Share on other sites
On 4/2/2019 at 6:01 PM, lightbug said:

El método "AlignAuxiliaryCameraWithViewport" está haciendo cosas como:


GameObject[] newSelection = new GameObject[1] { auxiliaryCamera.gameObject };

probablemente estés generando cuadro a cuadro más basura que homero simpson como alcalde :3_grin:, medilo con el profiler pero igual, la funcionalidad que buscás no me suena tan rebuscada. Viendo el video (que todavía no entiendo la utilidad de tener una cámara que haga eso, quizás habría que entender el proceso de fondo) lo que hace probablemente funcione con algún mensaje o delegate estilo "OnSelectionChange" ( https://docs.unity3d.com/ScriptReference/EditorWindow.OnSelectionChange.html )una vez ocurre esto moves la cámara (que previamente catcheaste) a la posición correcta.

Y el AlignObjectWithView (dedicado a la mainCamera) lo unico que hace es algo así:


if( viewportCamera == null )
	viewportCamera = SceneView.GetAllSceneCameras()[0];
		
if( mainCamera == null )
	mainCamera = Camera.main;				
		
mainCamera.transform.position = viewportCamera.transform.position;
mainCamera.transform.rotation = viewportCamera.transform.rotation;

En tiempo real funciona, aunque no recuerdo si lo usé en un OnSceneGUI, Update (con [ExecuteInEditMode] ) o parecido, la verdad ya borré todo xD, osea sería una variante en tiempo real de "AlignObjectWithView", pero no es lo mismo que lo que aparece en el video.

Muchas gracias lightbug, en cuanto vuelva a tener tiempo para ponerme con esto reviso y pruebo bien todo lo que me comentaste a ver si puedo prescindir de EditorApplication.ExecuteMenuItem( "GameObject/Align With View" ); ya que utilizar ese método es lo que me quita todo el control que debería tener sobre la funcionalidad.
Igual, como ya coment'e en el mensaje anterior, resulta que me anda perfectamente bien y fluido en la versión que mostré, descubrí que es en un proyecto concretamente que se jode la performance!

Gracias! Saludos!

Cappa

Share this post


Link to post
Share on other sites
Sign in to follow this  

×
×
  • Create New...