Jump to content

Archived

This topic is now archived and is closed to further replies.

Alex

Cámara Multijugador.

Recommended Posts

tengo un problema, ya tengo el juego en multijugador, entra bien, pero cuando se crean los personajes, todas las cámaras se pasan al jugador nuevo, (entro a una sala normal, pero cuando otro jugador entra, mi pantalla pasa a ese jugador, es como si mi personaje ya no valiera, es lo mismo si creo varios, la cámara se actualiza y paso a manejar el player de otro) cuando desactivo el jugador nuevo, mi cámara vuelve a mi personaje y cuando vuelvo a activarlo, se regresa al nuevo (esto sucede para los dos jugadores) alguna ayuda?

Share this post


Link to post
Share on other sites

imagino que eso es porque hay varias cámaras en pantalla y el juego muestra la última cámara habilitada.

CREO que podrías resolverlo si no permites que en la escena de tu jugador se habiliten más cámaras que la propia del player, siento no explayarme más, pero no sé como tienes organizado tu proyecto ni nada, mucha suerte.

Share this post


Link to post
Share on other sites

La solución que le encuentro es: hacer una variable que defina la cámara a mi jugador como dueño de esta y si en algún momento muere, las otras cámaras tengan algo que le  impida pasar a otro personaje, que desactive la cámara, no cambiando de jugador como lo hace, tengo entendido eso pero no se como desarrollarla.

Share this post


Link to post
Share on other sites

El problema es que cuando diseñas un sistema multijugador armas el clásico "MoveNetwork" que no es más que enviar y recibir posiciones.

1º Debes eliminar esa estructura de tu proyecto.

2º Debes abstraer todo el proyecto para que cada componente NetworkBehaviour sea un cliente, esto quiere decir que todas las características del jugador se controlan desde un solo componente.

El problema de las cámaras es algo simple de resolver siguiente la estructura correcta.

 

Share this post


Link to post
Share on other sites

No deberías necesitar más de una cámara en la escena, cuando crees una escena "online" piensa que esa escena se va a crear en cada cliente con todos los GameObjects que haya en ella, las mallas (por ejemplo un edificio) se crean de manera "local", al igual que la cámara, audiosource, luces, etc... si no haces cambios (imagina que quieres que haya una habitación en la que los jugadores pueden encender/apagar la luz o puertas abiertas/cerradas) no deberías de tener que sincronizar nada de esto entre los diferentes clientes.

La lógica es tema aparte, debes tener mucho cuidado con físicas (no hablo solo de rigidbody, sino también de los cast) porque depende de dónde hagas los cálculos puedes tener errores, como dice Franco, debes abstraer bastante, aunque no concuerdo con lo de un NetworkBehaviour por cliente, sí creo que debes reducir lo máximo el número de NetworkBehaviour. El tema de la cámara, si tienes una cámara que sigue al jugador, será el jugador el que le diga a la cámara de la escena que lo tiene que seguir (también puedes instanciar una cámara al crear al jugador), aquí verás que si no tienes cuidado acabas con tantas cámaras como jugadores (mal), puedes tirar de isLocalPlayer para saber si es el jugador "local", por ejemplo:

void Start ()
{
	if(isLocalPlayer)
	{
		Emparenta la cámara con el jugador o setea tu jugador en la cámara.
	}
}

También puedes usar los métodos que son llamados por Networking: OnStartLocalPlayer.

Suerte!!

Share this post


Link to post
Share on other sites

Gracias @francoe1 @juanma_teso estaba un buen rato con esto y sí, recordé que cada jugador crea en su escena su propia cámara, oo que hice fue poner una cámara general en la escena de juego multijugador, y dentro de ella puse el codigo de seguir a mi jugador usando target, ahora tengo un nuevo problema y es que mi jugador se puede instanciar en diferentes lugares y la camara se queda en x,z en la misma posición en que la deje, quiero que la camara al iniciar la escena se mueva a la posición del jugador (claro que debe estar almenos en 0,1,4 x,y,z) he usado un script que convierte a la cámara en hijo de mi jugador y otro script en la cámara que hace mover a esta a una posición un poco alejada de mi jugador, todo bien con eso pero tengo un error con otra función de la cámara, y es que necesito evitar convertir a mi cámara en hijo de mi jugador, mi cámara trae la opción de target la cual hace posible que mi cámara siga a mi jugador, alguien podria decirme como puedo usar esa función target que almacena a mí jugador para que la cámara se mueva hasta mi jugador? Estoy buscando y he encontrado el transform.position y el offset, pueden ayudarme?

