{"id":2712,"title":"\u0422\u0435\u0441\u0442 \u0441 \u0448\u0438\u0444\u0440\u0430\u043c\u0438 \u0438\u0437 \u0435\u0434\u044b: \u043d\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u0435 \u043d\u0430 \u0433\u043e\u043b\u043e\u0434\u043d\u044b\u0439 \u0436\u0435\u043b\u0443\u0434\u043e\u043a","url":"\/redirect?component=advertising&id=2712&url=https:\/\/tjournal.ru\/special\/kaleidofood&placeBit=1&hash=28db11ae3219937c44aa1427c824eab338831a6e3433f41ae22d24d5717c4772","isPaidAndBannersEnabled":false}
Вопросы
Dmitriy Baturinec

Как сделать управление RTS камеры на смартфонах?

Привет DTF, мне нужны твои лучшие умы!

В чем проблема. Я новичок и я делаю RTS управление камерой в 3D пространстве для телефона, и у меня не получается сделать Зумм камеры. Как только я касаюсь 2 пальцами экрана, камера просто движется вперёд без остановки.

Сама камера прикреплена к ригу и является его дочерним объектом, как на этом рисунке:

Скрипт камеры вы видите ниже:

[SerializeField] private Camera _mainCamera; [SerializeField] private float speedCam; [SerializeField] private float speedZoom; private Vector3 newPosition; private Vector3 dragStartPosition; private Vector3 dragCurrentPosition; private Vector3 newZoom; [SerializeField] private Vector3 zoomAmount; private void Awake() { _mainCamera = GetComponentInChildren<Camera>(); newPosition = transform.position; } private void Start() { } private void Update() { HandleTouchInput(); } private void HandleTouchInput() // метод передвижение и зумм - сенсор { foreach (Touch touch in Input.touches) { if (Input.touchCount == 1) { if (touch.phase == TouchPhase.Began) // касается ли палец экрана и создаем плейн, куда отправляем луч { Plane plane = new Plane(Vector3.up, Vector3.zero); Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position); float entry; if (plane.Raycast(ray, out entry)) // если луч касаеться плейна, присваеваем его позицию { dragStartPosition = ray.GetPoint(entry); } } if (touch.phase == TouchPhase.Moved) // проверяем двигается ли палец и отправляем луч { Plane plane = new Plane(Vector3.up, Vector3.zero); Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position); float entry; if (plane.Raycast(ray, out entry)) // если луч касаеться олейна передаем значения новой позиции { dragCurrentPosition = ray.GetPoint(entry); newPosition = transform.position + dragStartPosition - dragCurrentPosition; } } } if (Input.touchCount == 2) // метод для зумма { var Finger1 = Input.GetTouch(0); var Finger2 = Input.GetTouch(1); var TouchFinger0Direction = Finger1.position - Finger1.deltaPosition; var TouchFinger1Direction = Finger2.position - Finger2.deltaPosition; var TouchesPosition = Vector3.Distance(Finger1.position, Finger2.position); var TouchesDirection = Vector3.Distance(TouchFinger0Direction, TouchFinger1Direction); if (TouchesPosition > TouchesDirection) { newZoom -= zoomAmount; } if (TouchesPosition < TouchesDirection) { newZoom += zoomAmount; } // как движется зумм _mainCamera.gameObject.transform.localPosition = Vector3.MoveTowards(_mainCamera.gameObject.transform.localPosition, newZoom, Time.deltaTime * speedZoom); } } newPosition.x = Mathf.Clamp(newPosition.x, 16f, 145f); // ограничеваем передвижение newPosition.z = Mathf.Clamp(newPosition.z, -8.5f, 390f); transform.position = Vector3.MoveTowards(transform.position, newPosition, Time.deltaTime * speedCam); // плавное передвижение }

Я прошу:

• Помогите мне сделать зум для камеры!

• Как я могу ограничить зум?

Важно:
• Камера в режиме Перспективы, а значит зум через угол обзора делать нельзя!

0
30 комментариев
Популярные
По порядку
Написать комментарий...
Советский глобус

if (TouchesPosition > TouchesDirection)
{
newZoom -= zoomAmount;
}
if (TouchesPosition > TouchesDirection)
{
newZoom += zoomAmount;
}
Знак сравнения в одном из случаев поменять случайно не забыл?

Ответить
2
Развернуть ветку
Dmitriy Baturinec

Поправил, но не помогло

Ответить
0
Развернуть ветку
Советский глобус

А зачем ты в цикле обходишь все касания? Да еще и зумишь в нем же. При этом в любом условии у тебя в самом конце есть движение камеры. Запусти дебаг и посмотри, куда ты отправляешь камеру.
А вообще, у тебя newZoom же нигде не обнуляется и при удержании двух пальцев всегда будет расти (уменьшаться), отправляя камеру куда-то в далекие края.

Ответить
0
Развернуть ветку
Dmitriy Baturinec

А как вы предлагаете сделать код управления?

Ответить
1
Развернуть ветку
Dmitriy Baturinec

Можно скриптом написать? Я новичок и мне интересно!

Ответить
0
Развернуть ветку
Советский глобус

