Unity Spain

Mesa de ayuda => Unity3D => Scripting => Mensaje iniciado por: nokiz en Abril 02, 2019, 06:46:05 PM

Título: [Solucionado] Mover cámara de un punto a otro
Publicado por: nokiz en Abril 02, 2019, 06:46:05 PM
Hola! Mi problema es que quiero mover la cámara de un punto a otro al pulsar una tecla (v).
 
Quiero que el movimiento sea gradual, no que simplemente cambie de un punto a otro en un instante. Tambíen que si se vuelve a pulsar la tecla, vuelva a la primera posición.
 
Todo lo que he investigado me ha llevado a lo mismo, pero lo único que consigo es que la cámara se mueva por un instante pero inmediatamente vuelve a su posición inicial. ¿Qúe estoy haciendo mal?
 
Os dejo el script que le estoy aplicando a la cámara. Muchas gracias!
 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
    // Assigned in inspector
    public Transform firstPersonCamera = null;
    public Transform thirdPersonCamera = null;
 
    private int state = 0;
    private Transform target = null;
    void Update () {
        if (Input.GetButton("LeftStickButton") || Input.GetKeyUp("v")) {
            state = 1;
        }
    }
    void LateUpdate() {
        if (state == 1) {
            if (Vector3.Distance(transform.position, thirdPersonCamera.position) < 0.001f) {
                target = firstPersonCamera;
                transform.position = Vector3.MoveTowards(transform.position, target.position, 2 * Time.deltaTime);
            } else {
                target = thirdPersonCamera;
                transform.position = Vector3.MoveTowards(transform.position, target.position, 2 * Time.deltaTime);
            }
        }
        if (state == 1 && Vector3.Distance(transform.position, target.position) < 0.001f) {
             state = 0;
             target = null;
        }
    }
}

 
Aclaración: firstPersonCamera y thirdPersonCamera son gameObjects vacios en los puntos a los que quiero que se mueva la cámara.
Título: [Solucionado] Mover cámara de un punto a otro
Publicado por: pioj en Abril 02, 2019, 09:24:35 PM
Nunca he usado MoveTowards, así que mi pregunta es "¿Por qué no estás usando LERP?
 
https://docs.unity3d.com/ScriptReference/Vector3.Lerp.html (https://docs.unity3d.com/ScriptReference/Vector3.Lerp.html)
Título: [Solucionado] Mover cámara de un punto a otro
Publicado por: Cappa en Abril 02, 2019, 10:06:48 PM
Yo tampoco he usado MoveTowards. Tengo un script muy similar que hice hace un tiempo, le cambié los nombres y le hice una pequeña adaptación para lo que buscas:

Quizá es demasiado complejo para lo que necesitas ya que hago uso de curvas, pero está bastante claro el tema del Lerp en vectores y cuaterniones.
 

using UnityEngine;
public class PointOfViewHandler: MonoBehaviour
{
    [Header("")]
#pragma warning disable IDE0044 // Add readonly modifier
    [SerializeField] private new Transform camera;
    [Header("References of points of view")]
    // Assigned in inspector
    [SerializeField] private Transform firstPerson = null;
    [SerializeField] private Transform thirdPerson = null;
    public enum PointsOfView
    {
        FIRST_PERSON,
        THIRD_PERSON
    }
    [Header("")]
    [SerializeField] private PointsOfView currentPointOfView = PointsOfView.FIRST_PERSON;
    [Header("Lerp parameters")]
    [SerializeField] private float lerpTime = 25;
    [SerializeField] private AnimationCurve smoothCurve = new AnimationCurve( new Keyframe[]{ new Keyframe( 0, 0 ) , new Keyframe( 1, 1 ) } );
#pragma warning restore IDE0044 // Add readonly modifier
    private float currentLerpTime;
    private Transform target;
    private void Awake()
    {
        GetCamera();
        SetInitialPosition();
    }
    private void GetCamera()
    {
        if ( camera == null )
            try { camera = Camera.main.transform; }
            catch
            {
                try { camera = FindObjectOfType<Camera>().transform; }
                catch { Debug.LogError( "Assign a camera" ); }
            }
        camera.transform.SetParent( transform );
        camera.transform.localPosition = Vector3.zero;
        camera.transform.localRotation = Quaternion.identity;
    }
    private void SetInitialPosition()
    {
        if ( firstPerson == null || thirdPerson == null )
        {
            Debug.LogError( "Point of view not assigned" );
            return;
        }
        switch ( currentPointOfView )
        {
            case PointsOfView.FIRST_PERSON:
                transform.position = firstPerson.position;
                transform.rotation = firstPerson.rotation;
                break;
            case PointsOfView.THIRD_PERSON:
                transform.position = thirdPerson.position;
                transform.rotation = thirdPerson.rotation;
                break;
        }
    }
    private void Update()
    {
        if ( Input.GetKeyDown( KeyCode.V ) )
            ChangePoint();
        if ( target == null ) return;
        if ( Vector3.Distance( transform.position, target.position ) < 0.01f )
        {
            transform.position = target.position;
        }
        Movement();
    }
    private void Movement()
    {
        if ( target == null ) return;
        currentLerpTime += Time.deltaTime;
        float percent = smoothCurve.Evaluate(currentLerpTime / lerpTime);
        Translate( percent );
        Rotate( percent );
    }
    private void Translate( float percent ) => transform.position = Vector3.Lerp( transform.position, target.position, percent );
    private void Rotate( float percent ) => transform.rotation = Quaternion.Lerp( transform.rotation, target.rotation, percent );
    private void ChangePoint()
    {
        currentLerpTime = 0f;
        currentPointOfView = currentPointOfView == PointsOfView.FIRST_PERSON ? PointsOfView.THIRD_PERSON : PointsOfView.FIRST_PERSON;
        switch ( currentPointOfView )
        {
            case PointsOfView.FIRST_PERSON:
                target = firstPerson;
                break;
            case PointsOfView.THIRD_PERSON:
                target = thirdPerson;
                break;
        }
    }
}

 
Simplemente creás un objeto en la escena y le añadís este componente.