Share this post


Link to post
Share on other sites

@juanma_teso Cada cliente debe tener un solo NetworkB... Esto es algo que se debe seguir, cada componente NB es una conexión nueva con UID diferentes imagina el desastre que sería la lógica.

Por otro lado, la abstracción para un juego multijugador se debe realizar de tal modo que las mecánicas del juego no se vean afectadas por el código de red. Esto quiere decir que el juego debería funcionar completamente en modo offline y luego de ser necesario sincronizar eventos y estados entre jugadores y servidor. 

Siguiendo lo anterior la migración de un juego offline a online sería bastante simple, también, permite utilizar diferentes tecnologías para la conexión, por ejemplo migrar de UNET a Photon o cualquier otra libreria, hasta de ser necesario podrías armar sobre unos simples sockets UDP. 

UNET llegó para complicar el mundo del networking.... 

Share this post


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

Gracias @francoe1 @juanma_teso estaba un buen rato con esto y sí, recordé que cada jugador crea en su escena su propia cámara, oo que hice fue poner una cámara general en la escena de juego multijugador, y dentro de ella puse el codigo de seguir a mi jugador usando target, ahora tengo un nuevo problema y es que mi jugador se puede instanciar en diferentes lugares y la camara se queda en x,z en la misma posición en que la deje, quiero que la camara al iniciar la escena se mueva a la posición del jugador (claro que debe estar almenos en 0,1,4 x,y,z) he usado un script que convierte a la cámara en hijo de mi jugador y otro script en la cámara que hace mover a esta a una posición un poco alejada de mi jugador, todo bien con eso pero tengo un error con otra función de la cámara, y es que necesito evitar convertir a mi cámara en hijo de mi jugador, mi cámara trae la opción de target la cual hace posible que mi cámara siga a mi jugador, alguien podria decirme como puedo usar esa función target que almacena a mí jugador para que la cámara se mueva hasta mi jugador? Estoy buscando y he encontrado el transform.position y el offset, pueden ayudarme?

Usa la función que te mencioné, en el mismo manual te pone como ejemplo que puedes usarla para activar la cámara:

void OnStartLocalPlayer ()
{
	//Busca la cámara y fija el target.
}

@francoe1 jajaj siempre discrepamos en lo mismo, hasta donde sé los NetworkBehaviour (NB) no son nada sin un NetworkIdentity (NI), es necesario un NI para que el NB funcione y se sincronice además un NI puede manejar varios NB, todos los que tenga un mismo GameObject (creo que tiene un máximo), el NI tampoco es el que manda los mensajes a través de la red, el encargado de mandar y recibir los mensajes (no hablo a nivel bajo) es el NetworkConnection y según la documentación maneja múltiples NI y es único para un cliente, entonces según lo entendí yo, no crea múltiples conexiones.

Share this post


Link to post
Share on other sites

Alguien puede ayudarme! Estoy con esto ya casi 4 dias y no puedo lograr que la cámara este en cada jugador!

Este es mi script de la cámara: 

(Disculpen por no ponerlo en <>)

using UnityEngine;

using System.Collections;

public class SmoothCameraFollow : MonoBehaviour {
    static public Transform target;
    public float distance = 4.0f;
    public float height = 1.0f;
    public float smoothlag = 0.2f;
    public float maxSpeed = 10.0f;
    public float snapLag =  0.3f;
       public float clampHeadPositionScreenSpace= 0.75f;
       LayerMask lineOfSightMask = 0;
       Vector3 headOffset= Vector3.zero;
       Vector3 centerOffset = Vector3.zero;


