|
16.11.2011, 13:27
|
#1
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Движение 2D космического корабля
Решил написать пример, как можно организовать управление перемещением 2D космическим кораблем.
Ссылка на Web-плеер: http://shgames.ru/unity/astro/
В аттаче пакадж со скриптом и сценой.
Скрипт собственно вот:
using UnityEngine; public class SpaceShipController : MonoBehaviour { public float speed = 5; // максимальная скорость корабля в секунду public float rotationSpeed = 90; // максимальный поворот в секунду public Transform shipModel; // сслыка на модель корабля (должна быть дочерним объектом) // значение вращения корпуса по умолчанию private Quaternion _shipDefaultRotation; // текущий поворот корпуса private float _shipRotation = 0; // текущая скорость private float _shipSpeed = 0; public void Start() { // сохраняем значение вращения корпуса по умолчанию _shipDefaultRotation = shipModel.localRotation; } public void Update() { // скорость корабля с дампингом _shipSpeed = Mathf.Lerp(_shipSpeed, Mathf.Max(Input.GetAxis("Vertical"), 0), 0.1f); // смещаем корабль в перед на нужную величину transform.position += transform.forward * _shipSpeed * speed * Time.deltaTime; var rot = Input.GetAxis("Horizontal"); // вращаем корабль по оси Z transform.rotation *= Quaternion.AngleAxis(rot * rotationSpeed * Time.deltaTime, transform.up); // рассчитываем поврот корпуса корабля с дампингом _shipRotation = Mathf.Lerp(_shipRotation, -rot * 30, 0.1f); // рассчитываем значение поворота корпуса shipModel.localRotation = _shipDefaultRotation * Quaternion.AngleAxis(_shipRotation, Vector3.right); } }
Желаю удачно разобраться
|
(Offline)
|
|
Эти 5 пользователя(ей) сказали Спасибо pax за это полезное сообщение:
|
|
16.11.2011, 13:46
|
#2
|
Дэвелопер
Регистрация: 24.07.2008
Сообщений: 1,544
Написано 1,095 полезных сообщений (для 2,706 пользователей)
|
Ответ: Движение 2D космического корабля
// Player class
public class Player {
public GameObject move_pivot, rotate_pivot, model;
public float yaw_speed,yaw_rotation,x_speed,z_speed;
// Procedure of player creation
public void Create() {
move_pivot = new GameObject("player");
rotate_pivot = new GameObject("player_rotate_pivot");
rotate_pivot.transform.parent = move_pivot.transform;
model = Instantiate(player_mesh) as GameObject;
model.transform.localScale = new Vector3(10, 10, 10);
model.transform.name = "player_model";
model.transform.parent = rotate_pivot.transform;
}
// Procedure of player update
public void Update(float yaw_acceleration, float speed_acceleration) {
float width;
if (Input.GetKey(KeyCode.LeftArrow)) {yaw_speed += -yaw_acceleration;};
if (Input.GetKey(KeyCode.RightArrow)) {yaw_speed += yaw_acceleration;};
yaw_speed *= 0.85F;
yaw_rotation += yaw_speed;
rotate_pivot.transform.localRotation = Quaternion.Euler(0, yaw_rotation, 0);
model.transform.localRotation = Quaternion.Euler(0, 0, yaw_speed * 10);
if (Input.GetKey(KeyCode.UpArrow)) {
x_speed += (Mathf.Sin(((rotate_pivot.transform.transform.eulerAngles.y - 180) * Mathf.PI) / 180F) * speed_acceleration);
z_speed += (Mathf.Cos(((rotate_pivot.transform.transform.eulerAngles.y - 180) * Mathf.PI) / 180F) * speed_acceleration);
};
x_speed *= 0.95F;
z_speed *= 0.95F;
width = ((float)Screen.width / (float)Screen.height) * 4.6F;
if ((move_pivot.transform.position.x < -width) & (x_speed < 0)) {x_speed = 0;};
if ((move_pivot.transform.position.x > width) & (x_speed > 0)) {x_speed = 0;};
if ((move_pivot.transform.position.z < -4.4F) & (z_speed < 0)) {z_speed = 0;};
if ((move_pivot.transform.position.z > 4.4F) & (z_speed > 0)) {z_speed = 0;};
move_pivot.transform.Translate(x_speed, 0, z_speed);
}
}
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
16.11.2011, 13:52
|
#3
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Движение 2D космического корабля
2Amatsu Хоть бы описание какое написал.
UPD: твое движение не зависит от времени - следовательно будет работать на каждой машине с разной скоростью.
UPD2: Если конечно ты не изобрел свою версию твинига для Unity
UPD3: В моем примере только крен не зависит... надо бы потом поправить.
|
(Offline)
|
|
16.11.2011, 13:54
|
#4
|
Дэвелопер
Регистрация: 24.07.2008
Сообщений: 1,544
Написано 1,095 полезных сообщений (для 2,706 пользователей)
|
Ответ: Движение 2D космического корабля
Сообщение от pax
2Amatsu Хоть бы описание какое написал.
|
Это код управления кораблем из Kefir Fighter, переложенный на юнити
|
(Offline)
|
|
Эти 2 пользователя(ей) сказали Спасибо Amatsu за это полезное сообщение:
|
|
16.11.2011, 14:01
|
#5
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Движение 2D космического корабля
Еще хотел сказать - моделер из меня в блендере так себе. На работе больше нету софта. Там в скрипте вращение корпуса я реализовал через вектор Vector3.right - это потому, что модель корабля у меня не по осям повернута (не смог повернуть правильно в блендере ). Можете в сцене посмотреть что там не так. Если правильно модель ориентировать: Вектор вперед - Z, вектор вверх - Y. То тогда вместо Vector3.right подставляем Vector3.forward.
Последний раз редактировалось pax, 16.11.2011 в 15:13.
|
(Offline)
|
|
16.11.2011, 14:08
|
#6
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Движение 2D космического корабля
Небольшое дополнение (избавимся от "магических" чисел):
using UnityEngine; public class SpaceShipController : MonoBehaviour { public float speed = 5; // максимальная скорость корабля в секунду public float speedDamping = 0.1f; // дампинг скорости public float rotationSpeed = 90; // максимальный поворот в секунду public float rotationDamping = 0.1f; // дампинг вращения корпуса public float maxRotationAngle = 30f; // максимальный укол крена корпуса public Transform shipModel; // сслыка на модель корабля (должна быть дочерним объектом) // значение вращения корпуса по умолчанию private Quaternion _shipDefaultRotation; // текущий поворот корпуса private float _shipRotation; // текущая скорость private float _shipSpeed; public void Start() { // сохраняем значение вращения корпуса по умолчанию _shipDefaultRotation = shipModel.localRotation; } public void Update() { // скорость корабля с дампингом _shipSpeed = Mathf.Lerp(_shipSpeed, Mathf.Max(Input.GetAxis("Vertical"), 0), speedDamping); // смещаем корабль в перед на нужную величину transform.position += transform.forward * _shipSpeed * speed * Time.deltaTime; var rot = Input.GetAxis("Horizontal"); // вращаем корабль по оси Z transform.rotation *= Quaternion.AngleAxis(rot * rotationSpeed * Time.deltaTime, transform.up); // рассчитываем поврот корпуса корабля с дампингом _shipRotation = Mathf.Lerp(_shipRotation, -rot * maxRotationAngle, rotationDamping); // рассчитываем значение поворота корпуса shipModel.localRotation = _shipDefaultRotation * Quaternion.AngleAxis(_shipRotation, Vector3.right); } }
|
(Offline)
|
|
16.11.2011, 16:57
|
#7
|
Элита
Регистрация: 16.01.2010
Адрес: Новосибирск
Сообщений: 2,157
Написано 502 полезных сообщений (для 1,012 пользователей)
|
Ответ: Движение 2D космического корабля
blender3d.org.ua Учись Блендеру,PAX.
|
(Offline)
|
|
16.11.2011, 17:12
|
#8
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Движение 2D космического корабля
Я не моделер
|
(Offline)
|
|
Эти 2 пользователя(ей) сказали Спасибо pax за это полезное сообщение:
|
|
20.11.2011, 13:59
|
#9
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Движение 2D космического корабля
Итак часть вторая - пролет через края экрана.
Для этого нам понадобятся 2 скрипта. Первый будет рассчитывать область экрана, второй будет работать на каждом объект, который должен пролетать через края экрана.
1. Скрипт расчета области игры.
using UnityEngine;
// скрипт рассчитывает область, выходя за которую // корабль перемещается на другую сторону экрана public class RectangleArea : MonoBehaviour { // статическая переменная области, // которая используется в скрипте RectangleAreaObject public static Vector3 areaSize; public static Vector3 areaHalfSize;
// буферная область для перелета за экраном public float bufferArea;
// считаем область каждый кадр, // но по хорошему надо считать только при смене разрешения игры public void Update() { CalculateArea(); }
// функция рассчета области public void CalculateArea() { var cam = Camera.mainCamera; var camTransform = cam.transform; // считаем что камера оп осям z и x не смещена, т.е. x и z равны нулю // само действи игры происходит в проскости x0z var distance = camTransform.position.y; var halfAngle = cam.fov * 0.5f; var height = distance * Mathf.Tan(halfAngle * Mathf.Deg2Rad) * 2; var width = height * cam.aspect; areaSize = new Vector3(width + bufferArea, 20, height + bufferArea); areaHalfSize = areaSize * 0.5f; }
// при нажатии Play можно увидеть саму область public void OnDrawGizmos() { Gizmos.DrawWireCube(Vector3.zero, areaSize); } }
Вешаем этот скрипт на пустой объект, объект должен находиться в сцене, чтобы выполнялся расчет.
В примере буферная зона равна 10 единицам мира.
2. Скрипт для объектов.
using UnityEngine;
// скрипт необходимо вешать на каждый объект, // который должен переходить через края экрана public class RectangleAreaObject : MonoBehaviour { public void Update() { var size = RectangleArea.areaSize; var halfSize = RectangleArea.areaHalfSize;
// если координата объекта выходит за половину размера области, // то смещаем объект в обратную сторону по этой координате на полный размер
if (transform.position.x > halfSize.x) { var pos = transform.position; pos.x -= size.x; transform.position = pos; } else if (transform.position.x < -halfSize.x) { var pos = transform.position; pos.x += size.x; transform.position = pos; }
if (transform.position.z > halfSize.z) { var pos = transform.position; pos.z -= size.z; transform.position = pos; } else if (transform.position.z < -halfSize.z) { var pos = transform.position; pos.z += size.z; transform.position = pos; }
} }
Этот скрипт вешаем на корабль на тот же объект, на котором висит контроллер корабля, написанный в предыдущем примере.
Собственно результат: http://shgames.ru/unity/astro_example2/
В аттаче доработанный пример.
|
(Offline)
|
|
Эти 3 пользователя(ей) сказали Спасибо pax за это полезное сообщение:
|
|
04.06.2012, 14:37
|
#10
|
AnyKey`щик
Регистрация: 04.06.2012
Сообщений: 1
Написано 0 полезных сообщений (для 0 пользователей)
|
Ответ: Движение 2D космического корабля
Вот вопрос возник. Я пытался проделать похожее на своем корабле, он у меня крутится вокруг оси Z, но не поворачивается по Y. Это я так понимаю из-за того, что у вас объект сделан дочерним, а если его не делать дочерним, то что нужно поменять, чтобы работало как тут?
|
(Offline)
|
|
28.04.2016, 22:48
|
#11
|
AnyKey`щик
Регистрация: 28.04.2016
Сообщений: 1
Написано 0 полезных сообщений (для 0 пользователей)
|
Ответ: Движение 2D космического корабля
А как сделать чтобы корабль так же летал, плавно входил в повороты, но не кнопками WASD а по клику мышки? чтобы летел в конкретно - заданную точку?
|
(Offline)
|
|
28.04.2016, 23:16
|
#12
|
Быдлокодер
Регистрация: 05.07.2009
Адрес: Проспит
Сообщений: 5,021
Написано 2,312 полезных сообщений (для 5,349 пользователей)
|
Ответ: Движение 2D космического корабля
Сообщение от Mopnex
А как сделать чтобы корабль так же летал, плавно входил в повороты, но не кнопками WASD а по клику мышки? чтобы летел в конкретно - заданную точку?
|
Как правило берутся координаты куда кликнул мышью, затем объект разворачивают в сторону точки и двигают к ней.
|
(Online)
|
|
29.04.2016, 14:54
|
#13
|
Дэвелопер
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,376
Написано 491 полезных сообщений (для 886 пользователей)
|
Ответ: Движение 2D космического корабля
Можно так.
Есть вектор скорости - это направление, в котором летит корабль.
По клику мышки запоминаем точку клика.
Далее рассчитываем угол поворота от текущего вектора скорости до линии, соединяющей текущее положение и точку клика.
Однако поворачиваем не сразу на весь этот угол, а на небольшую его часть.
В итоге получится плавный разворот.
Функция Lerp вроде как помогает получать дельту значения.
|
(Offline)
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 11:25.
|