Народ помогите! Все мозги уже себе вынес. Есть корабль, который перемещается только по X,Z. Под ним поверхность с тегом. При нажатии мышки на поверхности, корабль должен плавно повернуться к месту нажатия, затем набирая скорость подлететь к назначению с плавным торможением и соответственно остановиться. С камерой RTS разобрался - а вот с кораблем никак. Помогите пожалуйста с кодом и разъяснениями.
Зачем делать два одинаковых поста в разных местах? Уже ответил, в другом месте: Пускаем луч в место щелчка мышью, затем направляем корабль туда.
Код
var Point : Vector3; var speed : float;
functiom Update () {
if (Input.GetButtonDown ("Fire1")){ var ray : Ray = Camera.main.ScreenPointToRay(Input.mousePosition); var hit : RaycastHit; if (Physics.Raycast(ray, hit, 1000)) Point = hit.point; } if (Vector3.Distance (transform.position, Point) > 10){ transform.Rotate (0, Vector3.Normalize(transform.InverceTransformDirection ( Point - transform.position)).z * time.deltaTime * 5, 0); transform.position += transform.forward * time.deltaTime * speed; } }
Копируй осторожнее, писал вслепую, наверное наделал ошибок) Но суть понятна. Плавности ускорения и торможения нет, но их легко сделать самому.
Сори за репост. И огромное спасибо за ответ. Но не срабатывает скрипт на JS Переделал на шару, но объект поворачивается в ходе смещения, а не перед тем как начать двигаться и смещается только при зажатой клавише. И кроме того уходит по оси Y - только. Мне необходимо, что-бы он двигался по Х,Z, получая координаты мыши от луча падающего на Plane, который висит под сценой (невидимая плоскость) Что здесь не так?:
Код
using UnityEngine; using System.Collections;
public class ShipMove : MonoBehaviour {
public Vector3 Point; private float Speed = 10; private Ray ray; private RaycastHit hit; public GameObject Ship; public Camera CAM;
void Update() { if (Input.GetKey(KeyCode.Mouse0)) { ray = CAM.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out hit)) { Point = hit.point; } if (Vector3.Distance(transform.position, Point) > 10) { Ship.transform.Rotate(0, Vector3.Normalize(transform.InverseTransformDirection(Point - transform.position)).z * Time.deltaTime * 5, 0); Ship.transform.position += transform.forward * Time.deltaTime * Speed; } } } }
Vector3.Normalize(transform.InverseTransformDirection(Point - transform.position)) - это локальный (для объекта, на котором висит скрипт, то есть для корабля) вектор от корабля к Point. Чем его значение по z меньше, тем, значит, меньше его угол до направления к точке. Если по z он = 0, то, либо корабль смотрит на point, либо смотрит в обратную сторону. Если разложить "Vector3.Normalize(transform.InverseTransformDirection(Point - transform.position))" по составляющим, то получим: Point - transform.position - направление в глобальной системе координат от корабля на точку. transform.InverseTransformDirection получает из глобального локальный вектор. (таким способом можно найти, к примеру, скорость смещения самолета в бок) Vector3.Normalize - находит единичный вектор. Получается, что если корабль стоит боком к точке, Vector3.Normalize(transform.InverseTransformDirection(Point - transform.position)).z = +-1 (в зависимости от того, какой стороной корабль повернут)
напиши что-то типа "если V3.N(tr.ITD( p - tr.p)).z < 0.2 перемешаем корабль. иначе поворачиваем корабль."
А что вы имели ввиду тут, я не понял. "И кроме того уходит по оси Y - только. "
Раз у вас скрипт висит не на корабле, то пишем так:
Код
Ship.transform.Rotate(0, Vector3.Normalize(Ship.transform.InverseTransformDirection(Point - Ship.transform.position)).z * Time.deltaTime * 5, 0); а так же if (Vector3.Distance(Ship.transform.position, Point) > 10)
Сообщение отредактировал VolkOrievith - Пт, 25 Сен 2015, 18:14
Огромное спасибо - я разобрался. Вы мне очень помогли.
Добавлено (25 Сен 2015, 19:31) --------------------------------------------- Вот работающий код, но пока без ускорения и торможения. Если кому интересно. Благодарим VolkOrievith, Кто хочет улучшить и дописать - кидаем ниже в посте. Думаю многие будут благодарны
public class ShipMove : MonoBehaviour {
public Vector3 Point; private float Speed = 5; private float RotateSpeed = 0.001f; private Ray ray; private RaycastHit hit; public GameObject Ship; public Camera CAM;
void Update() { if (Input.GetKey(KeyCode.Mouse0)) { ray = CAM.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out hit, 100f) == true) { Point = hit.point; } } if (Vector3.Distance(Ship.transform.position, Point) > 1) // Еслии мы нажали не на корабле. { if (hit.collider.tag == "Map") //Если луч коснулся карты { Point.y = 3; Ship.transform.Rotate(0, Vector3.Normalize(Ship.transform.InverseTransformDirection(Point - Ship.transform.position)).x * Time.deltaTime * 720, 0); Ship.transform.position += transform.forward * Time.deltaTime * Speed; } } } }
Ускорение - торможение. я на JS пишу, мне так привычнее) Делай переменную "currentSpeed" Через "Mathf.Lerp ( from : float, to : float, time.deltaTime * ускорение)" делаешь
Mathf.Lerp ( a, b, c) смешивает числа a и b в соотношении a*c + b*(1 - c)
то есть, если написать n = Mathf.Lerp ( 2, 4, 0.5), то n будет = 3 если написать n = Mathf.Lerp ( 2, 4, 0.0), то n будет = 2 если написать n = Mathf.Lerp ( 2, 4, 1.0), то n будет = 4
Можно реализовать по другому. пусть переменная speed = 0; объявляешь переменную acceleration (ускорение)
при нажатии мыши записываешь расстояние от корабля до точки (Допустим переменная называется startDist). пусть настоящее растояние от коробля до точки будет currentDist.
Пускаешь корабль. Пока currentDist > startDist / 2 speed += acceleration * time.deltaTime; (ускоряешь) когда станет currentDist < startDist / 2 (пройдена половина пути) speed -= acceleration * time.deltaTime; (замедляешь)