forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Уроки (http://forum.boolean.name/forumdisplay.php?f=145)
-   -   Движение 2D космического корабля (http://forum.boolean.name/showthread.php?t=15858)

pax 16.11.2011 13:27

Движение 2D космического корабля
 
Вложений: 1
Решил написать пример, как можно организовать управление перемещением 2D космическим кораблем.



Ссылка на Web-плеер: http://shgames.ru/unity/astro/

В аттаче пакадж со скриптом и сценой.

Скрипт собственно вот:
PHP код:

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(_shipSpeedMathf.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.deltaTimetransform.up);

        
// рассчитываем поврот корпуса корабля с дампингом
        
_shipRotation Mathf.Lerp(_shipRotation, -rot 300.1f);
        
// рассчитываем значение поворота корпуса
        
shipModel.localRotation _shipDefaultRotation Quaternion.AngleAxis(_shipRotationVector3.right);

    }


Желаю удачно разобраться :)

Amatsu 16.11.2011 13:46

Ответ: Движение 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);
  }
}


pax 16.11.2011 13:52

Ответ: Движение 2D космического корабля
 
2Amatsu Хоть бы описание какое написал.

UPD: твое движение не зависит от времени - следовательно будет работать на каждой машине с разной скоростью.

UPD2: Если конечно ты не изобрел свою версию твинига для Unity ;)

UPD3: В моем примере только крен не зависит... надо бы потом поправить.

Amatsu 16.11.2011 13:54

Ответ: Движение 2D космического корабля
 
Цитата:

Сообщение от pax (Сообщение 209912)
2Amatsu Хоть бы описание какое написал.

Это код управления кораблем из Kefir Fighter, переложенный на юнити

pax 16.11.2011 14:01

Ответ: Движение 2D космического корабля
 
Еще хотел сказать - моделер из меня в блендере так себе. На работе больше нету софта. Там в скрипте вращение корпуса я реализовал через вектор Vector3.right - это потому, что модель корабля у меня не по осям повернута (не смог повернуть правильно в блендере :(). Можете в сцене посмотреть что там не так. Если правильно модель ориентировать: Вектор вперед - Z, вектор вверх - Y. То тогда вместо Vector3.right подставляем Vector3.forward.

pax 16.11.2011 14:08

Ответ: Движение 2D космического корабля
 
Небольшое дополнение (избавимся от "магических" чисел):
PHP код:

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(_shipSpeedMathf.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.deltaTimetransform.up);

        
// рассчитываем поврот корпуса корабля с дампингом
        
_shipRotation Mathf.Lerp(_shipRotation, -rot maxRotationAnglerotationDamping);
        
// рассчитываем значение поворота корпуса
        
shipModel.localRotation _shipDefaultRotation Quaternion.AngleAxis(_shipRotationVector3.right);

    }



RegIon 16.11.2011 16:57

Ответ: Движение 2D космического корабля
 
blender3d.org.ua Учись Блендеру,PAX.;)

pax 16.11.2011 17:12

Ответ: Движение 2D космического корабля
 
Я не моделер ;)

pax 20.11.2011 13:59

Ответ: Движение 2D космического корабля
 
Вложений: 1
Итак часть вторая - пролет через края экрана.

Для этого нам понадобятся 2 скрипта. Первый будет рассчитывать область экрана, второй будет работать на каждом объект, который должен пролетать через края экрана.

1. Скрипт расчета области игры.
PHP код:

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 bufferArea20height bufferArea);
        
areaHalfSize areaSize 0.5f;
    }

    
// при нажатии Play можно увидеть саму область
    
public void OnDrawGizmos()
    {
        
Gizmos.DrawWireCube(Vector3.zeroareaSize);
    }


Вешаем этот скрипт на пустой объект, объект должен находиться в сцене, чтобы выполнялся расчет.
В примере буферная зона равна 10 единицам мира.

2. Скрипт для объектов.
PHP код:

using UnityEngine;

// скрипт необходимо вешать на каждый объект,
// который должен переходить через края экрана
public class RectangleAreaObject MonoBehaviour
{
    public 
void Update()
    {
        var 
size RectangleArea.areaSize;
        var 
halfSize RectangleArea.areaHalfSize;

        
// если координата объекта выходит за половину размера области, 
        // то смещаем объект в обратную сторону по этой координате на полный размер

        
if (transform.position.halfSize.x)
        {
            var 
pos transform.position;
            
pos.-= size.x;
            
transform.position pos;
        }
        else if (
transform.position.< -halfSize.x)
        {
            var 
pos transform.position;
            
pos.+= size.x;
            
transform.position pos;
        }

        if (
transform.position.halfSize.z)
        {
            var 
pos transform.position;
            
pos.-= size.z;
            
transform.position pos;
        }
        else if (
transform.position.< -halfSize.z)
        {
            var 
pos transform.position;
            
pos.+= size.z;
            
transform.position pos;
        }

    }


Этот скрипт вешаем на корабль на тот же объект, на котором висит контроллер корабля, написанный в предыдущем примере.

Собственно результат: http://shgames.ru/unity/astro_example2/

В аттаче доработанный пример.

Friend123 04.06.2012 14:37

Ответ: Движение 2D космического корабля
 
Вот вопрос возник. Я пытался проделать похожее на своем корабле, он у меня крутится вокруг оси Z, но не поворачивается по Y. Это я так понимаю из-за того, что у вас объект сделан дочерним, а если его не делать дочерним, то что нужно поменять, чтобы работало как тут?

Mopnex 28.04.2016 22:48

Ответ: Движение 2D космического корабля
 
А как сделать чтобы корабль так же летал, плавно входил в повороты, но не кнопками WASD а по клику мышки? чтобы летел в конкретно - заданную точку?

Arton 28.04.2016 23:16

Ответ: Движение 2D космического корабля
 
Цитата:

Сообщение от Mopnex (Сообщение 305849)
А как сделать чтобы корабль так же летал, плавно входил в повороты, но не кнопками WASD а по клику мышки? чтобы летел в конкретно - заданную точку?

Как правило берутся координаты куда кликнул мышью, затем объект разворачивают в сторону точки и двигают к ней.

Жека 29.04.2016 14:54

Ответ: Движение 2D космического корабля
 
Можно так.
Есть вектор скорости - это направление, в котором летит корабль.
По клику мышки запоминаем точку клика.
Далее рассчитываем угол поворота от текущего вектора скорости до линии, соединяющей текущее положение и точку клика.
Однако поворачиваем не сразу на весь этот угол, а на небольшую его часть.
В итоге получится плавный разворот.
Функция Lerp вроде как помогает получать дельту значения.


Часовой пояс GMT +4, время: 22:03.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot