Я пытаюсь создать экземпляр своего ballPrefab при нажатии на позицию курсора.
Я знаю, что Input.mousePosition принимает только координаты x и y. Однако моя камера смотрит в направлении x (глобально) (, как вы можете видеть здесь ). Поэтому я изменил x на 0. Проблема в том, что префабы появляются в одной и той же позиции y и z каждый раз, независимо от того, где я щелкаю левой кнопкой мыши.
Это мой код.
[SerializeField]
private GameObject ballPrefab;
void Update()
{
Vector3 mousePos = Input.mousePosition;
mousePos = Camera.main.ScreenToWorldPoint(mousePos);
mousePos.x = 0;
if (Input.GetButtonDown("Fire1"))
{
Instantiate(ballPrefab, mousePos, ballPrefab.transform.rotation);
}
}
Я искал в Интернете около часа.
Я наткнулся на Cursor.Position, который кажется старым (?), поскольку System.Windows.Forms не существует.
Я также пытался сделать положение мыши new Point , но тогда я не могу преобразовать его в Vector3.
Я также подумал о transform.localPosition, так как моя камера смотрит в «неправильном» направлении, но я не могу применить трансформацию, если использую Input.mousePosition.
Наконец, я читал о raycasts, но я не особо в них разбираюсь.





Чтобы разобраться в проблеме, лучше всего понять, как работает ScreenToWorldPoint. Закройте один глаз и смотрите прямо перед собой, не двигая глазами (как 2D-камера). Затем вытяните одну из ваших рук, возьмите указательный палец и поместите его поверх чего-то на расстоянии вашего взгляда (например, указатель мыши), но не двигайте глазами и не смотрите прямо на него. Функция ScreenToWorldPoint в некоторой степени работает, отмечая, где находится ваш палец по осям X и Y в поле зрения вашего глаза, но ей также необходимо знать, насколько далеко вы вытянули руку и палец по оси Z (глубина), чтобы ваш совместите палец с тем, на что вы указываете. Как провести линию от глаза к пальцу.
Проблема в том, что Input.mousePosition вернет Vector3, где ось Z (глубина) равна 0. Это означает, что когда вы передаете его ScreenToWorldPoint, он в основном не знает, как далеко вы вытянули руку и палец. Это все равно, что взять палец и поместить его прямо поверх глазного яблока, но добавить очень мало X или Y, чтобы палец все еще указывал на ваш объект. Вы получите очень маленькие значения X и Y, а значение Z будет везде, где находится ваше глазное яблоко (камера).
Другая проблема заключается в том, что вы вручную устанавливаете результирующее значение X равным 0. Таким образом, X всегда будет 0, а Z всегда будет в положении Z камеры, а значение Y будет очень маленьким, и все потому, что значение глубины не было задано. передается функции ScreenToWorldPoint. Это приведет к тому, что ballPrefab всегда окажется примерно в одном и том же месте в мире.
Поэтому попробуйте дать ему ссылку на глубину следующим образом:
public float distanceFromCamera = 5f;
public GameObject ballPrefab;
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Vector3 mousePos = Input.mousePosition;
mousePos = Camera.main.ScreenToWorldPoint(
new Vector3(mousePos.x, mousePos.y, distanceFromCamera));
Instantiate(ballPrefab, mousePos, ballPrefab.transform.rotation);
}
}
Кажется, вы хотите, чтобы мяч всегда находился на оси X мира, поэтому другое решение — использовать абсолютное значение положения камеры по оси X (которое представляет собой расстояние от камеры до точки X = 0) в качестве значения глубины.
mousePos = Camera.main.ScreenToWorldPoint(
new Vector3(mousePos.x, mousePos.y,
Mathf.Abs(Camera.main.transform.position.x)));
Это позволит вам перемещать камеру внутрь и наружу (в вашем случае по оси X) без необходимости настраивать какую-либо переменную distanceFromCamera.
1. Зачем мне нужно принимать Mathf.Abs? Если я уберу это, он будет работать так же. 2. Если я правильно понял, глобальная позиция камеры по оси X — это расстояние до глобальной оси Z/расстояние до оси X экрана, и поэтому это значение глубины. Но что, если я хочу, чтобы мои шары появлялись с глобальным X = 10, а моя камера — с глобальным X = 30? Тогда значение глубины будет равно 30, и мои шары будут появляться в точке X = 0, верно?
1: я не знал, была ли позиция вашей камеры -X или +X, и использование Abs устранит необходимость знать и всегда будет передавать положительное значение глубины, которое представляет истинное значение расстояния, потому что «расстояние» никогда не должно быть отрицательным числом. 2: Судя по тому, как вы это описали, возможно, все еще есть какое-то недопонимание. Поскольку ваша камера направлена в направлении X, это означает, что положение камеры по оси X может быть полезно для значения глубины функции ScreenToWorldPoint.
Если вы хотите, чтобы мяч появлялся в глобальном X = 10, я рекомендую добавить «deepOffset» некоторого типа, например: public float depthOffset = 10f;. Затем добавьте или вычтите эту переменную смещения с позицией X камеры, прежде чем отправлять ее в функцию ScreenToWorldPoint (STWP), например: Mathf.Abs(Camera.main.transform.position.x) - depthOffset. Простая установка значения X на 10 для объекта не будет работать хорошо, потому что перемещение объекта ближе или дальше от камеры сделает его визуально выше или ниже, чем положение щелчка мыши на экране. Вот почему глубина важна для функции STWP.
Это сработало, большое спасибо :) У меня есть несколько вопросов.