Noticias

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

Problema al disparar en juego 2D

Iniciado por Bydark, Noviembre 21, 2018, 08:59:43 PM

Tema anterior - Siguiente tema
 
 
Muy buenas a todos, iré directamente al grano.
 
 
 
He hecho un sistema de disparo en un vídeojuego donde el personaje es un sprite 2d y el resto del juego es en 3D, por lo que los ejes en los que se desplaza el personaje son XZ.
 
He conseguido que dispare en 4 posiciones, accediendo al valor de un vector al que llamo mov, si movX vale 1, dispara en una dirección, si movZ vale -1, dispara en otra dirección, etc.
 
El problema es que sólo es capaz de acceder a movX y movZ cuando el personaje está andando, por lo que es imposible disparar si el personaje está quieto.
 
Os dejo el código y algunas imágenes, muchísimas gracias.
 
 
 
PD: Como podéis en el breve vídeo que he dejado justo debajo, el personaje no puede disparar si está quieto, en la parte de abajo podéis ver los valores de movX y movZ en la pestaña Animator.
 
 
 
Gameplay de ejemplo
 
 
 
 
 


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour {
 
public float speed = 1f;
 
Animator anim;
Rigidbody rb3d;
Vector3 mov;
public GameObject arrowPrefab;
 
void Start () {
   anim = GetComponent<Animator>();
   rb3d = GetComponent<Rigidbody>();
   
}

void Update () {
   //Sistema de movimiento
   
   mov = new Vector3 (
      Input.GetAxisRaw ("Horizontal"),
      0,
      Input.GetAxisRaw ("Vertical")
   );
 
                 ;
   transform.position = Vector3.MoveTowards (
 
      transform.position,
      transform.position + mov,
      speed * Time.deltaTime
 
   );
 
   if (mov != Vector3.zero) {
      anim.SetFloat ("movX", mov.x);
      anim.SetFloat ("movZ", mov.z);
      anim.SetBool ("walking", true);
   } else {
   
      anim.SetBool ("walking", false);
   
   
   }
 

   //Sistema de disparo
 
   if (Input.GetButtonDown ("Fire1") && mov.x == 1) {
      GameObject arrow = Instantiate (arrowPrefab, transform.position, Quaternion.identity);
      arrow.GetComponent<Rigidbody> ().velocity = new Vector2 (50.0f, 0.0f);
 
   }
   if (Input.GetButtonDown ("Fire1") && mov.x == -1) {
      GameObject arrow = Instantiate (arrowPrefab, transform.position, Quaternion.identity);
      arrow.GetComponent<Rigidbody> ().velocity = new Vector2 (-50.0f, 0.0f);
 
   }
   if (Input.GetButtonDown ("Fire1") && mov.z == 1) {
      GameObject arrow = Instantiate (arrowPrefab, transform.position, Quaternion.identity);
      arrow.GetComponent<Rigidbody> ().velocity = new Vector3 (0.0f, 0.0f,50.0f);
 
   }
   if (Input.GetButtonDown ("Fire1") && mov.z == -1) {
      GameObject arrow = Instantiate (arrowPrefab, transform.position, Quaternion.identity);
      arrow.GetComponent<Rigidbody> ().velocity = new Vector3 (0.0f, 0.0f,-50.0f);
 
   }
}
void FixedUpdate(){

//Sistema de movimiento
   rb3d.MovePosition (rb3d.position + mov * speed * Time.deltaTime);




}
 
}

 
 

Cita de: Bydark date=1542830383El problema es que sólo es capaz de acceder a movX y movZ cuando el personaje está andando, por lo que es imposible disparar si el personaje está quieto.
   
   
      Os dejo el código y algunas imágenes, muchísimas gracias.
   


Disparar y andar no tienen nada que ver (en el 99% de los juegos), incluso es buena practica que diseñes estos comportamientos de forma separada , mismo script, varios scripts, no importa, pero que actúen independientemente.
 
Esto pasa porque para disparar estás evaluando valores positivos y negativos de "Mov", ya que mov es una delta cuando tengas mov nulo (quieto) no se mete a los if's, podrías tocar esto y aquello y que ande, pero yo iría por lo de arriba, movelo por un lado, dispará por el otro.
 
