Accurately Determining Object's End Position

Hello everyone,

I’m currently creating a VR Hockey Goalie game. To give a brief explanation on how I have it set up, when the gaze is on the puck and the user presses a button (or clicks on PC), the game object that is supposed to stop the puck will go to the puck’s end position which is determined when the player shoots it. Here is how I have it set up:

This function determines where the player will shoot the puck on the net:

    public Vector3 RandomNetArea()
    {
        float y = Random.Range(netArea.bounds.min.y - 0.5f, netArea.bounds.max.y + 0.5f);
        float z = Random.Range(netArea.bounds.min.z - 0.5f, netArea.bounds.max.z + 0.5f);
        Vector3 shootSpot = new Vector3(transform.position.x, y, z);
        return shootSpot;
    }

This part of the script gets the above function, then trigger’s the puck to move towards the position on the net when the player shoots it:

    void Update ()
    {
        if (movePuck)
        {
            ShootPuck();
        }
    }

    void ShootPuck()
    {
        rb.AddForce((shootSpot - transform.position).normalized * speed);
    }

    void AimPuckAtNet()
    {
        shootSpot = scoreDetect.RandomNetArea();
        Debug.Log(shootSpot);
    }

    void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Stick")
        {
            AimPuckAtNet();
            ShootPuck();
            movePuck = true;
            Destroy(gameObject, 6f);
        }

        if (other.tag == "Net" || other.tag == "Player" || other.tag == "Post")
        {
            movePuck = false;
            rbGravity = true;
        }
    }

This function is attached to an event trigger on the puck which moves the player’s blocking object to the correct position to block the puck, of course, the farther the puck is away when the user interacts with it, the more accurate the save:

    public void SaveThePuck()
    {
        if (greatPC.puckInCollider)
        {
            player.transform.position = new Vector3(player.transform.position.x, scoreDetect.RandomNetArea().y, scoreDetect.RandomNetArea().z);
        }
        else if (goodPC.puckInCollider)
        {
            player.transform.position = new Vector3(player.transform.position.x, scoreDetect.RandomNetArea().y, scoreDetect.RandomNetArea().z);
            player.transform.localScale = goodSize;
        }
        else if (okayPC.puckInCollider)
        {
            player.transform.position = new Vector3(player.transform.position.x, scoreDetect.RandomNetArea().y, scoreDetect.RandomNetArea().z);
            player.transform.localScale = okaySize;
        }
    }

My problem is that the player object does not accurately go where the puck is going to end up on the net. I have a feeling this has to do with the way force is added to the puck, but I am not entirely sure. I have tested the RandomNetArea() function to see where the puck is going, while checking the actual puck game object in the editor to see if they match up, and it doesn’t seem like they do. Is there a better way I could add force to the puck so it is accurate, while keeping it realistic? Thanks for your help in advance.

I can see a couple of wrong things there:

1- rb.AddForce is called inside Update. You should add forces and torques from FixedUpdate.

Applying forces in Update means you’re probably applying the same force many times per physics step. The result applying an indeterminate amount of force, as all them are summed together before each physics update. FixedUpdate runs at the physics rate, while Update typically runs at the screen refresh rate.

2- Mixing forces and speed. This line doesn’t have sense:

rb.AddForce((shootSpot - transform.position).normalized*speed);

I can guess that you want to move the rigidbody towards shootSpot at a specific speed. In that case, this will do it better. Ensure it’s called from FixedUpdate:

Vector3 velocity = (shootSpot - rb.position).normalized * speed;
rb.MovePosition(rb.position + velocity * Time.deltaTime);

Thanks for your reply, Edy. After testing your code, the puck seems to become a little more accurate. The player still doesn’t accurately go to the shootSpot to save the puck, so there must be an issue somewhere else in my code. I got rid of the ± 0.5f in the RandomNetArea function to see if that would change it, and it is still the same. What I am experiencing now is that I am clicking on the same puck numerous times, and the player is going to multiple positions. The shootSpot doesn’t change until the next shot is taken, so I am at a loss as to what is wrong.

EDIT:

I can’t believe I didn’t spot this before, but I am calling the function RandomNetArea(), which means it is giving the player a random position on the net each time, rather than getting the puck’s position.

Vector3 velocity = (shootSpot - rb.position).normalized * speed;
rb.MovePosition(rb.position + velocity * Time.deltaTime);

Although this code works, when it hits the player (sphere) it just seems to go around the object and does not bounce. I added a physics material to the puck, but I am pretty new to working with physics. If the puck has gravity, it seems as if there isn’t enough force to lift it off the ground to the exact position where it is supposed to go. How can I properly go about doing this? I am using another method now which seems more simple:

rb.velocity = shootSpot * speed;

My main issue is now getting the puck to have the characteristics of a puck. Any ideas?