Search Unity

How should I code my gun to shoot?

Discussion in 'Getting Started' started by Gabrieldonley, Dec 11, 2015.

  1. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Hi there,
    I'm very new to Unity and I'm working on a 2D infinite scrolling shooter game. I have the basic scene completed and I'm just using it as stand-ins until I can get a good designer!! Well, anyway, I have a stationary character behind a gun who is supposed to shoot at passing enemies. To keep this question simple, how can I make it so that wherever I click on the screen (providing its not the pause button) then the projectile shoots? I have it so when I click Mouse0, The projectile shoots, but it just translates straight up. Could someone please help me with this? Thanks in advance!:)
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Try using Quaternion.RotateTowards as shown in the sample code to rotate the projectile towards the point clicked.

    You will first need to translate the screen point clicked into a point in the world... Camera.ScreenToWorldPoint ought to do that for you.

    Good luck, and welcome to the community!
     
    Ryiah likes this.
  3. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Thanks Joe! I'll try that in a sec! Sounds like it should work!
     
  4. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Hi Joe,
    So I took the Quaternion.RotateTowards documentation and implemented it in my projectile script just where it said to. Then I took the Camera.ScreenToWorldPoint docu and put that in my script. Surprisingly, I only had 1 error. Speed in the quaternion needs to be defined. I made a new public bool and called it speed but it gave me this error message: Operator '*' cannot be applied to operands of type 'bool' and 'float' Hope this helps! Thanks
     
  5. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Well, of course you can't just throw bits of code into a method and expect it to work — it's not a cake. :) If you're trying to multiply a bool by a float then, yeah, something has gone seriously sideways.

    But this is the Getting Started forum, and we're here to help. Post your code (properly enclosed in CODE tags — easy trick is to use the Insert button, in the formatting bar between the movie filmstrip and the floppy disk) here, and we'll have a look.

    EDIT: Actually, it may just be that you made your speed property a bool instead of a float. Bool means true or false, so what would that mean here? Speed or no speed? Makes no sense. Speed should be something like number of units per second, i.e., a number (float).
     
    Ryiah likes this.
  6. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    ok you were totally right. I change it to public float speed because it was a float. So Here is my code, thanks for the help!: Also, sorry I'm not quite sure how to enclose my code in tagso_O

    public Transform target;
    public float speed;

    void OnDrawGizmosSelected() {
    Camera camera = GetComponent<Camera>();
    Vector3 p = camera.ScreenToWorldPoint(new Vector3(100, 100, camera.nearClipPlane));
    Gizmos.color = Color.yellow;
    Gizmos.DrawSphere(p, 0.1F);
    }

    // Use this for initialization
    void Start () {

    }

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

    float step = speed * Time.deltaTime;
    transform.rotation = Quaternion.RotateTowards(transform.rotation, target.rotation, step);

    }
     
  7. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I told you how to enclose your code in tags; if you can help me make that clearer, I'd appreciate it! Here's a picture that may help:
    OK, now, what is OnDrawGizmosSelected in there for? You've added code that draws a sphere gizmo at location 100,100 in the screen. I don't see much point in that. (Never copy & paste code you don't understand; achieve understanding first, then grab whatever bits of it is useful to your needs.)

    Then, your Update method... on every frame, this makes the object rotate to match some target object. That's my fault; I pointed you to the wrong method! I meant to point you toward Quaternion.LookRotation. You want to make your projectile look at the point clicked, not match the rotation of some other object. So sorry for the confusion.

    OK, so to lay it all out a bit more neatly, your tasks are:
    1. Get a basic understanding of programming concepts, and basic C# syntax, so that you can understand the code you read. I recommend going through all the tutorials at http://www.learncs.org/.
    2. Make a script that, when you click the mouse, calculates the world position clicked (using ScreenToWorldPoint). Print that out with Debug.Log, or prove that it works by moving some other object to that position.
    3. Now use Quaternion.LookRotation to point your newly instantiated projectile towards that location when you instantiate it.
    That should be it... none of it's very difficult, but it does require a basic grasp of coding. I say that only because we occasionally get folks here who don't understand a thing about code and don't seem especially eager to learn, but think they can make a game just by pasting together snippets they get here and there. It doesn't work. But if you're willing to start at the beginning and patiently level up your skills, you'll be a powerful code wizard before you know it!
     
  8. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Ok, thanks Joe! I've been coding for a while, but when it comes to games...I'm just a big noob! And Unity for that matter. Sorry to stretch this conversation out, but can I let you know if there's anything else that doesn't work?
     
  9. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Uh one more thing. I feel extremely overwhelmed and I just can't seemed to grasp how to write the code for each thing I want. I've been trying to go over the learncs but it's a little hard to tie it in with what I want to do in my script.
     
  10. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    If it makes any difference, now here is my code. I used to make it so that when mouse0 was pressed, the item (projectile) was translated up, but that's extremely boring for it to go straight up, and that's what inspired me to make a WorldToPoint. Here's the code I recently updated:
    Code (CSharp):
    1. public class FelixShooting : MonoBehaviour {
    2.    
    3.     public Transform target;
    4.     public float speed;
    5.     public bool shot;
    6.  
    7.     void WhenProjectileShot() {
    8.         Camera camera = GetComponent<Camera>();
    9.         Vector3 p = camera.ScreenToWorldPoint(new Vector3(100, 100, camera.nearClipPlane));
    10.     }
    11.  
    12.     // Use this for initialization
    13.     void Start () {
    14.     }
    15.    
    16.     // Update is called once per frame
    17.     void Update () {
    18.  
    19.         if (Input.GetKeyDown(KeyCode.Mouse0)) {
    20.             transform.Translate(Vector3.up * 0.8f);
    21.  
    22.  
    23.         Vector3 relativePos = target.position - transform.position;
    24.         Quaternion rotation = Quaternion.LookRotation(relativePos);
    25.         transform.rotation = rotation;
    26.  
    27.         }
    28.     }
    29. }
     
  11. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Sure, we're happy to keep helping as long as you're making an effort too. And I can see you're making progress already!

    So you've made a WhenProjectileShot method, but nothing's calling that as far as I can see. Maybe you want to call that from Update when the mouse button goes down? (Incidentally, GetMouseButtonDown is probably a better way to check for that.)

    And of course the method doesn't actually do anything yet (assigning a couple local variables has no effect). I'm assuming you haven't learned about the debugger yet, so you need some way to know whether the point p you've calculated here is correct. Try adding
    Code (CSharp):
    1. Debug.Log("p:" + p);
    to that method.

    Now, what you want is to see a position in the world that corresponds to the point clicked. Make that your first goal. You're not there yet. But start by seeing what you've got, by adding that debug output and studying what it tells you, and then figure out how to modify the code to get what you want.

    And do go through all the tutorials at learncs. Every one. It doesn't matter whether you can yet see how it relates to your needs... I guarantee you that it does, and it will save you tons of time. So don't worry about that. Just try to grasp what each lesson has to teach you, and accept that you're building the skills you need.

    It's like somebody wants to build a house, but has never picked up a hammer. They're climbing into the big construction machines and poking at buttons because that's what they've seen real construction workers do, and the guys are like, dood, let's start by nailing these two boards together. You might object that you don't want two boards nailed together; you want a house. But you have to learn to use the tools before you can build a house... you see where I'm going here. :)
     
  12. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Ok, I'll go over the tutorials and see if I can't kind of work it out from there! Thanks!
     
  13. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Oh one thing before I go. How do you call a variable to a method, or whatever it was you were talking about I needed to do with WhenProjectileShot?
     
  14. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    That's the last lesson at learncs.org. Basically you just give the name of the method, followed by parentheses (which enclose any arguments you need to pass with the call). You're calling methods already; you just don't understand what you're doing. :) Those tutorials will help. And if anything is confusing, do feel free to post questions about it — we're happy to help!
     
  15. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Ah, I see what I was missing out on when I didn't do these tutorials:). I understand a lot more about everything since I went through them. I found it helpful to make a new project in my text editor and write new code in the C# examples. So, I went back through the methods chapter, and called the WhenProjectileShot() in the update method, but it's saying my my debug.log that 'p' is not related in this context. If you want, here is my code so far:
    Code (CSharp):
    1. public Transform target;
    2.     public float speed;
    3.  
    4.     void WhenProjectileShot() {
    5.         Camera camera = GetComponent<Camera>();
    6.         Vector3 p = camera.ScreenToWorldPoint(new Vector3(100, 100, camera.nearClipPlane));      
    7.     }
    8.  
    9.     // Use this for initialization
    10.     void Start () {
    11.     }
    12.    
    13.     // Update is called once per frame
    14.     void Update () {
    15.  
    16.         WhenProjectileShot ();
    17.  
    18.         if (Input.GetMouseButtonDown(0)) {
    19.             //transform.Translate(Vector3.up * 0.8f);
    20.             Debug.Log ("p:" + p);
    21.  
    22.         }
    23.  
    24.         Vector3 relativePos = target.position - transform.position;
    25.         Quaternion rotation = Quaternion.LookRotation(relativePos);
    26.         transform.rotation = rotation;
    27.  
    28.        
    29.     }
     
  16. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I don't think it's saying that, because there's no such error. Programming is all about being precise — you have to say exactly what you mean, and this is a good habit when asking about programming, too. Error messages make sense; "not related in this context" doesn't.

    It's probably saying that p is not defined in this context. Defined means, you have a variable declaration for it that applies to that context. That could be a local variable in this method (not in some other method — the whole point of local variables is that they're local to the method or block they're declared in). Or it could be a parameter, or a property in the class. If you need more explanation of any of these terms, just say so!

    In this case, you've declared p in the WhenProjectileShot method. But then you're trying to Debug.Log it in the Update method. No can do; one method can't get to another method's locals.

    So, you'll probably want to move that Debug.Log up into WhenProjectileShot, so it can actually access p.

    Then, you should reconsider where you're calling WhenProjectileShot. Remember, the Update method gets called on every frame. Do you really want to call WhenProjectileShot on every frame? Or do you only want to call it when certain conditions are true?

    You're making good progress... keep going!
     
  17. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Well, I have to say I think I'm making a bit of progress. I moved my debug up into the WhenProjectileShot, and then created an if statement in update, so that only on certain terms would the action be executed and WhenProjectileShot work. This is the debug message I recieved and I'm not sure if it's what we want:
    Code (CSharp):
    1. p:(-0.2, -1.9, 0.3)
    2. UnityEngine.Debug:Log(Object)
    3. FelixShooting:WhenProjectileShot() (at Assets/Scripts/FelixShooting.cs:15)
    4. FelixShooting:Update() (at Assets/Scripts/FelixShooting.cs:28)
    5.  
     
  18. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Right. Now, the idea is, that position (-0.2, -1.9, 0.3) above should be the point in the world that you want your projectile to point at. Is it? Check by creating a cube or something, and just setting its position to that. Is it in the position you thought you clicked?

    (Hint: it won't be. Check exactly what point you're converting from Screen to World coordinates. You're passing in a constant 100, 100 right now... it'll work better if you pass in the mouse position!)
     
  19. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    OHHHHHHH wow that makes total sense. I just drew a yellow sphere and when I clicked nothing obviously happened, it went to wherever 100, 100 was. So now, what exactly am I supposed to use for mouse position? Does that just go in the ScreenToWorldPoint? Thanks a lot!
     
  20. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Yep, you would use Input.mousePosition, though the example given in the docs for that one is unusually bad — I can't imagine why you would cast a ray through the mouse, and if it hits something, create a particle system at the position of the object with the script on it!

    Anyway, the only tricky thing here is, a mouse moves in 2 dimensions (x and y), but a world in Unity can be 3D (x, y, and z). So, how do you convert this 2D input into a 3D position? There are two common techniques:
    1. Cast a ray through the mouse position, and see where that intersects something in the world.
    2. Assume a constant Z (or more simply, a constant distance from the camera).
    If you're making a 2D game, then option 2 is simpler. In that case you would use something like:

    Code (CSharp):
    1.  Vector3 p = camera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,, Input.mousePosition.y, camera.nearClipPlane));
    But you might have to fiddle with the Z value to get exactly what you want; that is, camera.nearClipPlane may not be the right distance. And if that still gives you trouble (whether it will or not depends on the geometry of your game), you can always switch to method 1... which would look a lot like the very last example at the bottom of the Physics.RayCast page.
     
  21. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Well let's see. I'm noticing that most of my code doesn't recognize 'p'. It's got a question mark next to it when I hover over it. Also, just to make sure I'm following along, are we still trying to get a yellow sphere to go where I click, or are we trying to get my projectile to shoot where I click now? Thanks so much. Here is my code so far. Even though I haven't gotten it yet, I feel like I'm learning much more already!!
    Code (CSharp):
    1. public Transform target;
    2.     public float speed;
    3.  
    4.     void WhenProjectileShot() {
    5.         Camera camera = GetComponent<Camera>();
    6.         Vector3 p = camera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, camera.nearClipPlane));
    7.         Gizmos.color = Color.yellow;
    8.         Gizmos.DrawSphere(p, 0.1f);
    9.    
    10.         if (Input.GetMouseButtonDown(0)) {
    11.             transform.Translate(Vector3.up * 0.8f);
    12.             Debug.Log ("p:" + p);
    13.            
    14.         }
    15.     }
    16.  
    17.     // Use this for initialization
    18.     void Start () {
    19.     }
    20.    
    21.     // Update is called once per frame
    22.     void Update () {
    23.  
    24.         if (Input.GetMouseButtonDown (0)) {
    25.             WhenProjectileShot ();  
    26.         }
    27.  
    28.         Vector3 relativePos = target.position - transform.position;
    29.         Quaternion rotation = Quaternion.LookRotation(relativePos);
    30.         transform.rotation = rotation;
    31.  
    32.        
    33.     }  
     
  22. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    "p" is a local variable, and will be usable by any other code in the same method. It will not be recognizable by code in other methods. (I'm assuming that you understand what methods are by now!)

    And, yeah, don't worry about the projectile yet — the goal is to determine what point in the world was clicked. Once you can do that, then you can figure out how to point your projectile at it. But first things first. Drawing a sphere, or using the Debug.Log, or whatever — those are just ways to see whether you are computing the right point in the world.

    The way you have your code now is a bit funny. Update runs every frame, but only when the mouse button goes down, you call WhenProjectileShot. WhenProjectileShot (which is only called when the mouse button goes down, remember) draws a sphere, and then checks again if the mouse button has gone down. Not much point in that, is there?

    But anyway, I see you've added Gizmos.DrawSphere as an attempt to see what point you're computing. But I don't think you can do that — gizmos are something different (they're used to draw selection handles and stuff in the scene editor). There are other ways to draw debugging stuff in the actual game view, but let's not get distracted. Just use your Debug.Log coordinates, and if you have trouble visualizing the point it's reporting, then manually create a sphere in the scene, and manually type in the X, Y, and Z coordinates for its position according to the point reported. This will help you get a better understanding of how coordinates work in your setup anyway.

    And the question is: is p now the point you expect, based on where you clicked?
     
  23. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    I see now. About my debug.log coordinates, they won't let me write in those 3 number decimals, because when I put them in, I get an error that says something like this cannot hold 3 units or something like that. Again, am I writing in the debug.log those three numbers I showed you in a few posts ago?
     
  24. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    No, the Debug.Log you have above is correct. It prints out the value of p. It even nicely labels it with "p: ". It's perfect; don't mess with it.

    Now I want to know is: is the value you see in the console, printed out by the Debug.Log, a correct position or not?

    And you should be asking yourself "well how should I know?" And then you should re-read the above messages, where I suggest manually creating a sphere (or cube or whatever), and using the inspector to set the sphere to that position, so you can see whether or not it is correct.
     
  25. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Ha, that's pretty cool. The funny thing is, I can't remember whether I clicked there or not originally! But, I mean it seems pretty accurate. For some reason, I'm not seeing my debug.log in the console. If I could check the log again, and then rewrite the new coordinates, I think I could figure this out!
     
  26. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Well don't just test with one click; repeat the test multiple times, clicking in different places, and check to make sure it's right every time.

    And if you're not seeing the debug.log in your console, then how are you checking? That's a problem you can't ignore. It should be there... if it's not there, then that code isn't executing at all (or you have Info messages hidden in your console; check the little button on the right side of the console toolbar, that looks like a "!" in a speech bubble).
     
  27. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Well I checked the little speech bubble. The only way I was checking was by looking at the code I posted with p: earlier. And the debug.log isn't showing up like it should. One more thing, to make sure I'm understanding. I run my code and look in the debug.log after I click a random place in my world. I take the 3 coordinates and manually created a sphere and set the sphere to the 3 coordinates. It should go where I clicked. Here's what my code looks like:
    Code (CSharp):
    1. public Transform target;
    2.     public float speed;
    3.  
    4.     void WhenProjectileShot() {
    5.         Camera camera = GetComponent<Camera>();
    6.         Vector3 p = camera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, camera.nearClipPlane));
    7.    
    8.         if (Input.GetMouseButtonDown(0)) {
    9.             transform.Translate(Vector3.up * 0.8f);
    10.             Debug.Log ("p:" + p);
    11.            
    12.         }
    13.     }
    14.  
    15.     // Use this for initialization
    16.     void Start () {
    17.     }
    18.    
    19.     // Update is called once per frame
    20.     void Update () {
    21.  
    22.         /*
    23.         if (Input.GetMouseButtonDown (0)) {
    24.             WhenProjectileShot ();  
    25.         }
    26.         */
    27.  
    28.         Vector3 relativePos = target.position - transform.position;
    29.         Quaternion rotation = Quaternion.LookRotation(relativePos);
    30.         transform.rotation = rotation;
    31.  
    32.        
    33.     }
     
  28. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    OK, well the debug.log isn't appearing because it's never happening! You've commented out the call to it.

    Somehow you're still not really understanding your own code. You've got to be the computer. Imagine you're very dumb and very literal (but very fast). It's a new frame; you enter the Update method. You skip over all the comments, because you're a computer, and those are for humans! So you set relativePos... set rotation... copy that into transform.rotation... and you're done!

    Nowhere in there do you do any Debug.Log, so of course no messages appear in the console.

    You probably commented out the important bit because of my comment a few messages up, where I said it was pointless to check Input.GetMouseButtonDown in both Update and WhenProjectileShot. That's true; if you be the computer and step through that, you'll see that you're doing the same if-test twice, which is just wasted busywork. But commenting out the entire if-block in the Update method was not the right fix!

    So back up, ask yourself exactly what you want the computer to do, step by step, on every frame. Write code that does that.

    And hang in there... you've already shown far more tenacity than a lot of people who come to Unity with big dreams but little experience, and get discouraged as soon as they discover it's not easy. That tenacity will serve you well, and I think we'll see amazing games from you someday! One day soon it's going to "click" for you and you'll see how to think like a computer, and suddenly you'll make rapid progress all on your own. Till then, keep trying, and keep posting back, and let me know if anything I say is unclear!

    (And yes, your undestanding of the check-the-position procedure is correct!)
     
  29. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    I'm understanding how to in a sense be the computer although I'm not quite there yet! And everything you've said is clear, I uncommented the code block, but I'm still not seeing a debug.log message. I'm sure I'm doing something thick and stupid, but I'm not quite sure what to do....
     
  30. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    OK, please try this:

    Code (CSharp):
    1.  
    2.         // Update is called once per frame
    3.         void Update () {
    4.             if (Input.GetMouseButtonDown(0)) {
    5.                 Camera camera = Camera.main;
    6.                 Vector3 p = camera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, camera.nearClipPlane));
    7.                 Debug.Log("p:" + p);
    8.             }
    9.         }
    I've just simplified the script and cut away all the distracting stuff. So on Update, we check if mouse button 0 has just been pressed. If so, we get the camera (I'm using Camera.main here so you don't have to attach this script to the camera, you could attach it anywhere), and convert the mouse position into world coordinates. And then we Debug.Log that point.

    Now, I guarantee that if this script is attached to an active object in the scene, and you click in the game view, it will log something. If you still don't see it, then I think you must have info-level messages hidden in the Console.
     
  31. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    EPIC!!! Success! I picked a prominent point in my world like the top of a pine tree, and then recorded the coords and the sphere went right to it!!!
     
  32. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Awesome! OK, so now you know how to convert a screen point to a world point!

    I'm actually a little surprised it worked right off the bat like that, because you're specifying a depth of camera.nearClipPlane. That wouldn't be the right depth, in general... I typically use something like the distance from the camera to the ground or game board, or I cast a ray. But if it's working for you, let's be glad and move on!

    Now, you want to make your newly spawned projectile face that point, right? Where's the code that spawns a new projectile? Post that and we'll look at where to insert this new capability.
     
  33. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Well, I don't have any code that spawns the object. When we were done with this I was going to ask how to do that. Let me sum this up in a nutshell.
    1. I have a character named Felix who sits behind an Artillery Gun and shoots little pellets.
    2. When I click mouse0. A pellet shoots (well not yet because I haven't gotten the code to translate toward the mouse!)
    3. It should be an infinite ammo source, but I only have 1 shot...which is a pretty darn big problem.
    So I really don't have an spawn code yet.
    And yes, I want to make the newly spawned projectile fly toward the mouse and past it off the world border.
    Thanks so much!
     
  34. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    OK, let's take it one step at a time. How about making your Artillery Gun actually point at the mouse, all the time? Then when you spawn a projectile, you can simply have it come out of the gun at the same orientation as the gun at that moment.

    (AND, that seems like good feedback for the user, makes it very obvious what's going on.)
     
  35. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Assuming that's what you want to do, then you need a script for your gun that does (in Update) the following:
    1. Converts the Input.mousePosition into a world position (you know how to do that now!)
    2. Sets its own transform.rotation to the result of calling Quaternion.LookRotation, with p - transform.position for the first parameter (which direction you want to rotate in), and probably new Vector3(0,0,-1) for the second parameter (what vector it should rotate around).
    I'm assuming there that you're making a 2D game, so sprites move in X and Y, and rotate around Z. If you have a different setup, please let me know!
     
  36. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Well the gun won't look very good pivoting around. I planned it for mobile, so the user touches where he wants the bullet to go. Here's a quick screenshot. I'm very willing to improvise, but I was more or less thinking of having the projectile be the only thing that moves. I'm 14 right now so much drawing needs a decent amount of improvement! Let me know if this works out or not. Thanks!
     

    Attached Files:

  37. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I think that drawing is pretty cool. However, as a bit of advice... mobile is twice as hard as desktop, so I'd advise you to forget about that for now and just make a few fun desktop games. You can publish them to the web, share them with your friends, etc... It will be a good time and you'll learn a lot. Then you can circle back and publish your dream game on mobile (or FireTV or AppleTV or the latest console or whatever) in a few years if that's what you want to do.

    But sure, we can skip rotating the gun if you want. You can just rotate the projectile when you instantiate it, and that'll accomplish the same thing.

    Now, if you're 14, I'm amazed you've stuck with me this far reading words. :) I have a son only a little older than you, and I thought your generation was all about the YouTube videos. If that works for you, you should search for step-by-step beginner tutorial videos for Unity — there are a ton of them, and they'll show you how to do stuff like this.

    But I'm willing to continue helping out this way, too. To instantiate a projectile, you need a script on your gun that has:

    1. A "public GameObject projectilePrefab;" property, into which you drag a prefab of your projectile.
    2. Code in the Update method that checks for a mouse button click — you know how to do that now.
    3. When the mouse click is detected, it does something like the following:
    Code (CSharp):
    1. GameObject noob = GameObject.Instantiate(projectilePrefab) as GameObject;
    2. noob.transform.position = transform.position;
    3. // TODO: rotate to look at the mouse here!
    We won't worry about rotation yet — one thing at a time is the key to success.

    So, with this code in place, you ought to be able to spam the mouse button and create dozens of projectiles. These will all just sit there, unless your prefab includes a script that makes them move forward... in which case, they will all fly forward as they're created. And that's a good start!
     
  38. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Ok, one thing that I'm not quite sure about. Or rather I should explain. The machine in that little picture is not part of the projectile. If you look at the picture that circular round thingy is the projectile and it is a completely separate prefab stuck between 2 electric bars. Obviously the code would just shoot the whole machine into the sky if I didn't define the prefab!! So since I have a projectile, what does the first step you gave me mean for me to do? Oh also, the script I've been working on is the same as my projectile script, so do I just keep using that one?
     
  39. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    You need a separate script for each function. At the very least, one for the projectile, and a different script for the gun.

    You have a projectile, but I don't believe you have a projectile prefab. Go read up on prefabs if you're not absolutely clear what that means.

    Step 1 is to define a public property on your gun script (not your projectile script!), into which you can drag your projectile prefab.
     
  40. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Right, I've got this now. I read up on some prefab docu and made a prefab for projectile. So this is what I have that relates to my tasks at hand.
    1. A projectile script (that works)
    2. A machine (gun) script that has nothing in it yet ...do I add the hunk of code a few posts earlier into update?
    3. An empty projectile prefab
    Is this basically what I need?
     
  41. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Hey, I got it..kind of. So I made a new script called gunBehavior and attached it to the gun, not the projectile. Then I added this code in its own method...well really just outside of the start or update method
    Code (CSharp):
    1. public GameObject projectilePrefab;
    Now in the object called Gun in Unity, I have a slot that says Projectile Prefab none. So then I made a new prefab, but I can't drag it in. I'm not sure why this is? So basically right now, the projectile prefab is attached to nothing, I have a gun script that creates a property, but I don't really need to do anything with the projectile script at the moment. Hope this isn't too confusing.
     
  42. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Sounds like you have a good start on your gun script. I don't know why you can't drag your projectile prefab in. I also don't know what you mean by "the projectile prefab is attached to nothing." I suspect you haven't actually created the projectile prefab like you think you have.

    You make a prefab by first preparing an object in the Hierarchy of your scene; then dragging it down into the Project hierarchy. At that point, you can delete the object that's in your scene Hierarchy; you don't need it any more. The prefab lives in the Project. You drag it from there into the "Projectile Prefab" slot on your gun.
     
  43. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    ok, sorry but let's see if I'm really understanding. If I just drag the projectile from the scene's hierarchy into the project hierarchy, then into the gun's projectile prefab, won't the projectile be deleted from my scene? Oh also, I created a new prefab the wrong way i guess. I went assets > create > prefab. My mistake!
     
  44. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    No, you'll have to do that yourself as a separate step. So drag it from the scene hierarchy into the Project; then drag it from the Project into the gun's projectile slot; then delete the projectile in your scene. You no longer want it there; you're going to instantiate it when you need it.

    Huh, I had forgotten that was there! Yeah, building an object and then just dragging it into the Project is a much easier way to do it.
     
  45. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Ok I got it. So is the next step making the code for the projectile? Would I do this in the gun script now?
     
  46. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    YAY! Sorry to keep relentlessly posting every minute. But I just figured it out. at first, I implemented some code in my update without any conditions. This made literally millions of projectiles. Then I thought like the computer and created an if statement to work as a condition. Now it only spawns them when I click Mouse0!
     
    JoeStrout likes this.
  47. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    You rock! Nicely done.

    Now, the last step is to point the projectiles at the mouse (with the help of Quaternion.LookRotation) when they're created, right?
     
  48. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
  49. Gabrieldonley

    Gabrieldonley

    Joined:
    Oct 30, 2015
    Posts:
    57
    Oh, I think I have some code for that that could go in the update method. Or would that update it every frame?
     
  50. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Yes, anything in the Update method runs every frame. You don't want to do that in this case; you want to point it in the right direction when it's fired, and then just let it move straight ahead after that.