0
\$\begingroup\$

I have a game that spawns "enemies" within a sphere around the camera, the player moves the camera to target and simply presses the screen to fire. For now my "ammo" is simply a sphere and for visual purposes the object I'm firing from is a sphere located below the camera. the "ammo" should fire from the "cannon" below the camera directly towards the crosshair and hit whatever target is in the crosshair.

With some online help this is how my crosshair is generated:

if(Time.timeScale != 0)
    {
        if(crosshairTexture!=null)
            GUI.DrawTexture(new Rect((Screen.width-crosshairTexture.width*crosshairScale)/2 ,(Screen.height-crosshairTexture.height*crosshairScale)/2, crosshairTexture.width*crosshairScale, crosshairTexture.height*crosshairScale),crosshairTexture);
        else
            Debug.Log("No crosshair texture set in the Inspector");
    }

And currently this is how my "Cannon" works

if ( Input.GetButton("Fire1") && Time.time > mNextFire){

        mNextFire = Time.time + mFireRate;

        Rigidbody projectile= (Instantiate (ammo, gameObject.transform.position, Quaternion.identity)).GetComponent<Rigidbody>();
        projectile.AddForce (projectile.transform.forward * mHitForce);
    }

Then on the ammo, I have this:

  int x = Screen.width / 2;
  int y = Screen.height / 2;
  transform.LookAt(new Vector3(x, y));

but it is horribly inaccurate, I had to move the canon around so it appears to be firing from below the camera, the speed/velocity is off and it barely hits what's being aimed at. It also often appears to go through the cross hair but doesn't collide with the target. I know it's not the target cause if I move the canon around a bit and keep the target still, it hits, the target takes damage, life bar decreases and the "ammo"that hit it "disappears".

I know questions like this are all over the internet however none of them describe my problem, and the ones I found somewhat similar have no solutions. After days of frustration I decided to ask the question here, I just started unity last week so I apologise in advance if my problem seems silly.

Also, I've been seeing a lot of things with raycast, I found this script that projected a yellow laser towards the centre of the screen;

void Update()
{
    int x = Screen.width / 2;
    int y = Screen.height / 2;

    Ray ray = camera.ScreenPointToRay(new Vector3(x, y));

    Debug.DrawRay(ray.origin, ray.direction * 1000, new Color(1f,0.922f,0.016f,1f));

}

it worked perfectly and projected the laser right to the centre but what am I supposed to do with it afterwards? how do I make the projectile follow it? I'd really appreciate the help. Thank you!

\$\endgroup\$
1
\$\begingroup\$

The idea of using raycasting to model projectiles is that we assume the projectile moves fast enough that we can treat its motion as instant, not continuous. That is why it works well with gunfire, where the human eye usually wouldn't catch the bullet traveling through the air anyway.

The alternative, to make the projectile a rigidbody, is preferred for slower-moving objects since it updates with each timestep. You can get the path, but if the object moves fast enough, it might entirely skip past the object with which it is supposed to collide, like if it moves 2 units per step and the object is one unit wide.

The problem in your scenario is that you want to both see the path and have accurate collisions when the projectile moves fast. Two possible solutions:

  1. Assuming the target does not move, you can use a raycast to check for collisions. Then, you can Lerp from the cannon to the point of impact. You delay the action that happens on impact until it reaches the destination, even though you already decided it would hit. This, however, would register false collisions if the target moves during that time.

  2. Launch the projectile normally, with a rigidbody. Then, each step, raycast ahead in the projectile's path, but only about as far as the projectile would move in that step based on its velocity. This means if you get a raycast hit, it would collide between the current step and the next step. Then call the code for when the target is hit either now or, probably better, on the next frame.

Update

To clarify the second solution, imagine you fire the projectile with a velocity of <2,6> (2 units per second in the x direction per second, and 6 units in the y direction per second. I'll stick to 2 dimensions for simplicity, but the concept is the same in 3 dimensions). Next frame, the object should be located at (oldPosition.x + 2 * deltaTime, oldPosition.y + 6 * deltaTime). Cast a ray from the old position to this new position. If it hits anything, then you know that there should be a collision on the next frame, even if the object is moving so fast that the physics engine fails to catch it.

\$\endgroup\$
  • \$\begingroup\$ I'm sorry, I'm having a hard time understanding what you're saying. The second solution you gave is for if the target moves? it does, they move around the camera. What exactly do you mean by raycast ahead. \$\endgroup\$ – Drew U Apr 21 '17 at 23:28

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.