Si le ponés algo así te va a funcionar(creo) de cinta adhesiva, pero ni lo vale:
 

if (Input.GetButtonDown ("Fire1") && mov == Vector3.zero)
{
//disparar quieto
}

 
 

Cita de: lightbug date=1542837521Disparar y andar no tienen nada que ver (en el 99% de los juegos), incluso es buena practica que diseñes estos comportamientos de forma separada , mismo script, varios scripts, no importa, pero que actúen independientemente.
   
   
      Esto pasa porque para disparar estás evaluando valores positivos y negativos de "Mov", ya que mov es una delta cuando tengas mov nulo (quieto) no se mete a los if's, podrías tocar esto y aquello y que ande, pero yo iría por lo de arriba, movelo por un lado, dispará por el otro.
   
   
      Si le ponés algo así te va a funcionar(creo) de cinta adhesiva, pero ni lo vale:
   
   

if (Input.GetButtonDown ("Fire1") && mov == Vector3.zero)
{
//disparar quieto
}

   
       
   


Muchas gracias por contestar, acabo de probar la solución que ofreces como "cinta adhesiva", pero no me funciona, lo único que hace es disparar quieto en una sola dirección ( la que le indique en su vector )
 
 
 
No sé si ahora serás capaz de hacer que de la misma manera, dispare en todas las direcciones estando quieto, pero teniendo en cuenta a donde esté mirando el personaje, no consigo sacarlo adelante, millones de gracias. 

Cita de: Bydark date=1542842300Muchas gracias por contestar, acabo de probar la solución que ofreces como "cinta adhesiva", pero no me funciona, lo único que hace es disparar quieto en una sola dirección ( la que le indique en su vector )
   


claro, es que así lo pensé, no es una "solución" es más para mostrar como disparar quieto, si seguís haciendolo así como lo tenés vas a tener que meter o más if's o cambiar argumentos, pero solo para mostrar que el problema era en el "positivo/negativo" del argumento.
 
 
 
Cita de: Bydark date=1542842300No sé si ahora serás capaz de hacer que de la misma manera, dispare en todas las direcciones estando quieto, pero teniendo en cuenta a donde esté mirando el personaje, no consigo sacarlo adelante, millones de gracias. 
   


Hacelo por partes, pensalo así, siempre se puede disparar, y siempre podés moverte, son independientes, aunque tienen algo en común (en este caso porque tenés un sprite supongo), y es que la dirección de movimiento determina "hacia donde donde mirás "(no lo penses como "hacia donde disparás") podés llevar registro de la dirección y sentido de vista con un vector, entonces si te movés hacia arriba tu "lookAt" será un vector3 con z positivo (para seguir la línea de tu código), si mirás para abajo será negativo, lo mismo para izq y der
 

Vector3 lookAt
 