Para cambiar puntos de vista del player te recomiendo una curva simple (probablemente la que seteo por defecto) y una velocidad bastante alta (Lerp Time bajo), esto lo configurás en el inspector.

Si no asignás la cámara, el script tomará la primera que encuentre en la jerarquía de la escena.
Título: [Solucionado] Mover cámara de un punto a otro
Publicado por: lightbug en Abril 02, 2019, 10:38:52 PM
Cita de: Cappa date=1554235608Yo tampoco he usado MoveTowards
   

Cita de: pioj date=1554233075Nunca he usado MoveTowards
   


MoveTowards nace de estar siempre haciendo (Ej con Vector3):
 

public float deltaPos;  //suponiendo que se elige el salto
Vector3 start , end;
...
float distanciaRestante = Distance( start , end );
"Move"( distanciaRestante < deltaPos ? distanciaRestante : deltaPos );
//Move incluye el vector de direccion
// cuando se da que (distanciaRestante < deltaPos) la pos se iguala al destino

 
La versión MoveTowards:
 

Vector3 resultado = Vector3.MoveTowards( start , end , deltaPos );

 
 
 
Cita de: nokiz date=1554223565Hola! Mi problema es que quiero mover la cámara de un punto a otro al pulsar una tecla (v).
   
   
      Quiero que el movimiento sea gradual, no que simplemente cambie de un punto a otro en un instante. Tambíen que si se vuelve a pulsar la tecla, vuelva a la primera posición.
   
   
      Todo lo que he investigado me ha llevado a lo mismo, pero lo único que consigo es que la cámara se mueva por un instante pero inmediatamente vuelve a su posición inicial. ¿Qúe estoy haciendo mal?
   
   
      Os dejo el script que le estoy aplicando a la cámara. Muchas gracias!
   


Hola Nokiz, un par de cosas:
 


// Por ej fuera o dentro de la clase
public enum MovementState
{
Idle, Moving
}


MovementState currentState;
Vector3 currentTarget;
--- (en Update/LateUpdate, etc) ---
switch(currentState)
{
case MovementState.Idle:

if( presionas la tecla esa )
{
   target = "el target que te guste"
   currentState = MovingState.Moving;
}
break;
case MovementState.Moving:
if( presionas la tecla esa )
   target = target == start ? end : start; //se conmuntan los targets,start vs end
if( se da la condición de arribo exitoso )
   currentState = MovingState.Idle;
Move();
break;
}
 
void Move()
{
// lo que haga tu método de movimiento aquí, por ej Lerp
...
}

 
(Lo hice al vuelo)
Título: [Solucionado] Mover cámara de un punto a otro
Publicado por: nokiz en Abril 05, 2019, 05:39:43 PM
Perdón por tardar en contestar, pero gracias a todos!
 
Al final he conseguido el efecto que quería ayudado por vuestros consejos.
 



   
      Nunca he usado MoveTowards, así que mi pregunta es "¿Por qué no estás usando LERP?
   

[/quote]
 
En respuesta a @pioj he de decir que leí que muchas veces se abusa del lerp cuando se puede usar MoveTowards que es más eficiente para la cpu.
 



   
      -Usar Update y luego LateUpdate en tu código no tiene tanto sentido, distinto si usaras físicas, en ese caso acumular inputs en update y resetearlas en FixedUpdate tiene sentido, pero acá no tanto (quizás sacaste la idea de algun ejemplo ?)

      -Usar movetowards te asegura que el objeto llega siempre a destino, no es necesario andar midiendo si es menor a 0.001f o parecido
   

[/quote]
 
Toda la razón, @lightbug
 
Gracias, @Cappa, me guardo tu script. Me vendrá bien más adelante.
 
Os dejo con el código con el que al final lo he solucionado por si le viene bien a alguien en un futuro.
 

public class CameraController : MonoBehaviour
{
    // Vars assigned in inspector (public)
    public Transform firstPersonCamera = null;
    public Transform thirdPersonCamera = null;
    // Private vars
    private Transform target = null;
    void Update () {
        if (Input.GetKeyUp("v")) {
            if (transform.position == thirdPersonCamera.position) {
                target = firstPersonCamera;
            } else {
                target = thirdPersonCamera;
            }
        }
        if (target) {
            transform.position = Vector3.MoveTowards(transform.position, target.position, 5 * Time.deltaTime);
        }
    }
}

 
 
Título: [Solucionado] Mover cámara de un punto a otro
Publicado por: Arcontus en Mayo 28, 2019, 02:54:13 PM
Cita de: nokiz date=1554478783transform.position = Vector3.MoveTowards(transform.position, target.position, 5 * Time.deltaTime);
   


¡A mi me ha ayudado!
 
Una línea que hace justo lo que necesito y sin complicaciones :)
Título: [Solucionado] Mover cámara de un punto a otro
Publicado por: iRobb en Junio 05, 2019, 10:03:03 PM
El componente de Cinemamachine es muy fácil de utilizar y puede realizar movimientos de cámara muy complejos.
 
Se pueden colocar diferentes cámaras e ir cambiando entre ellas con solamente enable true/false incluido movimiento transicional entre ellas. Estas cámaras pueden realizar seguimiento de cualquier target con smoothing y damping autómaticamente.