Я сам не в курсе. В другой области работаю и в Unity на мобилки не разрабатывал.
Но я бы условие на одно касание вынес бы за цикл, чтобы лишний раз не гонять его. Да и в целом избавился бы от него, т.к. каждый шаг не дает всей необходимой информации для обработки нажатий, поскольку получает только одно из нажатий.
Что однозначно стоит сделать в любом случае, так это вынести из него любые изменения позиций по выше указанной причине. Сейчас у тебя при двух нажатиях дважды срабатывает зум. Если бы не стояло условие на количество нажатий = 2, то при трех срабатывало бы трижды. И так далее.

Ответить
1
Развернуть ветку
Dmitriy Baturinec

Спасибо за помощь!

Ответить
0
Развернуть ветку
Dmitriy Baturinec

Спасибо за инфу. Посмотрю

Ответить
0
Развернуть ветку
Dmitriy Baturinec

ХММММММ

Ответить
0
Развернуть ветку
Dmitriy Baturinec

ХММММММ

Ответить
0
Развернуть ветку
Ярослав Голубев

На gamedev.ru и habr запость.

Ответить
1
Развернуть ветку
Dmitriy Baturinec

Спасибо!

Ответить
0
Развернуть ветку
Советский глобус

Ты перепутал площадки

Ответить
0
Развернуть ветку
Dmitriy Baturinec

Почему? Здесь мне уже не раз помогали.

Ответить
0
Развернуть ветку
Советский глобус

Тут только срутся и устраивают драмы.

Ответить
2
Развернуть ветку
Dmitriy Baturinec

Не согласен. Бывает люди помогают решить проблему!

Ответить
0
Развернуть ветку
Советский глобус

Да я попытался пошутить :(

Ответить
0
Развернуть ветку
Dmitriy Baturinec

Либо у тебя получается плохо, либо я тупой! А может все сразу :)

Ответить
0
Развернуть ветку
A Hideo Kojima Game

Как тебе написали выше, нужно отделить обработку инпута от движения камеры.
Не очень пойму зачем тут рейкасты и плейны, можно смотреть дельту сдвига тача. Тут конечно есть опасность, что на разных девайсах будет разрый сдвиг из-за разрешений и ppi, но можно нормализовать это дело.
Если ты делаешь зум движением вверх-вниз (подозреваю что по transform.forward камеры), то можно закешировать стартовую позицию и потом просто не давать двигаться если дистанция от стартовой больше какого-то значения.
С зумом алгоритм примерно такой: на touchphase begin сохраняешь положение обоих пальцев (или дистанцию между ними), потом в конце кадра чекаешь увеличилось или уменьшилось ли расстояние, в соответствии с этим делаешь зум ин или зум аут, обновляешь сохранённое расстояние на новое полученное. И так пока пальцев на экране 2.

Ответить
0
Развернуть ветку
Dmitriy Baturinec

Не понимаю, в каком смысле отделить инпут от движения камеры?
Как его можно нормализовать?

Может у вас есть примеры кода?

Ответить
0
Развернуть ветку
A Hideo Kojima Game

Выше написали, что у тебя движение камеры в цикле, где ты проходишься по тачам. Нужно вынести за цикл.
Нормализовать значит привести значения к отрезку 0, 1. Касательно координат экрана это будет так: координата X делится на Screen.width, а Y на Screen.height.

Ответить
1
Развернуть ветку
Dmitriy Baturinec

Спасибо

Ответить
0
Развернуть ветку
A Hideo Kojima Game

https://pastebin.com/2JqAKsqh
вот что-то такое у меня получилось, как всегда в теории всё оказалось не так как на практике, эджкейсы вылезли, нормализация делает всё только хуже и тд =)

скорее всего тебе все равно придется решать проблему того, что на разных разрешениях будут разные скорости драга и зума, я обычно решаю это пропорцией. то есть подгоняю скорости под одно разрешение, а потом пропорционально меняю в зависимости от Screen.Height и Screen.Width девайса

Ответить
0
Развернуть ветку
Иван Чернов

Помогите мне сделать зум для камеры!
Камера прикреплена к якорному объекту, объект смотри по лучу, камера смещается от якорного объекта по {transform.froward};

Как я могу ограничить зум?
...если сферический коллайдер рядом с камерой регистрирует пересечение - камера сдвигается назад по {- transform.forward};

Камера в режиме Перспективы, а значит зум через угол обзора делать нельзя!
А, так всё проще:
1. отказаться от перспективы
-= или =-
2. сжимать/разжимать область рендера.

Ответить
0
Развернуть ветку
Dmitriy Baturinec

Нет, я сейчас делаю зум перемещением, а не увеличением угла обзора. Делать коллайдеры для ограничения? Это лютый мазохизм и ограничения можно дать через Mathf.Clamp.

А вот transform.froward спасибо, почитаю больше об этом

Ответить
0
Развернуть ветку
Dmitriy Baturinec

Проблема зумма - это, то что он не останавливается.

Ответить
0
Развернуть ветку
Иван Чернов

private float maxdepth;
а уж у чему ты её привяжешь - твоё дело.

Ответить
0
Развернуть ветку
Boris Gavrikov

Do you guy not have PC?

Ответить
0
Развернуть ветку
Dinar Fakhriev

if (Input.touchCount == 0)
{
newPosition = transform.position
}

?

Ответить
0
Развернуть ветку
Dmitriy Baturinec

Спасибо всем за вашу помощь!

Ответить
0
Развернуть ветку
Читать все 30 комментариев
null