void Update(){
Move();   //Si te vas a mover con FUpdate esta func solo hace de recolector de entradas (GetAxis...)
Fire();

   
}
void Move()
{
  mov = new Vector3 ( Input.GetAxisRaw ("Horizontal"), 0, Input.GetAxisRaw ("Vertical"));
  //algo se apreta entonces cambia lookAt, una manera de llevar registro de adonde mira
  if(mov != Vector3.zero)
      lookAt = mov.normalized;
 
//Esto no se porque está aca?
     transform.position = Vector3.MoveTowards (
              transform.position,
              transform.position + mov,
              speed * Time.deltaTime
     );
//OJO ... me comí la parte de animación
}
void Fire()
{
if (Input.GetButtonDown ("Fire1") {
   GameObject arrow = Instantiate (arrowPrefab, transform.position, Quaternion.identity);
   //aca entra lookAt, normalmente acá pondrías un transform.forward o por el estilo
   arrow.GetComponent<Rigidbody> ().velocity = lookAt * 50;
}
}
         
void FixedUpdate(){   
rb3d.MovePosition (rb3d.position + mov * speed * Time.deltaTime);
}
         
   ... (y lo que falte)

 
No digo que esto esté bien pero es una pequeña forma de separar las cosas dentro de lo que tenés ... y nada, fijate que te estás moviendo en mundo transform y en rigidbody, yo le sacaría lo del MoveTowards.
 
Saludos

Noviembre 22, 2018, 05:59:40 PM #4 Ultima modificación: Noviembre 22, 2018, 07:54:28 PM por Bydark
Cita de: lightbug date=1542848343claro, es que así lo pensé, no es una "solución" es más para mostrar como disparar quieto, si seguís haciendolo así como lo tenés vas a tener que meter o más if's o cambiar argumentos, pero solo para mostrar que el problema era en el "positivo/negativo" del argumento.
   
   
       
   
   
      Hacelo por partes, pensalo así, siempre se puede disparar, y siempre podés moverte, son independientes, aunque tienen algo en común (en este caso porque tenés un sprite supongo), y es que la dirección de movimiento determina "hacia donde donde mirás "(no lo penses como "hacia donde disparás") podés llevar registro de la dirección y sentido de vista con un vector, entonces si te movés hacia arriba tu "lookAt" será un vector3 con z positivo (para seguir la línea de tu código), si mirás para abajo será negativo, lo mismo para izq y der
   
   

Vector3 lookAt
 
void Update(){
Move();   //Si te vas a mover con FUpdate esta func solo hace de recolector de entradas (GetAxis...)
Fire();

   
}
void Move()
{
  mov = new Vector3 ( Input.GetAxisRaw ("Horizontal"), 0, Input.GetAxisRaw ("Vertical"));
  //algo se apreta entonces cambia lookAt, una manera de llevar registro de adonde mira
  if(mov != Vector3.zero)
      lookAt = mov.normalized;
 
//Esto no se porque está aca?
     transform.position = Vector3.MoveTowards (
              transform.position,
              transform.position + mov,
              speed * Time.deltaTime
     );
//OJO ... me comí la parte de animación
}
void Fire()
{
if (Input.GetButtonDown ("Fire1") {
   GameObject arrow = Instantiate (arrowPrefab, transform.position, Quaternion.identity);
   //aca entra lookAt, normalmente acá pondrías un transform.forward o por el estilo
   arrow.GetComponent<Rigidbody> ().velocity = lookAt * 50;
}
}
         
void FixedUpdate(){   
rb3d.MovePosition (rb3d.position + mov * speed * Time.deltaTime);
}
         
   ... (y lo que falte)

   
      No digo que esto esté bien pero es una pequeña forma de separar las cosas dentro de lo que tenés ... y nada, fijate que te estás moviendo en mundo transform y en rigidbody, yo le sacaría lo del MoveTowards.
   
   
      Saludos
   


Millones de gracias, al final lo he resuelto de esta manera; 
 

if (ultPos == 0) { ultPos = 4; }
if (mov.x == 1) { ultPos = 1; }
if (mov.x == -1) { ultPos = 2; }
if (mov.z == 1) { ultPos = 3; }
if (mov.z == -1) { ultPos = 4; }
float distancia = 1f;
 
   if (Input.GetButtonDown ("Fire1") && ultPos == 1) {
      GameObject arrow = Instantiate (arrowPrefab, transform.position + new Vector3(distancia,0,0), Quaternion.identity);
      arrow.GetComponent<Rigidbody> ().velocity = new Vector2 (50.0f, 0.0f);
 
   }
   if (Input.GetButtonDown ("Fire1") && ultPos == 2) {
      GameObject arrow = Instantiate (arrowPrefab, transform.position + new Vector3(-distancia,0,0), Quaternion.identity);
      arrow.GetComponent<Rigidbody> ().velocity = new Vector2 (-50.0f, 0.0f);
 
   }
   if (Input.GetButtonDown ("Fire1") && ultPos == 3) {
      GameObject arrow = Instantiate (arrowPrefab, transform.position + new Vector3(0,0,distancia), Quaternion.identity);
      arrow.GetComponent<Rigidbody> ().velocity = new Vector3 (0.0f, 0.0f,50.0f);
 
   }
   if (Input.GetButtonDown ("Fire1") && ultPos == 4) {
      GameObject arrow = Instantiate (arrowPrefab, transform.position  + new Vector3(0,0,-distancia), Quaternion.identity);
      arrow.GetComponent<Rigidbody> ().velocity = new Vector3 (0.0f, 0.0f,-50.0f);
 
   }

 
EJEMPLO DE COMO HAN QUEDADO LOS DISPAROS

Etiquetas: