Ограничение вращения и перемещения по осям - Форум Игроделов
Пт, 17 Май 2024, 05:01 
 
Приветствую Вас Гость Главная | Регистрация | Вход
Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум Игроделов » UNITY3D » СКРИПТИНГ » Ограничение вращения и перемещения по осям
Ограничение вращения и перемещения по осям
dostalitionДата: Вт, 03 Дек 2013, 20:16 | Сообщение # 1
 
Сообщений: 155
Награды: 0
Репутация: 9
Статус: Offline
Подскажите как ограничить поворот и перемещение объекта по определённым осям в определённом диапазоне ...
 
СообщениеПодскажите как ограничить поворот и перемещение объекта по определённым осям в определённом диапазоне ...

Автор - dostalition
Дата добавления - 03 Дек 2013 в 20:16
игнатДата: Вт, 03 Дек 2013, 20:24 | Сообщение # 2
 
Сообщений: 706
Награды: 0
Репутация: 107
Статус: Offline
Доступно только для пользователей


Правила форума · участник GCC
 
СообщениеДоступно только для пользователей

Автор - игнат
Дата добавления - 03 Дек 2013 в 20:24
HomeshipДата: Ср, 18 Мар 2015, 15:08 | Сообщение # 3
 
Сообщений: 3
Награды: 0
Репутация: 0
Статус: Offline
данный вопрос теперь актуален для меня. biggrin
 
Сообщениеданный вопрос теперь актуален для меня. biggrin

Автор - Homeship
Дата добавления - 18 Мар 2015 в 15:08
ЛевшаДата: Ср, 18 Мар 2015, 16:17 | Сообщение # 4
Черный Волк
 
Сообщений: 7257
Награды: 30
Репутация: 3313
Статус: Offline
Mathf.Clamp();

X.cor.R (Prologue)
 
СообщениеMathf.Clamp();

Автор - Левша
Дата добавления - 18 Мар 2015 в 16:17
HomeshipДата: Ср, 18 Мар 2015, 17:17 | Сообщение # 5
 
Сообщений: 3
Награды: 0
Репутация: 0
Статус: Offline
Про то что так можно ограничить любое значение я в курсе.
Но вообще мне более интересна возможность применения такой загогулины как Configurable Joint.))

Контекст применения - реализация башенного орудия (основание-башня вращается вокруг локальной оси Y, ствол - вокруг оси X), наводимого на цель. Ограничены как скорости поворотов (наведения) так и углы возвышения ствола \ поворота основания-башни.
Башня стоит на другом меше, ствол - "дочка" от башни.

В принципе, первый вариант - "ручной":
1. взять плоскость в локальной XZ башни, задать границы поворотов как вектора в локальной системе координат башни.
2. выделить цель (bTarget) для башни - в плоскости XZ (проекцией на плоскость XZ башни)
3. затем - крутить башню через transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(bTarget.transform.position - transform.position), MaxRotation*Time.deltaTime); проверять углы между векторами-ограничителями
4. после завершения - ствол отдельно transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Target.transform.position - transform.position), MaxRotation*Time.deltaTime);
(вариант громоздкий и мне не нравится)

второй вариант:
через эйлеровы углы (взять углы между вектором направления ствола и вектором на цель, разделить на два угла - в XZ и по Y, крутить по одному - башню, по другому - ствол). Проверять углы на ограничения.
(Я вот не очень дружу с эйлеровыми углами, получаю постоянно не ожидаемые результаты)

третий вариант:
1. посадить башню на меш через Configurable Joint
2. прикрепить к башне ствол через Configurable Joint
3. настроить оба Configurable Joint на угловые ограничения и скорости поворотов
4. Передавать в Configurable Joint'ы - кватернионы на цели
(еще не пробовал)
 
СообщениеПро то что так можно ограничить любое значение я в курсе.
Но вообще мне более интересна возможность применения такой загогулины как Configurable Joint.))

Контекст применения - реализация башенного орудия (основание-башня вращается вокруг локальной оси Y, ствол - вокруг оси X), наводимого на цель. Ограничены как скорости поворотов (наведения) так и углы возвышения ствола \ поворота основания-башни.
Башня стоит на другом меше, ствол - "дочка" от башни.