       bool isSnapping = false;
       Vector3 velocity = Vector3.zero;
       float targetHeight = 10000.0f;


       void Apply(Transform dummyTarget, Vector3 dummyCenter){
Vector3 targetCenter = target.position+ centerOffset;
Vector3 targetHead = target.position + headOffset;
targetHeight = targetCenter.y+height;
if (Input.GetButton("Fire2")&& !isSnapping){
    velocity = Vector3.zero;
    isSnapping = true;
}
 if (isSnapping){  
 ApplySnapping(targetCenter);
}
else
{
    ApplyPositionDamping (new Vector3(targetCenter.x, targetHeight, targetCenter.z));

}
setUpRotation(targetCenter, targetHead);
       }
       void LateUpdate(){
           if (target)
           Apply(null,Vector3.zero);
       }
       void ApplySnapping(Vector3 targetCenter){
           Vector3 position =transform.position;
           Vector3 offset= position - targetCenter;
           offset.y = 0;
           float currentDistance = offset.magnitude;
           float targetAngle= target.eulerAngles.y;
           float currentAngle = transform.eulerAngles.y;

           currentAngle = Mathf.SmoothDampAngle(currentAngle,targetAngle,ref velocity.x, snapLag);
currentDistance = Mathf.SmoothDamp(currentDistance,distance,ref velocity.z, snapLag);
Vector3 newPosition = targetCenter;
newPosition += Quaternion.Euler(0, currentAngle,0) * Vector3.back * currentDistance;
newPosition.y = Mathf.SmoothDamp (position.y, targetCenter.y + height, ref velocity.y, smoothlag,maxSpeed);
newPosition += AdjustLineOfSight(newPosition, targetCenter);
transform.position = newPosition;
if (AngleDistance(currentAngle, targetAngle)> 3.0){
    isSnapping= false;
    velocity= Vector3.zero;
}     
       }
       Vector3 AdjustLineOfSight(Vector3 newPosition,Vector3 target){
           RaycastHit hit;
           if(Physics.Linecast(target, newPosition, out hit, lineOfSightMask.value)){
               velocity = Vector3.zero;
               return hit.point;
           }
           return newPosition;
       }
void ApplyPositionDamping(Vector3 targetCenter){
    Vector3 position = transform.position;
    Vector3 offset = position - targetCenter;
    offset.y = 0;
    Vector3 newTargetPos =offset.normalized * distance + targetCenter;
    Vector3 newPosition;
newPosition.x = Mathf.SmoothDamp (position.x, newTargetPos.x, ref velocity.x,smoothlag, maxSpeed);
newPosition.z = Mathf.SmoothDamp (position.z, newTargetPos.z, ref velocity.z,smoothlag, maxSpeed);
newPosition.y = Mathf.SmoothDamp (position.y, targetCenter.y, ref velocity.y,smoothlag, maxSpeed);
newPosition = AdjustLineOfSight(newPosition,targetCenter);
transform.position = newPosition;
}
void setUpRotation(Vector3 centerPos,Vector3 headPos){
    Vector3 cameraPos = transform.position;
    Vector3 offsetToCenter = centerPos - cameraPos;
    Quaternion yRotation = Quaternion.LookRotation(new Vector3(offsetToCenter.x, 0.0f, offsetToCenter.z));
Vector3 relativeOffset = Vector3.forward* distance + Vector3.down * height;
transform.rotation = yRotation * Quaternion.LookRotation(relativeOffset);

Ray centerRay = this.GetComponent<Camera>().ViewportPointToRay(new Vector3(.5f, 0.5f, 1f));
Ray topRay = this.GetComponent<Camera>().ViewportPointToRay(new Vector3(.5f, clampHeadPositionScreenSpace,1.0f));
Vector3 centerRayPos = centerRay.GetPoint(distance);
Vector3 topRayPos = topRay.GetPoint(distance);
float centerToTopAngle = Vector3.Angle(centerRay.direction,topRay.direction);
float heightToAngle = centerToTopAngle/(centerRayPos.y - topRayPos.y);
float extraLookAngle = heightToAngle * (centerRayPos.y - topRayPos.y);
if(extraLookAngle < centerToTopAngle){
    extraLookAngle = 0;
}
else{
    extraLookAngle = extraLookAngle - centerToTopAngle;
    transform.rotation *= Quaternion.Euler(-extraLookAngle,0,0);
}
}
float AngleDistance (float a, float b){
    a = Mathf.Repeat(a, 360);
    b= Mathf.Repeat(b,360);
    return Mathf.Abs(b-a);
}
Vector3 GetCenterOffset(){
    return centerOffset;
}
void setTarget (Transform t){
    target = t;
}
}

