- Home /
How do I instantiate/fire when Joystick input ends?
Hello World!
I have a twin stick shooter with the right joystick used to aim and fire. I want the character to fire when the JS is released (in the direction the character was last looking at). Currently, I'm not able to shoot. I'm not sure why.
public void playerLook()
{
bool canShoot = false;
Vector3 LookDir = new Vector3(shootJS.Horizontal * lookSpeed, 0f, shootJS.Vertical * lookSpeed);
Vector3 lastLook = Vector3.zero;
if (LookDir != Vector3.zero)
{
nav.transform.forward = LookDir;
lastLook = LookDir;
}
else { nav.transform.forward = lastLook;}
float x = shootJS.Horizontal; float z = shootJS.Vertical;
if (x != 0 || z != 0) //The player is aiming now and should shoot when the JS is released.
{ canShoot = true; }
if (canShoot==true)
{
if (x == 0 && z == 0) //if aiming, and the JS is released, check the condition for shooting and shoot.
{
if (currentMag > 0)
{
Instantiate(bullet, shotSpawn.position, shotSpawn.rotation);
currentMag--;
return;
}
else if (currentMag == 0)
{
StartCoroutine(reload());
}
}
}
}
IEnumerator reload()
{
ammo = ammo - mag;
currentMag = mag;
yield return new WaitForSeconds(reloadTime);
}
if (x != 0 || z != 0)
{ canShoot = true; }
if (canShoot==true)
if (x == 0 && z == 0)
It can't just magically become zero..
Doesn't this check for the JS inputs beco$$anonymous$$g 0 while the bool is true?
If this doesn't work logically, what kind of statement should I use?
I want to enable a bool when the JS is moved, disable it when input stops and trigger a single event. This event shouldn't trigger till the next time this cycle is repeated. Do you have any suggestions?
Answer by Captain_Pineapple · Sep 07, 2020 at 05:30 PM
Well in general @ShadyProductions pointed out the correct issue, however the solution is missing here. Only thing you are missing here in your code is that your variable canShoot
is a local one. Make that one a member of your class and reset it once you have reached the inner scope of if(x == 0 && y== 0)
This should then work.
Your current version does not work because you always set canShoot
to false and you will never enter both if statements for the input check in the same Update call.
@Captain_Pineapple
I did as you mentioned. However, I'm still seeing shots instantiated when I'm getting Joystick input. If you have the time, please do tell me how to rectify this.
Thank you
$$anonymous$$y whole code is as follows:
public bool canShoot;
// Start is called before the first frame update
void Start()
{
stateText.text = "";
nav = player.GetComponent<Nav$$anonymous$$eshAgent>();
animator = player.GetComponent<Animator>();
moveJS = GameObject.Find("Floating JS_$$anonymous$$ove").GetComponent<FloatingJoystick>();
shootJS = GameObject.Find("Floating JS_Shoot").GetComponent<FloatingJoystick>();
current$$anonymous$$ag = mag;
canShoot = false;
}
// Update is called once per frame
void Update()
{
movePlayer();
playerLook();
float x = shootJS.Horizontal; float z = shootJS.Vertical;
if (canShoot == true)
{
shoot();
}
if (x == 0 || z == 0)
{ canShoot = false; }
ammoCount.text = current$$anonymous$$ag + "/" + ammo;
Debug.Log(current$$anonymous$$ag);
}
public void movePlayer()
{
float x = moveJS.Horizontal;
float y = moveJS.Vertical;
nav.velocity = new Vector3(x * moveSpeed, 0, y * moveSpeed);
if (nav.velocity.x != 0 || nav.velocity.z != 0)
{ animator.SetBool("isRunning", true); }
else { animator.SetBool("isRunning", false); }
}
public void playerLook()
{
Vector3 LookDir = new Vector3(shootJS.Horizontal * lookSpeed, 0f, shootJS.Vertical * lookSpeed);
Vector3 lastLook = Vector3.zero;
if (LookDir != Vector3.zero)
{
nav.transform.forward = LookDir;
lastLook = LookDir;
}
else { nav.transform.forward = lastLook; }
float x = shootJS.Horizontal; float z = shootJS.Vertical;
if (x != 0 || z != 0) //The player is ai$$anonymous$$g now and should shoot when the JS is released.
{ canShoot = true; }
}
public void shoot()
{
if (current$$anonymous$$ag > 0)
{
Instantiate(bullet, shotSpawn.position, shotSpawn.rotation);
current$$anonymous$$ag--;
canShoot = false;
return;
}
else if (current$$anonymous$$ag == 0 && ammo != 0)
{
StartCoroutine(reload());
}
else if (ammo == 0)
{ return; }
}
IEnumerator reload()
{
ammo = ammo - mag;
current$$anonymous$$ag = mag;
yield return new WaitForSeconds(reloadTime);
}
}
i suggest you take out a paper and draw a diagramm of all possible states you can be in. This should help you in most cases to find your issue.. You now save the state by using a member variable but changed the conditions for some reason. This here does not really make sense does it? if (x == 0 || z == 0)
It does neither check if you are ai$$anonymous$$g nor check if you are not ai$$anonymous$$g since one axis can always be zero and make this be true.
What you basically need is to do the following in this order:
check if you aim (-> set canShoot to true in this case)
check if canShoot is True
if canShoot is True: {
check if ai$$anonymous$$g ends => if (x == 0 && z == 0)
if ai$$anonymous$$g ended call Shoot
. Shoot should then reset the flag canShoot = false
}
This way the player has to move the joystick to get into shooting mode, creates a bullet when ai$$anonymous$$g ends and then has to move the stick again to start this process anew.
Your answer
Follow this Question
Related Questions
Integer value randomly multiples itself by 3 or 2 for seemingly no reason. 2 Answers
How do I send a variable (after calculation) as the final variable to another game object 1 Answer
Baffling Input.Mouseposition problem. If statement not correctly working. 1 Answer
HoloLens: detect Airtap regardless of Raycast hit 0 Answers
Wanting timer to run after single click 2 Answers