В принципе, первый вариант - "ручной":
1. взять плоскость в локальной XZ башни, задать границы поворотов как вектора в локальной системе координат башни.
2. выделить цель (bTarget) для башни - в плоскости XZ (проекцией на плоскость XZ башни)
3. затем - крутить башню через transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(bTarget.transform.position - transform.position), MaxRotation*Time.deltaTime); проверять углы между векторами-ограничителями
4. после завершения - ствол отдельно transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Target.transform.position - transform.position), MaxRotation*Time.deltaTime);
(вариант громоздкий и мне не нравится)

второй вариант:
через эйлеровы углы (взять углы между вектором направления ствола и вектором на цель, разделить на два угла - в XZ и по Y, крутить по одному - башню, по другому - ствол). Проверять углы на ограничения.
(Я вот не очень дружу с эйлеровыми углами, получаю постоянно не ожидаемые результаты)

третий вариант:
1. посадить башню на меш через Configurable Joint
2. прикрепить к башне ствол через Configurable Joint
3. настроить оба Configurable Joint на угловые ограничения и скорости поворотов
4. Передавать в Configurable Joint'ы - кватернионы на цели
(еще не пробовал)

Автор - Homeship
Дата добавления - 18 Мар 2015 в 17:17
игнатДата: Ср, 18 Мар 2015, 17:35 | Сообщение # 6
 
Сообщений: 706
Награды: 0
Репутация: 107
Статус: Offline
Стандартный контроллер старый смотрели? Там какой-то мудак придумал делать для fps то, что нужно Вам. Но не забывайте то, что Вы написали выше.


Правила форума · участник GCC
 
СообщениеСтандартный контроллер старый смотрели? Там какой-то мудак придумал делать для fps то, что нужно Вам. Но не забывайте то, что Вы написали выше.

Автор - игнат
Дата добавления - 18 Мар 2015 в 17:35
HomeshipДата: Ср, 25 Мар 2015, 14:07 | Сообщение # 7
 
Сообщений: 3
Награды: 0
Репутация: 0
Статус: Offline
можно ссылку на "Стандартный контроллер старый" ?
И что именно из написанного мною выше - не забывать? biggrin

Добавлено (19 Мар 2015, 20:39)
---------------------------------------------
С Configurable Joint ничего не вышло.
Пошёл "ручным" путём. Вот то что у меня получилось.

Работает для конструкции:
1. GameObject (заместо основания-носителя)
1.1. GameObject (GunTower) на котором висит меш башни
1.1.1. GameObject (GunLine) на котором висит меш ствола
1.1.1.1. GameObject (FirePoint) - точка генерации снаряда и эффекта выстрела

Такая конструкция для отвязки геометрии от перемещаемых объектов. Для себя оформил в префаб. В любой момент - взял и навесил нужные меши на GameObject'ы - механика работы не меняется.

Код

using UnityEngine;
using System.Collections;

public class gunTracking : MonoBehaviour {

      public GameObject TrackedObject = null;
      public GameObject gunTower = null;
      public GameObject gunLine = null;

   public float hRotSpeed = 0.0f;
   public float vRotSpeed = 0.0f;

   public float minHangle = -90.0f;
   public float maxHangle = 90.0f;
   public float minVangle = -10.0f;
   public float maxVangle = 50.0f;

      public bool CanFire = true;

   // Use this for initialization
   void Start ()   
   {
    gunTower = transform.FindChild("GunTower").gameObject;
    gunLine = gunTower.transform.FindChild ("GunLine").gameObject;
   }
     