La cámara funciona bien, sigue al jugador y lo toma como target con este script:

 

public class Target : NetworkBehaviour
{
 public override void OnStartLocalPlayer(){
    if (!isLocalPlayer){
        GetComponent<VehicleParent>().gameObject.SetActive(true);
      SmoothCameraFollow.target =this.transform;
    }
}
}

(El vehicleparent es el código de control del carro)

 

Si inicio el multijugador solo, todo funciona bien, tengo una cámara en la escena de juego multijugador, cuando entro de 2 (editor y celular) la cámara toma como target al primer carro, y deja al otro sin cámara, cuando veo la jerarquía en el editor, uno de los carros es el que tiene la cámara y si muevo el auto, en la pantalla del celular no me muestra nada, solo una imagen estática de mi jugador sin poder moverlo (es como cuando sale el mensaje de "not is camera rendering" pero en el celular no sale ese mensaje, solo se muestra estático, en cambio en el editor si puedo ver que los dos  auto se mueven, alguien sabe como puedo solucionarlo? (El problema es que la única camara de mi escena solo se muestra a una pantalla, no a cada una individualmente como debería ser) porfavor ayuda con esto.

 

 

 

Share this post


Link to post
Share on other sites

Estas diciendo que todos los clientes al conectarse buscarán si no son locales se asignan a la camara. 

public override void OnStartLocalPlayer()
{
    if (!isLocalPlayer)
    {
        GetComponent<VehicleParent>().gameObject.SetActive(true);
      	SmoothCameraFollow.target =this.transform;
    }
}

Presta atención que la comparación del IF es válida cuando isLocalPlayer es FALSE debido al signo de exclamación al inicio (!) 

Por otro lado si es intencional, deberias plantear otra solución por que la asignación de la cámara sería bastante rara, de este modo el último cliente en entrar tendrá el control de la cámara.

Share this post


Link to post
Share on other sites

Entonces que tendría que cambiar?

Poner el:

If(isLocalPlayer)?

Para que cambie a una afirmación en vez de una negación?

Share this post


Link to post
Share on other sites
4 minutes ago, Alex said:

Entonces que tendría que cambiar?

Poner el:

If(isLocalPlayer)?

Para que cambie a una afirmación en vez de una negación?

Respuesta corta: Sí.

Share this post


Link to post
Share on other sites

Te Funciono al final el juego?

 

la verdad no se mucho de esto pero en multijugador la cámara la uso con el

public override void OnStartLocalPlayer()
	{
		Camera.main.transform.parent = transform;
	}

 

este script se lo pongo al Player ya con esto cada client funciona correctamente

 

 

Share this post


Link to post
Share on other sites
On 12/15/2018 at 12:04 AM, Javierhakerone said:

Te Funciono al final el juego?

Estuve revisando y intentando varias veces con diferentes variables y al final me funciono, (es parecida a la que pones) ya después la optimizare y agregare el efecto de retardo al seguir al jugador.

Share this post


Link to post
Share on other sites
22 hours ago, Alex said:

Estuve revisando y intentando varias veces con diferentes variables y al final me funciono, (es parecida a la que pones) ya después la optimizare y agregare el efecto de retardo al seguir al jugador.

si puedes indica o añade esa parte de tu script para que otros incluyéndome nos podamos ayudar de eso.... gracias

Share this post


Link to post
Share on other sites

×
×
  • Create New...