Noticias

¡RECUERDA QUE SI ERES UN NUEVO USUARIO, DEBES PRESENTARTE PARA PODER PUBLICAR MENSAJES! | TENEMOS CANAL OFICIAL DE TELEGRAM: t.me/unity3dspain

Temas recientes

[SOLUCIONADO]Fijar Cámara a Enemigos

Iniciado por PmL_Unity, Octubre 27, 2019, 02:17:01 AM

Tema anterior - Siguiente tema
Octubre 27, 2019, 02:17:01 AM Ultima modificación: Noviembre 02, 2019, 08:41:50 PM por PmL_Unity
Hola a todos,  lo que quiero hacer y no me sale porque no se me cae una idea de como empezar es de hacer que una cámara en tercera persona se fije al enemigo y que gire en torno al enemigo pero desde la posición de mi jugador, osea la tipica fijación de enemigo de todos los juegos de combate en tercera persona. 
 
Quiero lograr eso pero no se  por donde empezar, agradeceria si alguien me podria dar alguna orientación para poder conseguir algo parecido. 
 
Muchas gracias.

Añadir una transform al enemigo en el punto de distancia que te interese. Tener una cámara disabled. Cuando llegue el momento, asigna la cámara a la transform y que pase a enabled. Realiza una rotation local de la transform o la cámara. Lo de que giren entorno al enemigo desde la posición del jugador no lo acabo de entender, ya que desde esta cámara secundaria lo que se verá es al enemigo en la rotación. Pero vamos, creo que te servirá de base.

Octubre 27, 2019, 09:38:25 AM #2 Ultima modificación: Octubre 27, 2019, 09:44:30 AM por Igor
creo que quieres algo como en zelda: ocarina of time...
 
 
 
primero tienes que tener una lista o array de los enemigos 
 
luego, cuando pulsas el boton de "fijar" enemigo, tienes que tener una funcion para ver cual es el mas cercano al centro de la pantalla (se hace con camera.worldToScreenPoint o algo asi) y entonces "cojes" ese transform como objetivo.
 
luego, dependiendo como muevas la camara normalmente, pues lo que tienes que hacer es que mire hacia al enemigo... puede ser de varias maneras dependiendo como coloques la camara detras de tu personaje... la camara es libre? esta el protagonista siempre dando la espalda a la camara? el protagonista dispara o lanza flechas o algo hacia donde mira la camara? etc...
 
si pones aqui el script o los scripts que controlan la camara podremos ayudarte mas facilmente

Octubre 27, 2019, 03:01:59 PM #3 Ultima modificación: Octubre 28, 2019, 02:55:21 AM por pioj
Cita de: iRobb date=1572163273Añadir una transform al enemigo en el punto de distancia que te interese. Tener una cámara disabled. Cuando llegue el momento, asigna la cámara a la transform y que pase a enabled. Realiza una rotation local de la transform o la cámara. Lo de que giren entorno al enemigo desde la posición del jugador no lo acabo de entender, ya que desde esta cámara secundaria lo que se verá es al enemigo en la rotación. Pero vamos, creo que te servirá de base.
   


Muchas gracias por tomarte el tiempo en responder, lo pondré en práctica. :)
 
Cita de: Igor date=1572165505creo que quieres algo como en zelda: ocarina of time...
   
   
       
   
   
      primero tienes que tener una lista o array de los enemigos 
   
   
      luego, cuando pulsas el boton de "fijar" enemigo, tienes que tener una funcion para ver cual es el mas cercano al centro de la pantalla (se hace con camera.worldToScreenPoint o algo asi) y entonces "cojes" ese transform como objetivo.
   
   
      luego, dependiendo como muevas la camara normalmente, pues lo que tienes que hacer es que mire hacia al enemigo... puede ser de varias maneras dependiendo como coloques la camara detras de tu personaje... la camara es libre? esta el protagonista siempre dando la espalda a la camara? el protagonista dispara o lanza flechas o algo hacia donde mira la camara? etc...
   
   
      si pones aqui el script o los scripts que controlan la camara podremos ayudarte mas facilmente
   