   // Update is called once per frame
   void Update ()   
          {
          if (TrackedObject)
              {
     Vector3 hVec = TrackedObject.transform.position;
     hVec.y = transform.position.y;
     Quaternion qv = Quaternion.LookRotation( hVec - gunTower.transform.position );
     hVec = qv.eulerAngles;
     if (hVec.y > 180)
      hVec.y = hVec.y - 360;
     if (hVec.y < minHangle || hVec.y > maxHangle)
      CanFire = false;
     else
      CanFire = true;
     hVec.y = Mathf.Clamp(hVec.y, minHangle, maxHangle);
     qv.eulerAngles = hVec;
     gunTower.transform.rotation = Quaternion.Lerp(gunTower.transform.rotation, qv, hRotSpeed * Time.deltaTime);

     if ((TrackedObject.transform.position.y != gunLine.transform.position.y) && CanFire)
      {
      qv = Quaternion.LookRotation( TrackedObject.transform.position - gunLine.transform.position );
      Vector3 vVec = qv.eulerAngles;
      if (vVec.x > 180)
       vVec.x = vVec.x - 360;
      if (vVec.x < minVangle || vVec.x > maxVangle)
       CanFire = false;
      else
       CanFire = true;
      vVec.x = Mathf.Clamp(vVec.x, minVangle, maxVangle);
      vVec.y = gunLine.transform.rotation.eulerAngles.y;
      vVec.z = gunLine.transform.rotation.eulerAngles.z;
      qv.eulerAngles = vVec;
      gunLine.transform.rotation = Quaternion.Lerp(gunLine.transform.rotation, qv, vRotSpeed*Time.deltaTime);
      }
                      }
       }
}

Добавлено (20 Мар 2015, 14:15)
---------------------------------------------
Хм. Некому заценить результат? Или сообщество вымерло? biggrin

Добавлено (25 Мар 2015, 07:52)
---------------------------------------------
Мда... выяснил косяк в своём скрипте. Он работает только для горизонтальных GunTower. Если основание башни пушки наклоняется - башня стремится сохраниться своё положение. Не пойдёт.

Ушёл дорабатывать.

Добавлено (25 Мар 2015, 14:07)
---------------------------------------------
Переделанная версия скрипта:

Код
using UnityEngine;
using System.Collections;

public class gunTracking : MonoBehaviour
{

  public GameObject TrackedObject = null;
  public GameObject gunTower = null;
  public GameObject gunLine = null;

  public float hRotSpeed = 0.0f;
  public float vRotSpeed = 0.0f;

  public float minHangle = -90.0f;
  public float maxHangle = 90.0f;
  public float minVangle = -10.0f;
  public float maxVangle = 50.0f;

  public bool CanFire = true;
  public bool ReadyToFire = true;
  public bool Disabled = false;

  // Use this for initialization
  void Start ()
  {
   gunTower = transform.FindChild ("GunTower").gameObject;
   gunLine = gunTower.transform.FindChild ("GunLine").gameObject;
   //trackingLimit = 30.0f;
  }

  void Update ()
  {
   if (Disabled)
    return;

   if (TrackedObject) {
    //RotateToTarget( );
    TrackTurret (gunTower.transform, gunLine.transform, TrackedObject.transform.position);

   }
  }

  void TrackTurret (Transform _turret, Vector3 _target)
  {
   TrackTurret (_turret, null, _target);
  }

  void TrackTurret (Transform _turret, Transform _gun, Vector3 _target)
  {
   Vector3 vTargetPosLocal = _turret.InverseTransformPoint (_target); // Target position in my local space
   vTargetPosLocal.y = 0.0f;       
// Target position local horizontal projection
   float angle = Vector3.Angle (vTargetPosLocal, Vector3.forward);

   float RotSpeed = hRotSpeed * Time.deltaTime;// * Common.tool.gameTimeScale;
   if (angle > 0.1f) {
    float rot = Mathf.Sign (vTargetPosLocal.x) * ((angle > RotSpeed) ? RotSpeed : angle);
    _turret.Rotate (0, rot, 0, Space.Self);
     
    float angle_res = _turret.localEulerAngles.y;
    if (angle_res > 180)
     angle_res -= 360;

    if (angle_res > maxHangle || angle_res < minHangle) {
     CanFire = false;
     //_turret.Rotate (0, -rot, 0, Space.Self);
    } else {
     CanFire = true;
    }
   }

   if (_gun) {
    if (angle < RotSpeed * 4 && CanFire)
     TrackGun (_gun, _target);
    else
     ReadyToFire = false;
   }
  }

