3
\$\begingroup\$

I have this code that simulates the movement of a projectile without using the unity physics engine

IEnumerator LaunchProjectile(int angle, float speed)
{

    // Move projectile to the position of throwing object + add some offset if needed.
    Projectile.position = transform.position + new Vector3(0, 0f, 0);
    Projectile.rotation = transform.root.rotation;
    Debug.Log(transform.root.eulerAngles);

    // Calculate distance to target
    float target_Distance = speed * (Mathf.Sin(2 * firingAngle * Mathf.Deg2Rad) / gravity);

    // Extract the X  Y componenent of the velocity
    float Vx = Mathf.Sqrt(speed) * Mathf.Cos(firingAngle * Mathf.Deg2Rad);
    float Vy = Mathf.Sqrt(speed) * Mathf.Sin(firingAngle * Mathf.Deg2Rad); 

    // Calculate flight time.
    float flightDuration = target_Distance / Vx;

    this.arrowSimulationScript = Projectile.gameObject.GetComponentInChildren<ArrowSimulation>();

    float elapse_time = 0;

    while (!arrowSimulationScript.Collided())
    {
        Projectile.Translate(0, (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime);

        Projectile.LookAt(Projectile.position - new Vector3(0,  (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime));

        arrowSimulationScript.Velocity = new Vector3(0, (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime).magnitude;

        elapse_time += Time.deltaTime;

        yield return null;
    }
}

The arrow is fired in the direction of the object which has this script attached. To make the arrow rotate I use this line of code:

Projectile.LookAt(Projectile.position - new Vector3(0,  (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime));

The arrow moves towards the right direction but with the tip facing the z axis direction, instead of the direction of the bow. Here is a video of the problem: https://www.youtube.com/watch?v=cyK6DXxTw_E

If I comment out that line of code the arrow fly with the tip facing the direction of the bow, but it doesn't rotate.

\$\endgroup\$
  • \$\begingroup\$ I didn't look too closely as the script, but if the model is facing the wrong way and your code is correct, you can always rotate the origin in your 3D modeling program. Or you can make the model a child of a Transform, and move that Transform instead, with the model's rotation offset. The latter option also helps with organization in your hierarchy. \$\endgroup\$ – Selali Adobor Sep 10 '15 at 16:06
  • \$\begingroup\$ Projectile is already the father of a model, and is facing the right way. The problem is surely in the LookAt method but I don't know why. \$\endgroup\$ – AR89 Sep 10 '15 at 16:12
  • \$\begingroup\$ If the model is separate from the projectile and the projectile is facing the wrong way in flight, but the right way out of it, rotate the model so that it's the wrong way out of flight and the right way in flight. LookAt also has a worldUp vector, but usually if it's pointing in the wrong direction, the model is what should be offset. \$\endgroup\$ – Selali Adobor Sep 11 '15 at 4:34
  • \$\begingroup\$ could it be caused by the arrow clipping the player? And this is causes the physics to rotate it? just a thought as i had the same problem with a crossbow in a zombie survival game i made a wile back. \$\endgroup\$ – Ryan white Aug 15 '16 at 10:21
1
\$\begingroup\$

try adding the delatV to current position, to get the next step position

  Projectile.LookAt(Projectile.position + new Vector3(0,  (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime));

other than, an advice, calculate only once

new Vector3(0, (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime)

and store in a temp variable .

\$\endgroup\$
0
\$\begingroup\$

This code might help you since it turns the object according to its movement direction.

 public class OrientTowardsDirection : MonoBehaviour {

        Vector3 prevLoc = Vector3.zero;
        Vector3 moveDirection = Vector3.zero;
        public Transform cube;
        private float MaxTurnSpeed = 100;

        void Update () {

            Orient();
        }
        void Orient()
        {
             moveDirection = transform.TransformDirection(moveDirection);// Turns the direction from local to world space
             moveDirection = (transform.position - prevLoc);// calculate direction vector;
             Quaternion wanted_rotation = Quaternion.LookRotation(moveDirection);//create the rotation
             transform.rotation = Quaternion.RotateTowards(transform.rotation, wanted_rotation,MaxTurnSpeed* Time.deltaTime);// apply the rotation with a max turn speed so its smooth
             prevLoc = transform.position;// change our prev pos.
        }
    }

Note that for a arrow you might want to skip the Quaternion.RotateTowards step and set the object's rotation to wanted_rotation directly. Let me know how this works out ;)

\$\endgroup\$
0
\$\begingroup\$

I believe in your original code you want to switch the operands in your LookAt.

This:

  Projectile.LookAt(Projectile.position - new Vector3(0,  (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime));

Should be:

  Projectile.LookAt(new Vector3(0,  (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime) - Projectile.position);

Also, as @dnk pointed out, you should store your new vector in a variable so you're not computing it three times.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.