Mi script de la cámara es este: 
 

public class CamaraPlayer : MonoBehaviour
{
    
    public float mouseSensitivity = 10f; 
    public float dstFromTarget = 2f;
    public Vector2 pitchMininMax = new Vector2(-40, 85);
    public float rotationSmoothTime = .12f;
    Vector3 rotationSmoothVelocity;
    Vector3 currentRotation;
    float yaw;
    float pitch;
    public GameObject PLAYER;
   public Transform target;
    private void Awake()
    {
        PLAYER = GameObject.FindGameObjectWithTag("Player");
        target = PLAYER.transform;
    }
    
   
    void LateUpdate()
    {
        yaw += Input.GetAxis("GiroHorizontalCamara") * mouseSensitivity;
        yaw += Input.GetAxis("Mouse X") * mouseSensitivity;
        pitch -= Input.GetAxis("MovVerticalCamara") * mouseSensitivity;
        pitch -= Input.GetAxis("Mouse Y") * mouseSensitivity;
        pitch = Mathf.Clamp(pitch, pitchMininMax.x, pitchMininMax.y);
        currentRotation = Vector3.SmoothDamp(currentRotation, new Vector3(pitch, yaw), ref rotationSmoothVelocity, rotationSmoothTime);
        transform.eulerAngles = currentRotation;
 
        transform.position = target.position - transform.forward * dstFromTarget;
    }
    
}

 
 
 
La cámara es en 3ra persona al estilo GOD OF WAR (ps4), ASSASSINS CREED, DARK SOULS, DARKSIDERS, THE WITCHER 3 etc..  y si es libre y da a la espalda del player siempre.
 
Muchas gracias por tu respuesta y por tomarte un tiempo para responder.  :)

Octubre 29, 2019, 01:24:01 PM #4 Ultima modificación: Octubre 29, 2019, 01:28:13 PM por Igor
hola
 
en ese script no se puede ver como el "player"  gira para dar la espalda a la camara... supongo que esa parte esta en el script del player...
 
en el script tendria que hacer dos funciones, una para el control normal de la camara, y otra para cuando esta fijada...
 
tampoco has dicho como quieres fijarla... que se fije mientras mantengas pulsado un boton? y cuando lo sueltes que se "libere" la camara?
 
pues seria algo asi...
 

public class CamaraPlayer : MonoBehaviour
{
   