  void TrackGun (Transform _gun, Vector3 _target)
  {
   Vector3 vTargetPosLocal = _gun.InverseTransformPoint (_target); // Target position in my local space
   vTargetPosLocal.Normalize ();
   float angle = Vector3.Angle (vTargetPosLocal, Vector3.forward);

   float RotSpeed = vRotSpeed * Time.deltaTime;// * Common.tool.gameTimeScale;
   if (angle > 0.1f) {
    float rot = -Mathf.Sign (vTargetPosLocal.y) * ((angle > RotSpeed) ? RotSpeed : angle);
    _gun.Rotate (rot, 0, 0, Space.Self);
    float angle_res = _gun.localEulerAngles.x;
    if (angle_res > 180)
     angle_res -= 360;
    if (angle_res > maxVangle || angle_res < minVangle) {
     CanFire = false;
     _gun.Rotate (-rot, 0, 0, Space.Self);
    } else {
     CanFire = true;
     if (angle <= RotSpeed * 2)
      ReadyToFire = true;
     else
      ReadyToFire = false;
    }
   }
  }

}


Теперь работает как надо. biggrin


Сообщение отредактировал Homeship - Чт, 19 Мар 2015, 20:41
 
Сообщениеможно ссылку на "Стандартный контроллер старый" ?
И что именно из написанного мною выше - не забывать? biggrin

Добавлено (19 Мар 2015, 20:39)
---------------------------------------------
С Configurable Joint ничего не вышло.
Пошёл "ручным" путём. Вот то что у меня получилось.

Работает для конструкции:
1. GameObject (заместо основания-носителя)
1.1. GameObject (GunTower) на котором висит меш башни
1.1.1. GameObject (GunLine) на котором висит меш ствола
1.1.1.1. GameObject (FirePoint) - точка генерации снаряда и эффекта выстрела

Такая конструкция для отвязки геометрии от перемещаемых объектов. Для себя оформил в префаб. В любой момент - взял и навесил нужные меши на GameObject'ы - механика работы не меняется.

Код

using UnityEngine;
using System.Collections;

public class gunTracking : MonoBehaviour {

      public GameObject TrackedObject = null;
      public GameObject gunTower = null;
      public GameObject gunLine = null;

   public float hRotSpeed = 0.0f;
   public float vRotSpeed = 0.0f;

   public float minHangle = -90.0f;
   public float maxHangle = 90.0f;
   public float minVangle = -10.0f;
   public float maxVangle = 50.0f;

      public bool CanFire = true;

   // Use this for initialization
   void Start ()   
   {
    gunTower = transform.FindChild("GunTower").gameObject;
    gunLine = gunTower.transform.FindChild ("GunLine").gameObject;
   }
     
   // Update is called once per frame
   void Update ()   
          {
          if (TrackedObject)
              {
     Vector3 hVec = TrackedObject.transform.position;
     hVec.y = transform.position.y;
     Quaternion qv = Quaternion.LookRotation( hVec - gunTower.transform.position );
     hVec = qv.eulerAngles;
     if (hVec.y > 180)
      hVec.y = hVec.y - 360;
     if (hVec.y < minHangle || hVec.y > maxHangle)
      CanFire = false;
     else
      CanFire = true;
     hVec.y = Mathf.Clamp(hVec.y, minHangle, maxHangle);
     qv.eulerAngles = hVec;
     gunTower.transform.rotation = Quaternion.Lerp(gunTower.transform.rotation, qv, hRotSpeed * Time.deltaTime);

     if ((TrackedObject.transform.position.y != gunLine.transform.position.y) && CanFire)
      {
      qv = Quaternion.LookRotation( TrackedObject.transform.position - gunLine.transform.position );
      Vector3 vVec = qv.eulerAngles;
      if (vVec.x > 180)
       vVec.x = vVec.x - 360;
      if (vVec.x < minVangle || vVec.x > maxVangle)
       CanFire = false;
      else
       CanFire = true;
      vVec.x = Mathf.Clamp(vVec.x, minVangle, maxVangle);
      vVec.y = gunLine.transform.rotation.eulerAngles.y;
      vVec.z = gunLine.transform.rotation.eulerAngles.z;
      qv.eulerAngles = vVec;
      gunLine.transform.rotation = Quaternion.Lerp(gunLine.transform.rotation, qv, vRotSpeed*Time.deltaTime);
      }
                      }
       }
}

Добавлено (20 Мар 2015, 14:15)
---------------------------------------------
Хм. Некому заценить результат? Или сообщество вымерло? biggrin

