#c# #unity3d
#c# #unity3d
Вопрос:
я хочу вращать куб вокруг трубы размером 1×1 с помощью клавиш со стрелками. (слева и справа).
Проблема в том, что я не могу использовать встроенные функции, которые напрямую устанавливают положение и местоположение преобразования. (Например, transform.LookAt, transform.Rotate или transform.RotateAround). Потому что мне нужны векторные значения эйлера вращения и позиции для нескольких элементов, прежде чем я изменю значение преобразования, которое я хочу повернуть.
Я пробовал разные методы, но пока безуспешно.
Я пытался использовать sin-cos для поворота, но не мог понять, как заставить его работать как для поворота, так и для положения.
_timer = Time.deltaTime * _larvaSpeed;
float x = -Mathf.Cos(_timer) * distanceBetweenCenter;
float y = Mathf.Sin(_timer) * distanceBetweenCenter;
Вот чего я хочу добиться. Нажимая вправо или влево, перемещайте и поворачивайте объект вокруг трубы.
Результат, который я хочу. (Если я немного нажал клавишу со стрелкой вправо).
Я был бы признателен за любую помощь. Спасибо!
Комментарии:
1. соедините этот куб как дочерний элемент с пустым игровым объектом и поверните этот пустой игровой объект
2. Как я уже сказал, мне нужна математика, стоящая за этим.
3. вы можете сделать это, используя некоторую функцию в unity, о математическом способе и математике: вы можете использовать x ^ 2 y ^ 2 = r2 для достижения этой цели, x и y — движущаяся ось, а r — радиус (расстояние между кубом и центром трубы)… все, что вам нужно сделать, это сохранить это уравнение истинным, а «r» всегда постоянным… допустим, мы начинаем с x = 0 и y = 4, на втором кадре уменьшаем y как .1 и, используя это x ^ 2 y ^ 2 = r ^ 2, получаем новое значение x, затем преобразуем.position = (новый x, новый y, z);…… я установлю скрипт на ответ
4. Я был бы очень рад, если бы вы могли показать мне пример того, как задать положение и поворот объекта с помощью вашей математики.
5. Когда я это делал, я просто играл с углами и инспектором во время выполнения. Предполагая, что вы вращаетесь только по одной оси, это нормально. В противном случае это может потребовать дополнительной работы.
Ответ №1:
вот решение, использующее математику круга, и я настоятельно рекомендовал не использовать его, это просто для понимания кругового перемещения с использованием уравнения круга, как @FaTaLL спрашивает в комментариях
Уравнение окружности… (x1 — x2) ^ 2 (y1 — y2) ^ 2 = r ^ 2
x1, y1 — позиция куба
x2, y2 — это позиция канала
r — расстояние между кубом и трубой;
using UnityEngine;
public class Rotating : MonoBehaviour
{
public GameObject pipe;
public float Delta;
Vector3 nextpos;
bool compareY;
bool next;
int switchx;
float storeVarAxis;
float x, y, r;
private void Start()
{
next = true;
switchx = 1;
compareY = true;
x = transform.position.x - pipe.transform.position.x;
y = transform.position.y - pipe.transform.position.y;
storeVarAxis = y;
r = Mathf.Sqrt(x * x y * y);
}
private void Update()
{
if (next)
{
if (compareY == true)
{
y -= Delta * Time.deltaTime;
if (y <= -storeVarAxis)
{
y = -storeVarAxis;
compareY = false;
switchx = -1;
}
}
else
{
y = Delta * Time.deltaTime;
if (y >= storeVarAxis)
{
y = storeVarAxis;
compareY = true;
switchx = 1;
}
}
float v = r * r - y * y;
x = Mathf.Sqrt(Mathf.Abs(v));
nextpos = new Vector3(pipe.transform.position.x x * switchx, pipe.transform.position.y y, transform.position.z);
next = false;
}
transform.position = Vector3.MoveTowards(transform.position, nextpos, 1f * Time.deltaTime);
if(Vector3.Distance(transform.position, nextpos) < .05) transform.position = nextpos;
if (transform.position.x.Equals(nextpos.x) amp;amp; transform.position.y.Equals(nextpos.y)) next = true;
}
}
что ж, рекомендуемый способ — использовать этот простой скрипт
using UnityEngine;
public class Rotating : MonoBehaviour
{
public float speed;
public GameObject pipe;
float r, angle;
Vector3 startpos;
private void Start()
{
r = Mathf.Abs(transform.position.y - pipe.transform.position.y);
angle = 0;
transform.position = pipe.transform.position;
startpos = transform.position;
}
void Update()
{
angle = angle speed * Time.deltaTime;
transform.rotation = Quaternion.EulerAngles(0,0, angle);
transform.position = startpos (transform.rotation * new Vector3(r, 0, 0));
}
}
Комментарии:
1. Ты легенда !!. Это было именно то, что я искал. Спасибо за ваше время и объяснение.
2. всегда в работе!
Ответ №2:
Я думаю, что Quaternion * Vector3 — это то, что вы ищете. К счастью, вращение блока в его собственных локальных координатах — это то же самое вращение, которое вам нужно применить к положению блока.
public float speed; //how fast to rotate
public float radius; //radius of the cylinder
public float angle; //angle around it
void Update()
{
if (Input.GetKey(KeyCode.LeftArrow))
{
angle = angle speed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.RightArrow))
{
angle = angle - speed * Time.deltaTime;
}
//figure out the rotation (from euler angles i guess??)
var quat = Quaternion.EulerAngles(new Vector3(0, angle, 0));
//ok uh what is the box position?? lets just multiply
var unrotated_position = new Vector3(radius, 0, 0);
var rotated_position = quat * unrotated_position;
this.transform.position = rotated_position;
//oh yea and also rotate the box in its own local coordinates
this.transform.rotation = quat;
}
Комментарии:
1. Спасибо за ответ. Ваше решение работает очень хорошо.