    public float mouseSensitivity = 10f;
    public float dstFromTarget = 2f;
    public Vector2 pitchMininMax = new Vector2(-40, 85);
    public float rotationSmoothTime = .12f;
    Vector3 rotationSmoothVelocity;
    Vector3 currentRotation;
    float yaw;
    float pitch;
    public GameObject PLAYER;
    public Transform target;
 
private Transform enemyTransform;//transform del enemy
public float enemyOffsetY = 3;
    private void Awake()
    {
        PLAYER = GameObject.FindGameObjectWithTag("Player");
        target = PLAYER.transform;
    }
   
   
    void LateUpdate()
    {
   //buscar el enemy mas cerca del centro de la pantalla
   if (Input.GetMouseButton(1)) {
      GetMoreCenteredEnemy();
   }
   //que se fije la camara mientras mantengas pulsado el boton derecho del raton
   if (Input.GetMouseButton(1)) {
      fixetToEnemy();
   } else {
      NormalCamera()
   }
}
 
void NormalCamera() {
        yaw += Input.GetAxis("GiroHorizontalCamara") * mouseSensitivity;
        yaw += Input.GetAxis("Mouse X") * mouseSensitivity;
        pitch -= Input.GetAxis("MovVerticalCamara") * mouseSensitivity;
        pitch -= Input.GetAxis("Mouse Y") * mouseSensitivity;
        pitch = Mathf.Clamp(pitch, pitchMininMax.x, pitchMininMax.y);
        currentRotation = Vector3.SmoothDamp(currentRotation, new Vector3(pitch, yaw), ref rotationSmoothVelocity, rotationSmoothTime);
        transform.eulerAngles = currentRotation;
 
        transform.position = target.position - transform.forward * dstFromTarget;
    }
 
 
void FixedToEnemy() {
   if (enemyTransform != null) {
             transform.position = target.position;
             Quaternion oldRot = transform.rotation;
             transform.LookAt(enemyTransform.position - (Vector3.up * enemyOffsetY));
             transform.rotation = Quaternion.Lerp(oldRot, trasnform.rotation, rotationSmoothTime)
             transform.position -= transform.forward * dstFromTarget;
   } else {
             NormalCamera();
        }
}
 
void GetMoreCenteredEnemy() {
   Vector2 screenCenter = new Vector2(Screen.width/2, Screen.height/2);
   GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");
   float centerDist = 100000;
       foreach (GameObject enemy in enemies) {
           Vector3 screenPos = cam.WorldToScreenPoint(enemy.transform.position);
            float dist = Vector2.Distance(screenCenter, new Vector2(screenPos.x, screenPos.y));
      if (dist < centerDist){
                centerDist=dist;
                 enemyTransform = enemy.transform;
      }
        }
}
 
}

 
 
 
???
 
no se porque se han descuadrado todas las "llaves"...
 
 
 
he pasado tu funcion "LateUpdate" a "NormalCamera"... y he añadido una que elige el enemy mas cercano al centro y otra que hace que la camara le mire... he añadido un valor de "offset" para que el enemy quede mas arriba del centro de la pantalla...
 
creo que funcionara... pero no lo he probado... igual da algun error... 

Cita de: Igor date=1572351841hola
   
   
      en ese script no se puede ver como el "player"  gira para dar la espalda a la camara... supongo que esa parte esta en el script del player...
   
   
      en el script tendria que hacer dos funciones, una para el control normal de la camara, y otra para cuando esta fijada...
   
   
      tampoco has dicho como quieres fijarla... que se fije mientras mantengas pulsado un boton? y cuando lo sueltes que se "libere" la camara?
   
   
      pues seria algo asi...
   
   

public class CamaraPlayer : MonoBehaviour
{
   
