Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Fire a bullet in players last moved direction.

Discussion in 'Scripting' started by Brandon-Keeler, Nov 9, 2014.

  1. Brandon-Keeler

    Brandon-Keeler

    Joined:
    Oct 27, 2014
    Posts:
    75
    So I have this player (right now it is a sphere rolling around). This sphere has a game object called "weapon spawn point". Attached to weapon spawn point is a script that instantiates and fires a bullet prefab when I left click my mouse.

    Attached to the bullet prefab is the following script.
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class BulletManager : MonoBehaviour
    5. {
    6.     private float speed = 20f;
    7.     // Use this for initialization
    8.     void Awake ()
    9.     {
    10.         transform.rigidbody.velocity = Vector3.forward * speed;
    11.         Destroy (gameObject, 1f);
    12.     }
    13. }
    14.  
    When I move my character around and left click my mouse, the instantiated bullet only moves forward along the z axis regardless on the direction the player is facing. Now my question is how do I get my player's bullet to fire in the direction (x,z) last moved by my player (or the way my player is facing).
     
    Last edited: Nov 9, 2014
  2. GetUpKidAK

    GetUpKidAK

    Joined:
    Apr 9, 2013
    Posts:
    84
    You'll need to change Vector3.forward to transform.forward.

    Vector3.forward is always 0, 0, 1 in world space, transform.forward is the local z direction.
     
  3. Brandon-Keeler

    Brandon-Keeler

    Joined:
    Oct 27, 2014
    Posts:
    75
    That doesn't quite work, because my character is a sphere, and as I roll around it shoots all over the place (including upwards).
     
  4. GetUpKidAK

    GetUpKidAK

    Joined:
    Apr 9, 2013
    Posts:
    84
    Sorry, I missed that bit. You do want the bullet rigidbody velocity to be transform.forward otherwise it will always go in the same direction (World Z forward). The problem is with the object that is spawning the bullets - if it's a child object that it's rotating with the sphere and it's forward direction is spinning all over the place.

    I assume you want the bullet to fire in the direction the player is moving? In that case you should be able to use the player inputs (plugged into a Vector3) as the direction to fire in.
     
  5. Brandon-Keeler

    Brandon-Keeler

    Joined:
    Oct 27, 2014
    Posts:
    75
    "

    That won't quite work either. Consider this scenario. I am moving forward really fast, and I hit the left arrow once. I wouldn't want my player to fire left, as my players isn't left. Also if my player stops moving, where will it fire. I was just wondering if there was a way to "lock" my firing to only hit in front of the player.
     
  6. A.Killingbeck

    A.Killingbeck

    Joined:
    Feb 21, 2014
    Posts:
    483
    Will your camera always look towards the player? If so, that's always a good starting point.
     
  7. Brandon-Keeler

    Brandon-Keeler

    Joined:
    Oct 27, 2014
    Posts:
    75
    My camera is 10 units, back and up, from the player, regardless of the way it is facing, or the rotation of the player. Meaning if my player moves "World Z" Forward, it moves exactly as much in the same direction. Same for all directions. Right now this is temporary, but I want the weapon worked out first. Basically think of it only rotating around the x and z axis, not y, following the player where he moves.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class CameraController : MonoBehaviour {
    5.  
    6.     public GameObject player;
    7.     private Vector3 offset;
    8.     // Use this for initialization
    9.     void Start () {
    10.         offset = transform.position;
    11.     }
    12.    
    13.     // LateUpdate is called once per frame after Update
    14.     void LateUpdate () {
    15.         transform.position = player.transform.position + offset;
    16.     }
    17. }
     
    Last edited: Nov 10, 2014
  8. Maximillion

    Maximillion

    Joined:
    Dec 20, 2013
    Posts:
    22
    Unparent WeaponSpawnPoint from the sphere, and set its location and Y rotation using a script?
     
  9. GetUpKidAK

    GetUpKidAK

    Joined:
    Apr 9, 2013
    Posts:
    84
    I was going to suggest this, but it wouldn't change the WeaponSpawnPoint Z axis at any point, so it would effectively be the same as using Vector3.forward.
     
  10. Maximillion

    Maximillion

    Joined:
    Dec 20, 2013
    Posts:
    22
    Unless im missunderstanding the original question, what i suggested should work fine.. If you clone the spheres World Y rotation and set it to the WeaponSpawnPoints Y rotation its Z would be facing foward relative to the sphere. And then use transform.forward on the WeaponSpawnPoint.

    But again it may not work in practice - i am unable to test it at the moment.
     
  11. GetUpKidAK

    GetUpKidAK

    Joined:
    Apr 9, 2013
    Posts:
    84
    Code (CSharp):
    1.     public Rigidbody attachedObj;
    2.  
    3.     void FixedUpdate()
    4.     {
    5.         transform.position = attachedObj.position;
    6.  
    7.         transform.rotation = Quaternion.LookRotation(attachedObj.velocity);
    8.     }
    Put together quickly to test, but this seems to work like I *think* you want it to work.

    Add that to your separated Weapon Spawn object and it should point in the direction that the ball is rolling. You can spawn in transform.forwards direction then.

    I may have massively over-thought this now, though!
     
  12. Brandon-Keeler

    Brandon-Keeler

    Joined:
    Oct 27, 2014
    Posts:
    75
    It worked like I wanted, but brought up an additional issue. I have a PlayerController script. Inside this script is the ability for my character to jump. When I am jumping up, or falling down, the shots don't shoot correctly and fire up and down.

    For reference this is my script...
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class PlayerController : MonoBehaviour
    4. {
    5.     //Variables
    6.     public GameObject player;
    7.     public float speed;
    8.     private float value = 0;
    9.     private float moveHorizontal;
    10.     private float moveVertical;
    11.     bool spaceKeyDown = false;
    12.     bool isGrounded = false;
    13.  
    14.     void OnCollisionEnter (Collision col)//Test if player is on the ground
    15.     {
    16.         if(col.gameObject.name == "Ground 1")
    17.         {
    18.             isGrounded = true;
    19.         }
    20.     }
    21.  
    22.     void OnCollisionExit (Collision col)//Test if player is off the ground
    23.     {
    24.         if(col.gameObject.name == "Ground 1")
    25.         {
    26.             isGrounded = false;
    27.         }
    28.     }
    29.  
    30.     void Update ()//For Input Data
    31.     {
    32.         moveHorizontal = Input.GetAxis ("Horizontal");
    33.         moveVertical = Input.GetAxis ("Vertical");
    34.         if(Input.GetButtonDown("Jump"))
    35.            {
    36.             spaceKeyDown = true;
    37.             //Debug.Log("Space Key Pressed. Frame: " + Time.frameCount);
    38.         }
    39.     }
    40.  
    41.     void FixedUpdate ()//For Physics Data
    42.     {
    43.         JumpData ();
    44.         Vector3 movement = new Vector3 (moveHorizontal, value/speed , moveVertical);
    45.         rigidbody.AddForce(movement * speed * Time.deltaTime);//Value (jump height) is not effected by speed.
    46.         value = 0;//Make sure value is 0 after jump sequence.
    47.     }
    48.     void JumpData()
    49.     {
    50.         if (isGrounded == true)
    51.         {
    52.             if (spaceKeyDown == true)
    53.             {
    54.                 spaceKeyDown = false;
    55.                 value = 9.8f * 1500f;
    56.             }
    57.             else {value = 0;}
    58.         }
    59.         else {value = 0;}
    60.         spaceKeyDown = false;
    61.     }
    62. }
     
  13. GetUpKidAK

    GetUpKidAK

    Joined:
    Apr 9, 2013
    Posts:
    84
    It should work if you zero out the rigidbody's y velocity when assigning it to the Weapon Spawn object.
     
  14. Brandon-Keeler

    Brandon-Keeler

    Joined:
    Oct 27, 2014
    Posts:
    75
    I cant figure out how to do that, when I try it brings up an error saying

    Assets/Scripts/shootBullet.cs(22,39): error CS1612: Cannot modify a value type return value of `UnityEngine.Rigidbody.velocity'. Consider storing the value in a temporary variable.

    Also I found out that when I am running the code (before any edits), before I even move my player I get the following repeating error...

    Look rotation viewing vector is zero
    UnityEngine.Quaternion:LookRotation(Vector3)
    shootBullet:FixedUpdate() (at Assets/Scripts/shootBullet.cs:23)
     
  15. GetUpKidAK

    GetUpKidAK

    Joined:
    Apr 9, 2013
    Posts:
    84
    Try this in place of what I suggested before:

    Code (CSharp):
    1.     public Rigidbody attachedObj;
    2.  
    3.     void FixedUpdate()
    4.     {
    5.         transform.position = attachedObj.position;
    6.  
    7.         Vector3 newRot = new Vector3(attachedObj.velocity.x, 0f, attachedObj.velocity.z);
    8.  
    9.         transform.rotation = Quaternion.LookRotation(newRot);
    10.     }
    I've not tested it, but I think that will work. You're basically telling it to use the rigidbody velocity, but rigging its vertical velocity to zero.

    The 'Look rotation viewing vector is zero' message is just because Quaternion.LookRotation takes a direction and converts that direction to a rotation, which it obviously can't do with Vector.zero. I'm not aware of it causing any issues, but you can put the LookRotation line in an if statement that checks if the rotation is equal to Vector.zero first if you want to remove it.
     
  16. Brandon-Keeler

    Brandon-Keeler

    Joined:
    Oct 27, 2014
    Posts:
    75
    My bullet is shooting how it is supposed to. That error message is annoying though. How do I go about removing it. I'm new to the LookRotation.
     
  17. GetUpKidAK

    GetUpKidAK

    Joined:
    Apr 9, 2013
    Posts:
    84
    You just need to add something like:

    Code (CSharp):
    1. void FixedUpdate()
    2.     {
    3.         transform.position = attachedObj.position;
    4.  
    5.         Vector3 newRot = new Vector3(attachedObj.velocity.x, 0f, attachedObj.velocity.z);
    6.  
    7.         if (newRot != Vector.zero)
    8.                 transform.rotation = Quaternion.LookRotation(newRot);
    9.     }
     
  18. Brandon-Keeler

    Brandon-Keeler

    Joined:
    Oct 27, 2014
    Posts:
    75
    Thanks, everything is working perfectly now. Here is my final code.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class shootBullet : MonoBehaviour
    5. {
    6.     public GameObject projectile;
    7.     public Rigidbody attachedObj;
    8.     void Update ()
    9.     {
    10.         if (Input.GetButtonDown("Fire1"))//left control and left mouse button
    11.         {
    12.             // instantiate a prefab, at the position of the object that has this script, with the default rotation (gameobject rotation ignored)
    13.             Instantiate(projectile, transform.position, transform.rotation);
    14.         }
    15.     }
    16.    
    17.     void FixedUpdate()
    18.     {
    19.         transform.position = attachedObj.position;
    20.        
    21.         Vector3 newRot = new Vector3(attachedObj.velocity.x, 0f, attachedObj.velocity.z);
    22.        
    23.         if (newRot != Vector3.zero)
    24.             transform.rotation = Quaternion.LookRotation(newRot);
    25.     }
    26. }