Search Unity

Make my bow shoot? Help please :)

Discussion in 'Animation' started by ecloev, Oct 1, 2015.

Thread Status:
Not open for further replies.
  1. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    Hello,
    I would like to make my bow shoot an arrow which i already have positions on the bow.
    I need this arrow to travel forward until it hits something and disappear.
    However, the catch is that i need to make it so after 2 seconds of hitting 'Fire1' it will reload with another arrow?

    I already have an if getbuttondown fire1 statemtn setup.
    It also has to be the actual game object that shoots cause i have the bow and arrow at an angle at the left side of the screen. I want the arrow to go from it's location straight to the crosshair and continue moving until it hits something. But i need a copy of the arrow to reappear even if the other arrow isn't destroyed

    Help appreciated thanks!
     
    Last edited: Oct 1, 2015
  2. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    I'm a little confused as to what you're seeking help on, the arrow flight or the reloading. It seems like your main question is how to get the same arrow that has just been fired to reappear two seconds after you fire the arrow.

    The best way I can think of is to create a prefab of the arrow and then instantiate the prefab as a GameObject each time you reload the bow. I'm going to leave out information about creating prefabs and the necessary animations for reloading the bow as I'm sure you already know how to do that.

    If you don't have a timer class, I suggest you create one as timers are a very common thread in game design. Unless you plan on doing everything through IEnumerator coroutines which can be a pain to manage once you have a lot of them to worry about.

    There are several steps you need to take to make this process work properly.
    1. Make a prefab of the arrow you are firing.
    2. Create an animation for when the player reloads the bow with another arrow.
    3. Create a public function that will instantiate the prefab at the desired position & rotation.
    4. Attach a keyframe event on the frame of the reload animation that brings the arrow onto the bow.
    5. Have the keyframe execute the public function you created for prefab instantiation.

    Once you are done with steps 1 and 2, you need to create a function on your bow script that looks like this:
    Code (CSharp):
    1.  public void OnReloadArrow()
    2.     {
    3.         //The following variables are here for example only. Ideally you'd want to set these
    4.         //as global variables at the start of your bow script.
    5.         // * Global as in global to the scope of the scirpt, not global to the entire solution.
    6.  
    7.         //This would be your prefab so you'd want to direct this to the prefab you created for the
    8.         //new arrow.
    9.         GameObject fabArrow = (GameObject)Resources.Load("Prefabs/Objects/Ammo/StandardArrow");
    10.         //This is the reference to the actual instantiated gameObject.
    11.         GameObject gArrow;
    12.         //You said at some point in your post that you had created all the necessary anchors and positions
    13.         //on the bow, so I assume you have variables for these somewhere
    14.         Vector3 pt_pos_arrow = Vector3.zero;//This is the position of the arrow when on the bow in ready position
    15.         Quaternion pt_rot_arrow = Quaternion.identity; //This is the rotation of the arrow when on the bow in ready position.
    16.  
    17.         //Create the new arrow and assign it to gArrow
    18.         //NOTE: This assumes that on firing the bow, the arrow is no longer tracked by this script.
    19.         //If that isn't the case, you'll want separate GameObject references for the arrow in flight
    20.         //and the arrow in the bow.
    21.          gArrow = (GameObject)Instantiate(fabArrow, pt_pos_arrow, pt_rot_arrow);
    22.  
    23.     }
    It's important to note that this function has to be attached to a monobehavior script that is attached to the GameObject of the Bow that has the actual Animation component, otherwise the function won't show up on the keyframe event list.

    Now that you have your function and the keyframe event that points to it, all that's left to do is to create your timer variable to handle when the reload animation gets played.

    Code (CSharp):
    1. void Update()
    2.     {
    3.  
    4.  
    5.         if(JustFired)
    6.         {
    7.  
    8.             //while the timer is greater than 0, decrease it by increments of deltaTime
    9.             if(ReloadTimer > 0)
    10.             {
    11.                 ReloadTimer -= Time.deltaTime;
    12.             }
    13.  
    14.             //If the timer gets below zero, set it to zero
    15.             if(ReloadTimer < 0)
    16.             {
    17.                 ReloadTimer = 0;
    18.             }
    19.  
    20.             //Once the timer has officially reached 0
    21.             if(ReloadTimer == 0)
    22.             {
    23.                 animation.Play["ReloadBow"];
    24.                 JustFired = false;
    25.             }
    26.         }
    27.  
    28.  
    29.  
    30.     }
    There are two variables not mentioned in there, because again they need to be global to the scope of the script.

    bool JustFired; //This is a simple boolean to track whether or not the player just fired the bow
    float ReloadTimer; //Simple float to track the amount of time passed between firing and reloading

    JustFired should be set to true right when the player fires the arrow. Additionally, ReloadTimer should be set to 2.0f at the same time.

    I'm sure that's a lot to take in, but I hope it helps you out somewhat.

    -McMayhem
     
    theANMATOR2b likes this.
  3. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    Thanks so much! But my bow wont even shoot! I got my whole game figured out but i am having difficulty even making
    my bow shoot an arrow. I need my bow to shoot at the cross hair at the center and hit and enemy if crosshair is on the enemy. But I think i couldv'e worded this part better. I want it so that when i shoot the arrow gets destroyed when it hits something. But a new arrow is reloaded in after 2 seconds and you can shoot again. So even if the other one is still moving i can shoot again. I'm very new to unity and everything is done except the attacking system. Thanks!
     
  4. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    Ahhh okay. Then there's just a few more things I'd need clarified to help you further.

    1. Do you have animations that you are using for the firing/reloading of the bow? Are you using animations at all?
    2. Do you want your arrow to have physics? That is to say, are you looking for the arrow to be affected by gravity, or just continuously move on a single forward vector?
    3. Are you also looking for help on how to aim, or are you just looking for how to launch the arrow?

    For the destruction of the arrow upon hitting a target, that's super simple. You can just use Destroy(arrow); to get rid of the arrow once it's reached its destination.

    As for the actual movement, a very common (but restricted) procedure is to keep the arrow facing its target, and translate it forward at the speed you desire.

    So let's say we have a few variables set up:
    float arrowSpeed = 30; //This will be the speed at which the arrow travels when in flight
    GameObject gArrow; //This is the actual arrow that has been fired and is moving
    Vector3 target; //This is the target position that the arrow is trying to reach

    With those variables in mind, your arrow travel code would look something like this (remember this has to be called from the Update() thread)
    Code (CSharp):
    1. public void ArrowFlight()
    2. {
    3.      //First we get the direction of the arrow's forward vector
    4.      //to the target position.
    5.      Vector3 tDir = gArrow.transform.position - target;
    6.  
    7.      //Now we use a Quaternion function to get the
    8.      //rotation based on the direction
    9.      Quaternion rot = Quaternion.LookRotation(tDir);
    10.  
    11.     //And finally, set the arrow's rotation to the one we just
    12.     // created.
    13.      gArrow.transform.rotation = rot;
    14.  
    15.      //Get the distance from the arrow to the target
    16.      float dist = Vector3.Distance(transform.position, target);
    17.  
    18.  
    19.      if(dist <= 0.1f)
    20.      {
    21.            //This will destroy the arrow when it is within .1 units
    22.            //of the target location. You can set this to whatever
    23.            //distance you're comfortable with.
    24.            GameObject.Destroy(gArrow);
    25.  
    26.      }
    27.      else
    28.      {
    29.           //If not, then we just keep moving forward
    30.           gArrow.transform.Translate(Vector3.forward * (arrowSpeed * Time.deltaTime);
    31.      }
    32. }
    That code won't work if you're looking for a physics approach. Based on your answers to the first three questions, I can make a better function for you that will do exactly what you want.

    -McMayhem
     
  5. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    No, i am not using animations as of now but i think i have the capability to edit the code if i need to.
    Uhm, it would be nice for it to be affected by gravity and then just have it so when it hits the ground or an enemy it destroys. However one set distance would be fine and if the enemy is out of range just destory.
    I already have a crosshair set up, however i do not know how to make the arrow fly to the crosshair and then straight to the enemy. Is there a system we could do that would basically say if the crosshair is on the enemy launch to the enemy. Because idk what i want to do with it because the actual bow and the arrow is on the left side of the screen tilted inwards. Meanwhile, the crosshair is in the center and an arrow that shoots to the middle and then makes a 45 degree turn towards the enemy may look a bit weird haha. Any solution to that?
     
  6. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    And it would be even better to have the arrow destroyed if it hits a tree, the ground, an enemy or anything on the map that isn't the air :)
     
  7. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    Just let me know if you have an idea. :)
     
  8. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,932
    @McMayhem, we are having a similar issue and would like to find a physics based solution for the movement of the arrow. So far, it has spawned a number of heated discussions between me and my programmer so any clues you can give us would be helpful.

    Is there an asset on the store that might help? He is a good programmer but has never done this before and I think is off in the wrong direction.

    Thank you.
     
  9. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    The real question when it comes to physics based solutions is, how fast do you want the arrow to go? The answer to that will dramatically change how you approach this. For my project, we are using ballistic weapons, so the speed of the projectile had to be very high. The problem with using high speed physics objects is that the percent of collision detection error scales up inversely with projectile speed.

    You'll find that forces > 65 are going to pass through most objects regardless of the type of collider they are using. This is due to the fact that the update for physics needs to be less frequent than your usual update loop to ensure optimized performance (this isn't unity specific, every game engine runs into this issue).

    There is a very nice way to handle physics of high speed objects using raycasts. The results are often more accurate and in some cases more CPU friendly than the physics solution.

    So if you would like, I can post a simple script that will do the raycast physics. But if you aren't dealing with projectiles that travel at high speeds, the built-in physics system should do just fine and I can show you how to go that route as well.
     
  10. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    I think 40 would be fine for me :)
     
  11. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,932
    We are not using high speed projectiles so lower is good for us too. :) Thank you. You may have saved a relationship. lol
     
  12. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    Things can often times get tense on teams, particularly when facing an issue of how to plan implementation of features, so I understand that 100%.

    I'm going to drum something up really quick using a new project. I'll post the step-by-step here for you guys, but if you also want the project file, just let me know and I'll send it to you.

    Should have something in about 15 minutes.
     
    Teila likes this.
  13. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    Alright, I’ve tested this out myself and it works just fine. Fun note: The 65 force threshold I gave earlier was incorrect it’s more like 78 – 95 that misses on collision. I haven’t used this for projectiles since Unity 3, so it’s clear UT have made some very nice improvements here.


    Let’s start with the setup. (Remember, let me know if you want the project file so you can test it out yourself.)

    Scripts:

    BowHandler.cs (This will be attached to the bow you are shooting the arrow from)

    ArrowHandler.cs (This will be attached to the arrow that is being shot)


    In your Scene:

    BowWeapon [GameObject] [BowHandler]

    Pt_arrow [GameObject]

    Arrow [GameObject] [ArrowHandler] (make this use the same position/rotation as pt_arrow)



    Prefabs:

    Arrow.prefab (this is the prefab of the arrow that’s in the scene. It will get instantiated where the old one was after firing)


    Bow Handler
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class BowHandler : MonoBehaviour {
    5.  
    6.     public GameObject fabArrow; //Reference to the arrow prefab
    7.     public GameObject gArrow; //Reference to the initial arrow. Note: You need to have an arrow on the bow already at start.
    8.  
    9.     public Transform pt_arrow; //Point on the bow to create the new arrow after firing.
    10.  
    11.  
    12.     public float ArrowForce; //Force to be applied to the arrow when firing
    13.  
    14.  
    15.     // Update is called once per frame
    16.     void Update () {
    17.    
    18.         //Simple input code to get a keypress. Change this to whatever key you like
    19.         if(Input.GetKeyDown(KeyCode.LeftControl))
    20.         {
    21.             FireArrow();
    22.         }
    23.  
    24.     }
    25.  
    26.  
    27.     public void FireArrow()
    28.     {
    29.         //Anytime you use a public variable, or any variable really, you should
    30.         //always make sure the variable has been set before attempting to use it.
    31.         //This will avoid infuriating errors. Alternatively, you may want to send
    32.         //some information to the output log if it is null so that you can see what
    33.         //happened later.
    34.  
    35.         if(fabArrow != null && gArrow != null)
    36.         {
    37.          
    38.             //Get the rigidbody component of the arrow.
    39.             Rigidbody rArrow = gArrow.GetComponent<Rigidbody>();
    40.  
    41.             if (rArrow != null)
    42.             {
    43.                 //Setting isKinematic to false will allow physics to be applied to
    44.                 //the arrow.
    45.                 rArrow.isKinematic = false;
    46.  
    47.                 //Grab a reference to the arrow handler.
    48.                 ArrowHandler aHand = gArrow.GetComponent<ArrowHandler>();
    49.  
    50.                 if(aHand != null)
    51.                 {
    52.                     //Set the arrow handler to active since we are now firing
    53.                     aHand.IsActive = true;
    54.                 }
    55.  
    56.                 //This command will add velocity to a rigidbody using a vector
    57.                 //For our situation, we want the arrow to fly forward, so we multiply
    58.                 //the arrow's forward facing vector times the force amount.
    59.                 rArrow.AddForce(pt_arrow.forward * ArrowForce, ForceMode.VelocityChange);
    60.  
    61.                 //ForceMode.Impulse is just one of several force modes. You might want to play around with those
    62.                 //to see if you can get better results with different options.
    63.  
    64.                 //Now we recreate a new arrow on the old arrow spot. This should be placed in your reload function
    65.                 // if you have one.
    66.                 gArrow = (GameObject)Instantiate(fabArrow, pt_arrow.position, pt_arrow.rotation);
    67.             }
    68.             else
    69.             {
    70.                 Debug.Log("Bow Error! There is no rigidbody attached to the arrow object! Sent from: " + gArrow.name);
    71.             }
    72.         }
    73.         else
    74.         {
    75.             //If it is null, then we need to have a little chat with ourselves.
    76.             Debug.Log("Bow Error! You are trying to instantiate an object without a reference! Sent from: " + gameObject.name);
    77.             //I usually like to toss in the name of the object that throws the error just so I have a more focused search area
    78.             // when trying to identify a problem.
    79.         }
    80.  
    81.  
    82.     }
    83. }
    84.  

    Arrow Handler
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class ArrowHandler : MonoBehaviour {
    5.  
    6.  
    7.     public float Lifetime; //The float amount of seconds this arrow should remain in play before being destroyed
    8.     public float DestroyDelay; //The delay after this object hits something before destroying it
    9.  
    10.     private TimerVar _lifeTimer; //If the arrow doesn't hit anything we need to destroy it after a time to save performance.
    11.     private TimerVar _deathTimer; //Timer for when to destroy if the arrow hits another object while in flight.
    12.     private TimerVar _colTimer; //We need this small timer to turn on the box collider for this object after firing.
    13.     private bool _hitSomething; //Has this arrow hit an object? Used to destroy the arrow after a time.
    14.     public bool IsActive; //Has this arrow been fired? Used to start lifetime calculations.
    15.  
    16.  
    17.     // Use this for initialization
    18.     void Start () {
    19.         //Set up our timers.
    20.         _lifeTimer = new TimerVar(Lifetime, false);
    21.         _deathTimer = new TimerVar(DestroyDelay, false);
    22.    
    23.     }
    24.    
    25.     // Update is called once per frame
    26.     void Update () {
    27.  
    28.         //Don't do any calculations until after the arrow has been fired.
    29.         if (!IsActive)
    30.             return;
    31.  
    32.         if(_hitSomething)
    33.         {
    34.             //Has this arrow hit something?
    35.             //If yes, start the death routine
    36.             if(_deathTimer.TimerDone)
    37.             {
    38.                 //Check to see if the destroy delay is done.
    39.                 //If yes, destroy the object.
    40.  
    41.                 Destroy(gameObject);
    42.             }
    43.             else
    44.             {
    45.                 //If not, keep counting down.
    46.                 _deathTimer.TimerUpdate();
    47.             }
    48.         }
    49.         else
    50.         {
    51.             //If not, keep checking the lifetime info
    52.             if(_lifeTimer.TimerDone)
    53.             {
    54.                 //Has this object exceeded it's allotted life time?
    55.                 //If yes, we destroy it.
    56.                 Destroy(gameObject);
    57.             }
    58.             else
    59.             {
    60.                 //If no, we keep counting down.
    61.                 _lifeTimer.TimerUpdate();
    62.             }
    63.         }
    64.  
    65.    
    66.     }
    67.  
    68.     void OnCollisionEnter(Collision col)
    69.     {
    70.         //This function must be on the gameObject that has the box collider attached to it.
    71.         _hitSomething = true;
    72.     }
    73. }
    74.  
    75.  
    76.  

    I’ve tested this with force range from 10 – 70 and it works just fine. You can adjust the arrow speed from the bow and you can adjust the lifetime/deathtime of the arrow from the arrow in the inspector.


    One last thing. You'll notice I have a variable in the ArrowHandler called TimerVar.cs. This is the timer I talked about in my first post. My version is probably a little overkill for this scenario, but it does give you a lot of control for use later if you need it. (Better coders, feel free to let me know if this is poorly optimized. I did write it several years ago)

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. //*********************************************************************************//
    5. // Class: TimerVar
    6. // Created By: Chuck (McMayhem) McMackin
    7. //*********************************************************************************//
    8. // The Timer Var class is used as a simple timer for anyting that requires timed
    9. // activation or intervals. This is used to replace the general means of timers which
    10. // can cause convoluted code and poor management. The timer var must be updated in the
    11. // update function of any script it is attached to. For this reason, it can only be
    12. // placed in MonoBehavior-based scripts.
    13. //*********************************************************************************//
    14.  
    15. [System.Serializable]
    16. public class TimerVar
    17. {
    18.  
    19.     public float TimerSet;
    20.     public bool TimerDone;
    21.     public bool Looping;
    22.     public float TimerSpeed;
    23.     public float CurTime;
    24.     public float Percent;
    25.  
    26.     private float _timer;
    27.  
    28.     public TimerVar(float tSet, bool loop)
    29.     {
    30.         TimerSet = tSet;
    31.         Looping = loop;
    32.         TimerDone = false;
    33.         _timer = TimerSet;
    34.     }
    35.  
    36.     public TimerVar(float tSet, float tSpeed, bool loop)
    37.     {
    38.         TimerSet = tSet;
    39.         TimerSpeed = tSpeed;
    40.         Looping = loop;
    41.         TimerDone = false;
    42.         _timer = TimerSet;
    43.     }
    44.  
    45.  
    46.     public void TimerUpdate()
    47.     {
    48.         if (_timer > 0)
    49.         {
    50.             if (TimerSpeed > 0)
    51.             {
    52.                 _timer -= Time.deltaTime * TimerSpeed;
    53.             }
    54.             else
    55.             {
    56.                 _timer -= Time.deltaTime;
    57.             }
    58.         }
    59.  
    60.         if (_timer < 0)
    61.         {
    62.             _timer = 0;
    63.         }
    64.  
    65.         CurTime = _timer;
    66.         Percent = (CurTime / TimerSet) * 100;
    67.  
    68.         if (_timer == 0)
    69.         {
    70.             TimerDone = true;
    71.             if (Looping)
    72.             {
    73.                 Reset();
    74.             }
    75.         }
    76.  
    77.     }
    78.  
    79.     public void Reset()
    80.     {
    81.         Percent = 0;
    82.         TimerDone = false;
    83.         _timer = TimerSet;
    84.     }
    85.  
    86.     public void Reset(float num)
    87.     {
    88.         TimerSet = num;
    89.         TimerDone = false;
    90.         _timer = TimerSet;
    91.     }
    92.  
    93.     public void Reset(float num, float speed)
    94.     {
    95.         TimerDone = false;
    96.         _timer = num;
    97.         TimerSpeed = speed;
    98.  
    99.     }
    100. }
    101.  
    Hope this helps. Let me know if you need more clarification.
     
    MurtazaRameesh likes this.
  14. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,932
    Thank you! We will test it this weekend and let you know. :)

    I love the Unity community!
     
    McMayhem likes this.
  15. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    Thanks so much!
    What is g and pt arrow?
     
  16. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    After careful consideration, I realized this probably isn't something that can be fully explained in a forum post. With that in mind, I created a nifty little unity package called BowTutorial and threw it up on my website downloads page. If you want to grab it:

    Bow Tutorial Package

    Some things I forgot to mention
    - You need to create new layers for both the Arrow and the Bow and make it so that Bow !->* Arrow and that Arrow !-> Arrow. This will make it so they do not collide with one another while you are shooting the arrow.
    - You should have a physics material for the arrow that way you can change it's bounciness when hitting other objects

    * - This is just my shorthand for X does not interact with Y. In this case it means Bow does not interact with Arrow and Arrow does not interact with Arrow.
     
    theANMATOR2b and TonanBora like this.
  17. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,932
    Wow, very nice!!

    We have it working for the most part, just a few glitches, but will look at your tutorial before asking more questions. Thank you!
     
  18. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    I don't, i am still confused on what pt_Arrow and g arrow is?
    After that we should as well :)
     
  19. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    And also how do i do this layer thing?
    As i said, I'm new to unity and am having trouble understanding :)
     
  20. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    gArrow is the GameObject of the arrow that is currently loaded onto the bow. In the tutorial package I posted, you can see the green arrow object on the white bow object, that green arrow object is gArrow;

    pt_arrow is a Transform point on your bow weapon object that you use to place the new arrow when the old one has fired. This is also shown in the tutorial package.

    I've commented out just about everything in the scripts pretty rigorously, but if you need specific help with anything let me know.
     
  21. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,932
    It worked great for us! Thank you. :) Following the tutorial eliminated the little glitch. All is well and good.
     
    McMayhem likes this.
  22. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    Glad to hear things worked out for you guys! If you run into trouble down the line or otherwise need alternative methods to achieve this effect, just let me know and I'll compile you something else as well.
     
    TonanBora and Teila like this.
  23. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    Ok i got GArrow, but i do not have a transform of the arrow?
    Not sure what that even is... :p
     
  24. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    What is ptArrow? I don't even have a transform?
    What steps do i need to take to attatch this?
     
  25. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,932
    My programmer just followed the tutorial and it worked.

    The only issue we are having now is making it work with 3rd person, which is a bit different I guess. :)
     
  26. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    Transform isn't something you have in scene view, at least not as a separate object like you may be thinking. In the scene view it's a GameObject, just like gArrow is a GameObject. Every GameObject in Unity has a Transform that holds position, scale, and rotation of your object (along with some very helpful functions to work with all three coordinates). pt_Arrow is an empty GameObject you have in your scene that is a child of the Bow. It serves as the anchor point to place the new arrow once you've fired the old one. Think of it like a nail in a wall where you want to hang a painting or a picture. The nail serves as the anchor point for the painting. pt_Arrow serves as the anchor point for the arrow every time it gets brought into the game.

    Is your issue with how to get it to aim properly, or is there something else that's causing troubles? Also, what kind of third person view are we talking about here? Is it your standard over-the-shoulder viewpoint or a high up isometric view? There are some fun ways to handle aiming for both.

    Let me know if you need help with this and I'll append the solution to the original BowTutorial unity package.
     
    TonanBora likes this.
  27. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,932
    Hey, Mayhem!

    It is standard over-the-shoulder viewpoint. Ryan says he cannot get the arrow to fire or the bow to animate, although the animation might be a totally different problem. He says the aiming is not a problem, just not firing the bow. It worked fine in 1st person. He uses FinalIK for the aiming.

    When debugging, it goes through the fire code but the arrow does nothing.

    Thanks for any suggestions you have.
     
  28. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    Hello, I just tested as well, i attached everything as you said however the bow still acts if the scripts don't exists.
    It doesn't even fire...
    Thanks :)
     
  29. TonanBora

    TonanBora

    Joined:
    Feb 4, 2013
    Posts:
    493
    Hey MCMayhem!
    This is Teila's programmer.
    I have figured out that, when spawning in, the arrow does not want to spawn in at the right location like it does normally.
    Here are some pictures:
    2015-10-04_23-08-35.jpg

    Here, is the bow in question, in the middle of an Aim animation. The Arrow spawn point is right around the area of the hand holding the bow (I have it selected in the hierarchy, scene view is the window in the lower center), and I have called the Reload function by this point, but have not fired the arrow.

    However, I did a search for my arrow clone in the hierarchy window, and indeed the arrow has been instantiated...
    2015-10-04_23-10-28.jpg
    As you can see in this screen shot, the arrow was brought in very far from its spawn point (which I still have selected, you can see the move gizmo in among all those speaker icons).
     
    Last edited: Oct 5, 2015
  30. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    From the image it appears that there's an issue with position and rotation when instantiating on the pt_arrow anchor. This is probably due to something moving or being set just after the arrow has been instantiated. To ensure that the arrow properly locks to it's parent position and rotation, you might want to try adding the following code to your BowHandler.cs (or whatever script you are using that you put the reload function into).

    Code (CSharp):
    1.             //Next step is to parent the arrow to the bow so that it moves and rotates with it properly.
    2.             gArrow.transform.SetParent(transform); //I've heard it's better to use Transform.SetParent() rather than Transform.parent = transform.
    3.             gArrow.transform.localPosition = Vector3.zero;
    4.             gArrow.transform.localRotation = Quaternion.identity;
    That part of the code is located in the Reload() function of the BowHandler.cs in the BowTutorial. It's on line 98. I'm not sure how much of that code you adapted to your game code, but you just need to make sure you zero out the arrow's local rotation and position.

    Let me know how that works!
     
  31. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    Mine won't even shoot :( No errors but nothing happens :(
     
  32. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    Are you in the BowTutorial level with all the stuff I set up there? If it's not shooting from there, then that means something is very wrong. I'm going to need more information though, in order to help you.
     
  33. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
  34. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
  35. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    Ooh, how can i change this to fire1? Sorry haha!
     
  36. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    No worries at all! Just glad it's actually able to fire at all. You can change it to fire1 using the same boolean check with the Input Manager:

    So you would change the following code in BowHandler.cs (52*):
    Code (CSharp):
    1.             //Simple input code to get a keypress. Change this to whatever key you like
    2.             if (Input.GetKeyDown(KeyCode.LeftControl))
    3.             {
    4.                 FireArrow(); //Function that actually fires the arrow.
    5.             }
    To this code:
    Code (CSharp):
    1. if (Input.GetButtonDown("Fire1"))
    2.             {
    3.                 FireArrow();
    4.             }
    That will change the FireArrow() function to execute when the "Fire1" input button is pressed.

    Hope that helps!

    * - The code you want to replace is located at line 52 of the BowHandler class
     
  37. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    Well, i take that back. It's not shooting. :(
     
  38. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    So pressing Left Control when in game does nothing at all? Does the arrow fall off the bow or get unparented? If not that means the code isn't getting called for some reason. Do you have any other scripts affecting the bow?
     
  39. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    Nothing happens. IT isn't unparented, and there are no other scripts :)
     
  40. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    Try removing the animator component from the arrow object and see what happens. Also, what folder in your assets is the arrowRig_1.0 prefab located in? Make sure the prefab that the BowHandler class references isn't the arrow in the scene, but the one from your assets.

    To remove the arrow's Animator component right click on where it says "Animator" in the inspector and in the drop-down menu select "Remove Component".
     
  41. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    Nope :(
     
  42. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    Then I'm afraid I've exhausted my ability to help you. To be honest though, it feels like you are trying to jump in a bit too far given your experience with programming. These concepts and methods will be much easier to grasp if you get yourself a more basic understanding of the core concepts.

    You'll definitely want to at least tackle a beginners course on C# programming (or Javascript if that's your monster, though you'll find a lot more examples in C# than in Javascript, so you may want to get familiar with C# now). There are hundreds of good websites and youtube videos made by experts that do a great job of explaining everything you need to know.

    Here are some places to try:
    C# Fundamentals - Channel 9 is a good resource for programming in general
    MSDN Visual C# Resources - MSDN is a great network that has the most robust script reference guide I've seen to date
    C# Basics - If you aren't into the whole learn through video kind of thing

    For Unity in general:
    BurgZerg Arcade - Most in depth tutorials ever made for Unity. No joke, there are about 500 10-minute videos in just the Hack and Slash section. That's 5,000 minutes of pure education!

    You'll need to get at least a basic handle on these concepts in order to be able to be effective in any kind of way with Unity. I really, really, really hate the "stay in school, kid" answer, but sometimes it actually applies. It might take more time than you were expecting, but the payoff is so much better in the end run.

    Useless platitudes aside, I really do hope this helps you out in some way.
     
  43. ecloev

    ecloev

    Joined:
    Oct 1, 2015
    Posts:
    101
    I got it but my arrows are shooting sideways, also thank you for the resources! I'll check it out!
     
  44. TonanBora

    TonanBora

    Joined:
    Feb 4, 2013
    Posts:
    493
    Well, those code fixes did not seem to help any sadly.
    Here is my Reload code:


    Code (CSharp):
    1.     public void ReloadArrow()
    2.     {
    3.         //First we make sure there is an arrow prefab to instantiate.
    4.         if(fabArrow != null)
    5.         {
    6.             //We instantiate(create via prefab) a new arrow and save it as the
    7.             //arrow GameObject "gArrow" to be fired when needed.
    8.             gArrow = (GameObject)Instantiate(fabArrow, pt_arrow.position, pt_arrow.rotation);
    9.  
    10.             //Next step is to parent the arrow to the bow so that it moves and rotates with it properly.
    11.             //gArrow.transform.SetParent(transform); //I've heard it's better to use Transform.SetParent() rather than Transform.parent = transform.
    12.  
    13.  
    14.             //Next step is to parent the arrow to the bow so that it moves and rotates with it properly.
    15.             gArrow.transform.SetParent(pt_arrow.transform); //I've heard it's better to use Transform.SetParent() rather than Transform.parent = transform.
    16.             gArrow.transform.localPosition = Vector3.zero;
    17.             gArrow.transform.localRotation = Quaternion.identity;
    18.  
    19.             /*
    20.             gArrow.transform.localPosition = pt_arrow.localPosition;
    21.             gArrow.transform.localRotation = pt_arrow.localRotation; This is code I added to try and fix the arrow spawning issue before you posted anything.
    22.             */
    23.             //Now that the new arrow is in. We can fire again
    24.             CanFire = true;
    25.         }
    26.         else
    27.         {
    28.             //If it is null, then we need to have a little chat with ourselves.
    29.             Debug.Log("Bow Error! You are trying to instantiate an object without a reference! Sent from: " + gameObject.name);
    30.             //I usually like to toss in the name of the object that throws the error just so I have a more focused search area
    31.             // when trying to identify a problem.
    32.         }
    33.     }
     
Thread Status:
Not open for further replies.