    public float mouseSensitivity = 10f;
    public float dstFromTarget = 2f;
    public Vector2 pitchMininMax = new Vector2(-40, 85);
    public float rotationSmoothTime = .12f;
    Vector3 rotationSmoothVelocity;
    Vector3 currentRotation;
    float yaw;
    float pitch;
    public GameObject PLAYER;
    public Transform target;
 
private Transform enemyTransform;//transform del enemy
public float enemyOffsetY = 3;
    private void Awake()
    {
        PLAYER = GameObject.FindGameObjectWithTag("Player");
        target = PLAYER.transform;
    }
   
   
    void LateUpdate()
    {
   //buscar el enemy mas cerca del centro de la pantalla
   if (Input.GetMouseButton(1)) {
      GetMoreCenteredEnemy();
   }
   //que se fije la camara mientras mantengas pulsado el boton derecho del raton
   if (Input.GetMouseButton(1)) {
      fixetToEnemy();
   } else {
      NormalCamera()
   }
}
 
void NormalCamera() {
        yaw += Input.GetAxis("GiroHorizontalCamara") * mouseSensitivity;
        yaw += Input.GetAxis("Mouse X") * mouseSensitivity;
        pitch -= Input.GetAxis("MovVerticalCamara") * mouseSensitivity;
        pitch -= Input.GetAxis("Mouse Y") * mouseSensitivity;
        pitch = Mathf.Clamp(pitch, pitchMininMax.x, pitchMininMax.y);
        currentRotation = Vector3.SmoothDamp(currentRotation, new Vector3(pitch, yaw), ref rotationSmoothVelocity, rotationSmoothTime);
        transform.eulerAngles = currentRotation;
 
        transform.position = target.position - transform.forward * dstFromTarget;
    }
 
 
void FixedToEnemy() {
   if (enemyTransform != null) {
             transform.position = target.position;
             Quaternion oldRot = transform.rotation;
             transform.LookAt(enemyTransform.position - (Vector3.up * enemyOffsetY));
             transform.rotation = Quaternion.Lerp(oldRot, trasnform.rotation, rotationSmoothTime)
             transform.position -= transform.forward * dstFromTarget;
   } else {
             NormalCamera();
        }
}
 
void GetMoreCenteredEnemy() {
   Vector2 screenCenter = new Vector2(Screen.width/2, Screen.height/2);
   GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");
   float centerDist = 100000;
       foreach (GameObject enemy in enemies) {
           Vector3 screenPos = cam.WorldToScreenPoint(enemy.transform.position);
            float dist = Vector2.Distance(screenCenter, new Vector2(screenPos.x, screenPos.y));
      if (dist < centerDist){
                centerDist=dist;
                 enemyTransform = enemy.transform;
      }
        }
}
 
}

   
       
   
   
      ???
   
   
      no se porque se han descuadrado todas las "llaves"...
   
   
       
   
   
      he pasado tu funcion "LateUpdate" a "NormalCamera"... y he añadido una que elige el enemy mas cercano al centro y otra que hace que la camara le mire... he añadido un valor de "offset" para que el enemy quede mas arriba del centro de la pantalla...
   
   
      creo que funcionara... pero no lo he probado... igual da algun error... 
   


Hola, Muchas gracias por tu respuesta, lo probare  Muchas gracias. Este script es para una camara en 3 persona típica de los juegos estilo the witcher 3, dark souls, darksiders, god of war etc..
 
La fijación que quiero lograr es la que tienen estos juegos nombrados a la hora de combatir, que fijas la cámara al enemigo para cuando te mueves no pierdes de vista al mismo.

Octubre 31, 2019, 12:41:00 AM #6 Ultima modificación: Octubre 31, 2019, 12:53:02 AM por Ness
Bueno  en mi  opinión, seria desactivar  la cámara del jugador o el scritp del Player cuando estuvieras cerca del enemigo en cuestión que quieres fijar,  luego emparentar esa cámara al enemigo, usar un Array almacenar el total de enemigos y una tag o algo para saber cual enemigo en especifico es el quieres fijar.
 
luego de emparentarlo  la cámara al enemigo, le das distancia para que puedas ejecutar lo que gustes durante ese tiempo,  por ultimo le das salida, todo y des-emparentas la cámara y se le devuelves al jugador, vuelves a activar el scritp de la cámara del jugador.
 
https://answers.unity.com/questions/715058/lock-target-and-orbit-it.html

La cámara esa sencilla del  CamaraPlayer
 

public class CamaraPlayer : MonoBehaviour
{
   
    public float mouseSensitivity = 10f;
    public float dstFromTarget = 2f;
    public Vector2 pitchMininMax = new Vector2(-40, 85);
    public float rotationSmoothTime = .12f;
    Vector3 rotationSmoothVelocity;
    Vector3 currentRotation;
    float yaw;
    float pitch;
    public GameObject PLAYER;
   public Transform target;
    private void Awake()
    {
        PLAYER = GameObject.FindGameObjectWithTag("Player");
        target = PLAYER.transform;
    }
   
   
    void LateUpdate()
    {
        yaw += Input.GetAxis("GiroHorizontalCamara") * mouseSensitivity;
        yaw += Input.GetAxis("Mouse X") * mouseSensitivity;
        pitch -= Input.GetAxis("MovVerticalCamara") * mouseSensitivity;
        pitch -= Input.GetAxis("Mouse Y") * mouseSensitivity;
        pitch = Mathf.Clamp(pitch, pitchMininMax.x, pitchMininMax.y);
        currentRotation = Vector3.SmoothDamp(currentRotation, new Vector3(pitch, yaw), ref rotationSmoothVelocity, rotationSmoothTime);
        transform.eulerAngles = currentRotation;
 
        transform.position = target.position - transform.forward * dstFromTarget;
    }
   
}

 
 
 
Está usando el valor yaw (que irá desde -infinito hacia +infinito aunque en la práctica, es de -360 a +360), es un ángulo que usas después para ponérselo a la Y en el transform.eulerAngles.
 
