Instantiate Unity 3D

Turco

Buenas, tengo un problema a la hora de que los jugadores de una partida en multijugador, vean las balas. Puedo ver a los jugadores moverse y girar, pero cuando le dan a disparar, la bala sólo la ve el jugador que la dispara.

Tengo estos 3 scripts. Jugador_Disparos y Bala_Network está vinculados al prefab del jugador, y Bala, al prefab de la bala.

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class Jugador_Disparos :  NetworkBehaviour {

public GameObject go_arma;
public GameObject go_bala;

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {
	siHayDisparo ();

}

void siHayDisparo(){
	if (!isLocalPlayer) {
		return;
	}

	if (Input.GetKeyDown (KeyCode.Mouse0)) {
		disparo ();
	}
}

void disparo(){
	Network.Instantiate (go_bala, new Vector3 (go_arma.transform.position.x, go_arma.transform.position.y, go_arma.transform.position.z), transform.rotation, 0);
}
}
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class Bala_Network : NetworkBehaviour {

[SyncVar]private Vector3 syncPos;

[SerializeField] Transform balaTransform;
[SerializeField] float lerpRate = 15;

private Vector3 ultimaPos;
private float threshold = 0.1f;

// Use this for initialization
void Start () {
}

// Update is called once per frame
void Update () {
	LerpPosition();
}

void FixedUpdate () {
	LlamarPos ();
}

void LerpPosition() {
	//Actualiza las posiciones de los jugadores
	//if (!isLocalPlayer) {
		balaTransform.position = Vector3.Lerp (balaTransform.position, syncPos, Time.deltaTime * lerpRate);
	//}
}

[Command]
void CmdEnvioPosServidor (Vector3 pos) {
	syncPos = pos;
	//Debug.Log ("Comando para posición");
}

[ClientCallback]
void LlamarPos() {
	//if (isLocalPlayer && Vector3.Distance(balaTransform.position, ultimaPos) > threshold) {
		CmdEnvioPosServidor (balaTransform.position);
		ultimaPos = balaTransform.position;
	//}
}
}
using UnityEngine;
using System.Collections;


public class Bala : MonoBehaviour {

public float Velocidad = 100f;
public float distancia_maximaxi = -25f;
public float distancia_maximaxd = 75f;
public float distancia_maximazi = -3f;
public float distancia_maximazd = 53f;

// Use this for initialization
void Start () {
	transform.Rotate (90, 0, 0);
}

// Update is called once per frame
void Update () {
	transform.Translate(new Vector3 (0, 1, 0)*Velocidad*Time.deltaTime);

	if (transform.position.z >= distancia_maximazd || transform.position.z <= distancia_maximazi || transform.position.x >= distancia_maximaxd || transform.position.x <= distancia_maximaxi)
		Destroy(gameObject);
}
}

¿Alguna idea sobre que puedo estar haciendo mal?

r2d2rigo

Las balas solo se crean en el cliente que las dispara, no heredan de NetworkBehaviour, no implementan campos que se transmiten por la red, etc.

1 respuesta
B

#2 Creo que estás equivocado, está usando Network.Instantiate, y este método se encarga de replicar el Instantiate en todos los clientes conectados, mira la documentación: http://docs.unity3d.com/ScriptReference/Network.Instantiate.html

#1 Te aconsejo que no Instancies las balas por red, en su lugar ten una variable en el controlador del personaje que se llame "IsShooting" o algo por el estilo, la sincronizas por la red, y cuando esté activo simplemente instancias localmente las balas de cada jugador.

De esta forma evitas generar tráfico innecesario, a menos que tus balas sean cohetes o algo por el estilo, pero si lo comparas con las balas que se disparan, por ejemplo, en Call of Duty, no son más que una simulación.

1 respuesta
Turco

#3 Las balas han de verse porque no van a una gran velocidad, y la idea es que los jugadores puedan esquivarlas.

Al final lo que hice fue instanciar la bala de manera local (con un instantiate a secas) y hacerle un NetworkServer.Spawn

Y aprovechando esto, me surgió otro problemilla, y es que las balas de uno mismo, no puedan hacer daño. Estaba intentando en el script de la bala, obtener el id del jugador para así en el método de OnTriggerEnter, meter la condición de si la bala es mia, la ignore, pero parece que no pueda obtener la id de un GameObject (el del jugador) desde un script de otro GameObject (el de la bala).

1 respuesta
B

#4 Qué quieres decir con pillar la id de un GameObject? Sería tan fácil como comprobar desde el componente de red si la bala es tuya, no recuerdo exactamente la sintaxis pero era algo así como this.gameObject.isMine, y sólo devolvía true si el objeto era tuyo y no de otro cliente.

Hace mucho que toqué el Networking que viene con Unity así que seguramente estoy rustido, (desde la 3.x), así que no estoy muy seguro de que se pueda seguir haciendo así.

1 respuesta
Turco

#5 Creo que eso lo puse en práctica a groso modo, pero no me funcionó. Le echaré un vistazo más detenidamente. Muchas gracias.

bLaKnI

Además, esa maldita manía de programador de domingo noche de hacer en una función los "if(blabla) return;"

No lo soporto. Coño, aprended a hacer correctamente la puta estructuración lógica!

if( isLocalPlayer && Input.GetKeyDown (KeyCode.Mouse0) ) ...

Usuarios habituales