Q: How to calculate the accuracy of shot in percentage I am making a game in Unity (C#), where you need to shoot a target.
Once you make a shot - the accuracy of your shot is to be shown.
The idea of my game is to be as precise as possible, so I cannot just make zones on the target for 100% accuracy, 90%, 80%, etc.
My idea for the calculations is the following: 
PercentageErrorForXCoordinate = ((YourShotX – CenterOfTargetX)/ CenterOfTargetX) x 100;
PercentageErrorForYCoordinate = ((YourShotY – CenterOfTargetY)/ CenterOfTargetY) x 100;
TotalPercentageError = (PercentageErrorForXCoordinate+ PercentageErrorForYCoordinate)/2; 
=> eventually I have 2 big problems:

* when spawned coordinates are (0,0) - as I won't be able to divide later;

* if the shot is far away from the target the result is too big. 
Do you have any ideas on how to calculate correctly in this case?
The code is below:
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.SceneManagement;
using UnityEngine.UI;


public class GameManager : MonoBehaviour
{

    public GameObject spawnManager;
    
    //public GameObject shot;




    public List<GameObject> Prefabs;
   

    //public Vector3 miwen; 
    

    public bool GameIsActive;

    private float minValueX = -2.5f; //  x value of the center of the left-most square
    private float minValueY = -9f; //  y value of the center of the bottom-most square

    private float targetPosX;
    private float targetPosY;

    private float pointerPosX;
    private float pointerPosY;

    private float pointerCorPosX;
    private float pointerCorPosY;

    private float pointerDisplayPosX;
    private float pointerDisplayPosY;

    private float AccuracyX;
    private float AccuracyY;
    private float TotalAccuracy;





    public TextMeshProUGUI centerCalculator;

    // Start is called before the first frame update
    void Start()
    {
        SpawnerActivator();

        GameIsActive = true;
        centerCalculator.gameObject.SetActive(false);

    }





    // Update is called once per frame
    void Update()
    {

        

    }





    void  SpawnerActivator()
    {
        int index = Random.Range(0, Prefabs.Count);
        Instantiate(Prefabs[index], RandomSpawnPosition(), Prefabs[index].transform.rotation);
        SpawnerPrecisionCalculator();
    }





    // Generate a random spawn position based on a random index from 0 to 3
    Vector3 RandomSpawnPosition()
    {
        float spawnPosX = minValueX + RandomPosX();
        float spawnPosY = minValueY + RandomPosY();

        Vector3 spawnPosition = new Vector3(spawnPosX, spawnPosY, 0);
        return spawnPosition;

    }





    // Generates random square index from 0 to 3, which determines which square the target will appear in
    float RandomPosX()
    {
        return Random.Range(-1, 7);
    }

    // Generates random square index from 0 to 3, which determines which square the target will appear in
    float RandomPosY()
    {
        return Random.Range(0, 19);
    }

   void SpawnerPrecisionCalculator()
    {
       
        targetPosX = GameObject.FindGameObjectWithTag("Miwen").transform.position.x;
        targetPosY = GameObject.FindGameObjectWithTag("Miwen").transform.position.y;
        //Debug.Log(targetPosX + " " + targetPosY);
        


    }

    public void CalculatePosition()
    {

        pointerPosX = GameObject.FindGameObjectWithTag("Pointer").transform.position.x;
        pointerPosY = GameObject.FindGameObjectWithTag("Pointer").transform.position.y;
        
        //Debug.Log("Pointer:" + " " + pointerPosX + " " + pointerPosY + " " + "target" + " " + targetPosX + " " + targetPosY);
    }

    public void CorPosCalculator()
    {
        //pointerCorPosX = Mathf.Round(targetPosX - pointerPosX);

        //pointerCorPosY = Mathf.Round(targetPosY - pointerPosY);

        pointerCorPosX = targetPosX - pointerPosX;

        pointerCorPosY = targetPosY - pointerPosY;

        pointerDisplayPosX = (Mathf.Round((targetPosX - pointerPosX) * 1000)) / 1000;

        pointerDisplayPosY = (Mathf.Round((targetPosY - pointerPosY) * 1000)) / 1000;







        AccuracyX = ((Mathf.Abs(pointerPosX) - Mathf.Abs(targetPosX)) / Mathf.Abs(targetPosX)) * 100;
        AccuracyY = ((Mathf.Abs(pointerPosY) - Mathf.Abs(targetPosY)) / Mathf.Abs(targetPosY)) * 100;
        TotalAccuracy = (AccuracyX + AccuracyY) / 2;




        Debug.Log($"Pointer: {pointerPosX} {pointerPosY}\nTargett: {targetPosX} {targetPosY}\nTotalAccuracy: {TotalAccuracy}");

        centerCalculator.text = "Diff X:" + pointerDisplayPosX + "      " + "Diff Y:" + pointerDisplayPosY;
        centerCalculator.gameObject.SetActive(true);




    }


}


A: Typically you would use an exponential function to calculate a fixed range score with a potentially infinite numeric input.
In your case the following function could be used:
y = 100*10^(-x*strictness)
For any positive x value (zero included) you will receive a value for y that is between 0 and 100. Exactly zero for x will net you 100 and infinity will give you 0. You can adjust how generous the awarded points are by modifying the strictness constant.
public Vector2 YourShot;
public Vector2 CenterOfTarget;
public float strictness;//You will likely need a value above 1

float distance = Vecor2.Distance(YourShot,CenterOfTarget);
float score = 100*Mathf.Pow(10,-distance*strictness);


A: You must not take the coordinates of the target as reference but its radius. Something like this
float radiusOfTarget = ...;
float radiusSquared = radiusOfTarget * radiusOfTarget;

float dx = CenterOfTargetX - YourShotX;
float dy = CenterOfTargetY - YourShotY;
float deviationSquared = dx * dx + dy * dy;
if (deviationSquared  >= radiusSquared) { // Pythagoras!
    error = 100;
} else {
    error = 100 * MathF.Sqrt(deviationSquared) / radiusOfTarget;
}

Or, if you are happy with a quadratic mapping
    error = 100 * deviationSquared / radiusSquared;

This will be more forgiving when close to the target center.