En este código, ese ángulo se modifica moviendo el ratón, pero si tuvieras un enemigo, o un objetivo específico al que apuntar la cámara, lo que necesitas es hallar el ángulo para que apunte a ese punto.


De modo que si tienes la X y Z de la posición del enemigo...
 
 
 

 
En ese código que tienes después de hacer la rotación, simplemente mueve la cámara a la posición del jugador y da unos pasos hacia atrás, luego según veo yo no haría falta hacer más modificaciones para el asunto de la rotación.
 
Para el pitch, la idea es igual, pero usando la distancia y la altura (Y) en lugar del X y Z. (Si haces algún enemigo volador pues puede que lo necesites, pero ten cuidado de aplicar también la línea del clamp o puede que la cámara empiece a dar vueltas raras y a ponerse bocabajo).
 
 
 
 
 
 
 
Otra cosa sería cuando hallar el yaw mediante trigonometría y cuando mover el yaw mediante el ratón, se puede hacer dos cámaras, o también podrías poner alguna variable Transform para el "objetivo" de la cámara, si es igual a null, moverla con el ratón, si es distinto de null, hallar el yaw con la fórmula.

Cita de: Ness date=1572478860Bueno  en mi  opinión, seria desactivar  la cámara del jugador o el scritp del Player cuando estuvieras cerca del enemigo en cuestión que quieres fijar,  luego emparentar esa cámara al enemigo, usar un Array almacenar el total de enemigos y una tag o algo para saber cual enemigo en especifico es el quieres fijar.
   
   
      luego de emparentarlo  la cámara al enemigo, le das distancia para que puedas ejecutar lo que gustes durante ese tiempo,  por ultimo le das salida, todo y des-emparentas la cámara y se le devuelves al jugador, vuelves a activar el scritp de la cámara del jugador.
   
   
      https://answers.unity.com/questions/715058/lock-target-and-orbit-it.html
   


 
 
Cita de: Antonio date=1572662890La cámara esa sencilla del  CamaraPlayer
   
   

public class CamaraPlayer : MonoBehaviour
{
   
