Jump to content
UnitySpain
Sign in to follow this  
PmL_Unity

ANSWERED [SOLUCIONADO]Fijar Cámara a Enemigos

Recommended Posts

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.

Edited by PmL_Unity

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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

Edited by Igor

Share this post


Link to post
Share on other sites
17 hours ago, iRobb said:

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.

Muchas gracias por tomarte el tiempo en responder, lo pondré en práctica. :)

17 hours ago, Igor said:

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

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.  :)

Edited by pioj
Por favor, usa el <> o el "quote" para pegar código.

Share this post


Link to post
Share on other sites

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... 

Edited by Igor

Share this post


Link to post
Share on other sites
1 hour ago, Igor said:

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... 

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.

Share this post


Link to post
Share on other sites

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

Edited by Ness

Share this post


Link to post
Share on other sites

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...

 

case1.jpgcase2.jpgcase3.jpgcase4.jpg

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.

Share this post


Link to post
Share on other sites
On 10/30/2019 at 8:41 PM, Ness said:

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

 

11 hours ago, Antonio said:

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...

 

case1.jpgcase2.jpgcase3.jpgcase4.jpg

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! 

Share this post


Link to post
Share on other sites

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 :) 

Share this post


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

×
×
  • Create New...