Arrow does not stay on course towards target

The character has an animation for firing his crossbow; firing the crossbow when the crossbow is swing up from the negative y direction until it is horizontal in the positive z direction (1). After firing, the crossbow will have a recoil that swing the crossbow upwards in the positive y direction. (positive y is upwards and positive z is pointing to the right, with no animation in the x direction (positive x is coming towards you)).

With the character facing the target, the intention is for the script to instantiate an arrow (as child object of the crossbow) on the crossbow and just as the crossbow is leveled with the ground (at 1 above),the arrow is fired towards the target.

FireArrow() is a keyframe event attached to the crossbow animation when it is leveled at the target.

private void FireArrow ()
    {
        GameObject newArrow = Instantiate(prefabArrow, parent);
        Vector3 arrowDirection = hero.transform.position - newArrow.transform.position;
      
        newArrow.transform.localPosition = newArrow.transform.position;
        newArrow.transform.localRotation = newArrow.transform.rotation;
        newArrow.transform.localScale = newArrow.transform.lossyScale;
      
        newArrow.GetComponent<Rigidbody>().velocity = newArrow.transform.forward * arrowSpeed; // line 1
        //newArrow.GetComponent<Rigidbody>().velocity = arrowDirection.normalised * arrowSpeed; // line 2

    }

For line 1, the cloned arrow flew off in the z direction (horizontal) in the first frame, but as the crossbow is recoiled in the second frame, the arrow appear at an angle to the horizontal (till upwards) as the z axis direction is no longer perpendicular to the ground (the crossbow is no longer horizontal and the arrow is a child object of the crossbow).

For line 2, the cloned arrow also start to till upwards with the crossbow recoil as the frame progresses.

Appreciate any insight on this.

Thanks!

The problem is that the arrow is a child to a moving object. When a parent moves it takes all the children with it. You need to make it independent of the the crossbow.

Also, if you don’t use an object pool you’re going to start eating though memory real fast.

Yeah, imagine the real world, bullets are guided by the gun until they are out of it. The recoil is not null between the time you shoot and the bullet is out.

If the arrow is a child of the crossbow, it’s like having an infinite long gun where the arrow can’t escape.

What you should do is have an arrow as a child, then turn off the renderer and create an arrow in those coordinates.

Does the physics engine check on the velocity, which in turn resolve the newArrow.transform.forward (blue axis), every frame? If the physics engine resolve the velocity only once, it should take the initial velocity and keep moving in the z direction even if the parent is a moving object. Any clarity on this is greatly appreciated!

Thanks for the tip on object pooling.

For creating the arrow in those coordinates, do you mean something like the code below?

private void FireArrow ()
    {
        GameObject newArrow = Instantiate(prefabArrow);        
        prefabArrow.transform.position = arrowLocation.transform.position; //where arrowLocation is the child arrow with the renderer off
        prefabArrow.transform.rotation = arrowLocation.transform.rotation;
        prefabArrow.transform.scale = arrowLocation.transform.scale;

        newArrow.GetComponent<Rigidbody>().velocity = newArrow.transform.forward * arrowSpeed;
   
    }

For another scenerio, what if I need to have the arrow instaniated on the crossbow and have it moving along with the crossbow (the character swings his arm as he moves) and then fire it only when enemy is in range. Does it mean I have to unchild (if there is a way to do it) the arrow before firing it?

Thanks!

What I was suggesting in my last comment was that you use an arrow on the crossbow model to show the animation of it being loaded and fired. But when it leaves the bow, turn it off and generate the arrow that is not attached to the crossbow.

What you have seems like it should work.

However, I would strongly recommend creating a pool like I said, AND once the bow fires the arrow the bow’s job should be done. Add force to the arrow on a script in the arrow.

The arrow will need to set all movement to zero on awake, then add force in a direction. If you don’t zero the movement it will continue whatever rotation and velocity it had when it gets turned off.

Then adjust the gravity and wind on the rigidbody.

Here’s a great video on how to make an object pool. It’s actually REALLY simple.

BTW, good on you for sticking it out and doing this the correct way. A lot of new people are looking for easy answers and don’t last too long. Hope you keep at it.