Добавлено (25 Мар 2015, 07:52)
---------------------------------------------
Мда... выяснил косяк в своём скрипте. Он работает только для горизонтальных GunTower. Если основание башни пушки наклоняется - башня стремится сохраниться своё положение. Не пойдёт.

Ушёл дорабатывать.

Добавлено (25 Мар 2015, 14:07)
---------------------------------------------
Переделанная версия скрипта:

Код
using UnityEngine;
using System.Collections;

public class gunTracking : MonoBehaviour
{

  public GameObject TrackedObject = null;
  public GameObject gunTower = null;
  public GameObject gunLine = null;

  public float hRotSpeed = 0.0f;
  public float vRotSpeed = 0.0f;

  public float minHangle = -90.0f;
  public float maxHangle = 90.0f;
  public float minVangle = -10.0f;
  public float maxVangle = 50.0f;

  public bool CanFire = true;
  public bool ReadyToFire = true;
  public bool Disabled = false;

  // Use this for initialization
  void Start ()
  {
   gunTower = transform.FindChild ("GunTower").gameObject;
   gunLine = gunTower.transform.FindChild ("GunLine").gameObject;
   //trackingLimit = 30.0f;
  }

  void Update ()
  {
   if (Disabled)
    return;

   if (TrackedObject) {
    //RotateToTarget( );
    TrackTurret (gunTower.transform, gunLine.transform, TrackedObject.transform.position);

   }
  }

  void TrackTurret (Transform _turret, Vector3 _target)
  {
   TrackTurret (_turret, null, _target);
  }

  void TrackTurret (Transform _turret, Transform _gun, Vector3 _target)
  {
   Vector3 vTargetPosLocal = _turret.InverseTransformPoint (_target); // Target position in my local space
   vTargetPosLocal.y = 0.0f;       
// Target position local horizontal projection
   float angle = Vector3.Angle (vTargetPosLocal, Vector3.forward);

   float RotSpeed = hRotSpeed * Time.deltaTime;// * Common.tool.gameTimeScale;
   if (angle > 0.1f) {
    float rot = Mathf.Sign (vTargetPosLocal.x) * ((angle > RotSpeed) ? RotSpeed : angle);
    _turret.Rotate (0, rot, 0, Space.Self);
     
    float angle_res = _turret.localEulerAngles.y;
    if (angle_res > 180)
     angle_res -= 360;

    if (angle_res > maxHangle || angle_res < minHangle) {
     CanFire = false;
     //_turret.Rotate (0, -rot, 0, Space.Self);
    } else {
     CanFire = true;
    }
   }

   if (_gun) {
    if (angle < RotSpeed * 4 && CanFire)
     TrackGun (_gun, _target);
    else
     ReadyToFire = false;
   }
  }

  void TrackGun (Transform _gun, Vector3 _target)
  {
   Vector3 vTargetPosLocal = _gun.InverseTransformPoint (_target); // Target position in my local space
   vTargetPosLocal.Normalize ();
   float angle = Vector3.Angle (vTargetPosLocal, Vector3.forward);

   float RotSpeed = vRotSpeed * Time.deltaTime;// * Common.tool.gameTimeScale;
   if (angle > 0.1f) {
    float rot = -Mathf.Sign (vTargetPosLocal.y) * ((angle > RotSpeed) ? RotSpeed : angle);
    _gun.Rotate (rot, 0, 0, Space.Self);
    float angle_res = _gun.localEulerAngles.x;
    if (angle_res > 180)
     angle_res -= 360;
    if (angle_res > maxVangle || angle_res < minVangle) {
     CanFire = false;
     _gun.Rotate (-rot, 0, 0, Space.Self);
    } else {
     CanFire = true;
     if (angle <= RotSpeed * 2)
      ReadyToFire = true;
     else
      ReadyToFire = false;
    }
   }
  }

}


Теперь работает как надо. biggrin

Автор - Homeship
Дата добавления - 25 Мар 2015 в 14:07
Форум Игроделов » UNITY3D » СКРИПТИНГ » Ограничение вращения и перемещения по осям
  • Страница 1 из 1
  • 1
Поиск:
Загрузка...

Game Creating CommUnity © 2009 - 2024