    public float mouseSensitivity = 10f;
    public float dstFromTarget = 2f;
    public Vector2 pitchMininMax = new Vector2(-40, 85);
    public float rotationSmoothTime = .12f;
    Vector3 rotationSmoothVelocity;
    Vector3 currentRotation;
    float yaw;
    float pitch;
    public GameObject PLAYER;
   public Transform target;
    private void Awake()
    {
        PLAYER = GameObject.FindGameObjectWithTag("Player");
        target = PLAYER.transform;
    }
   
   
    void LateUpdate()
    {
        yaw += Input.GetAxis("GiroHorizontalCamara") * mouseSensitivity;
        yaw += Input.GetAxis("Mouse X") * mouseSensitivity;
        pitch -= Input.GetAxis("MovVerticalCamara") * mouseSensitivity;
        pitch -= Input.GetAxis("Mouse Y") * mouseSensitivity;
        pitch = Mathf.Clamp(pitch, pitchMininMax.x, pitchMininMax.y);
        currentRotation = Vector3.SmoothDamp(currentRotation, new Vector3(pitch, yaw), ref rotationSmoothVelocity, rotationSmoothTime);
        transform.eulerAngles = currentRotation;
 
        transform.position = target.position - transform.forward * dstFromTarget;
    }
   
}

   
       
   
   
      Está usando el valor yaw (que irá desde -infinito hacia +infinito aunque en la práctica, es de -360 a +360), es un ángulo que usas después para ponérselo a la Y en el transform.eulerAngles.
   
   
      En este código, ese ángulo se modifica moviendo el ratón, pero si tuvieras un enemigo, o un objetivo específico al que apuntar la cámara, lo que necesitas es hallar el ángulo para que apunte a ese punto.


      De modo que si tienes la X y Z de la posición del enemigo...
   
   
       
   
   
      
   
   
      En ese código que tienes después de hacer la rotación, simplemente mueve la cámara a la posición del jugador y da unos pasos hacia atrás, luego según veo yo no haría falta hacer más modificaciones para el asunto de la rotación.
   
   
      Para el pitch, la idea es igual, pero usando la distancia y la altura (Y) en lugar del X y Z. (Si haces algún enemigo volador pues puede que lo necesites, pero ten cuidado de aplicar también la línea del clamp o puede que la cámara empiece a dar vueltas raras y a ponerse bocabajo).
   
   
       
   
   
       
   
   
       
   
   
      Otra cosa sería cuando hallar el yaw mediante trigonometría y cuando mover el yaw mediante el ratón, se puede hacer dos cámaras, o también podrías poner alguna variable Transform para el "objetivo" de la cámara, si es igual a null, moverla con el ratón, si es distinto de null, hallar el yaw con la fórmula.
   


Muchas gracias por sus respuestas! 

Paso la solucion si alguien le interesa:
 
public class FijarCamra_Test_A : MonoBehaviour

{
 
    public float mouseSensitivity = 10f; 


    public float dstFromTarget = 2f;

    public Vector2 pitchMininMax = new Vector2(-40, 85);

    public float rotationSmoothTime = .12f;
 
    Vector3 rotationSmoothVelocity;

    Vector3 currentRotation;
 
    float yaw; // movimiento horizontal

    float pitch; // movimiento vertical

    public GameObject PLAYER;

    public Transform target;

    public Transform enemigo;

    public float speed;
 
    private void Awake()

    {


        PLAYER = GameObject.FindGameObjectWithTag("Player");

        target = PLAYER.transform;

    }
 


    void LateUpdate()

    {

        yaw += Input.GetAxis("GiroHorizontalCamara") * mouseSensitivity;

        yaw += Input.GetAxis("Mouse X") * mouseSensitivity;

        pitch -= Input.GetAxis("MovVerticalCamara") * mouseSensitivity;

        pitch -= Input.GetAxis("Mouse Y") * mouseSensitivity;

        pitch = Mathf.Clamp(pitch, pitchMininMax.x, pitchMininMax.y);
 
        currentRotation = Vector3.SmoothDamp(currentRotation, new Vector3(pitch, yaw), ref rotationSmoothVelocity, rotationSmoothTime);

        transform.eulerAngles = currentRotation;
 
        //LÍNEA NUEVA PARA FIJAR AL ENEMIGO       
 
       transform.LookAt(enemigo);

        transform.RotateAround(enemigo.position, Vector3.forward, speed * Time.deltaTime);
 
        //FIN LÍNEA NUEVA PARA FIJAR AL ENEMIGO       
 
        transform.position = target.position - transform.forward * dstFromTarget;
 
      

    }
 
 
 
 
 
Este script va a la cámara del Player y despues hago otro script para que active este script para fijar al enemigo y desactive el otro script / desactive este script  y active el otro para que vuelva a la cámara normal.
 
Quizás hay mejor y más eficientes manera de hacer esto pero es la que me resultó, gracias a todos por sus respuestas son unos genios todos :) 

Etiquetas: