Страницы

Поиск по вопросам

пятница, 11 января 2019 г.

Поворот текстуры и движение на определённый угол Unity 5

Есть текстура, бегает в неком радиуса, стукаясь об стенки - получает новое направление.
Vector2 dir;
void Start() { InvokeRepeating("Move", 1 / 24f, 1 / 24f); dir = Vector2.right; }
void Update() {
}
void Move() { transform.Translate(dir); }
void OnTriggerEnter2D(Collider2D coll) {
if (coll.name.StartsWith("bright")) { dir = -Vector2.right; } if (coll.name.StartsWith("bleft")) { dir = Vector2.right; }
if (coll.name.StartsWith("btop")) { dir = Vector2.down; } }
Хочу чтобы текстура бегала не (вверх\низ\лево\право) а на определённый угол Пробовал так
dir = Vector(0, 1);
Но подчёркивает красным. Как на 45* допустим повернуть?
А соответственный вопрос - как повернуть на случайный угол? На случайный, кроме допустим, 0?


Ответ

1) Конструкция вида dir = Vector(0, 1); не работает потому, что нужно писать Vector2/Vector3, а не просто Vector. И так как вы не обращаетесь к свойству как здесь
Vector2.down;
то значит надо обращаться к экземпляру класса, т.е. надо писать
dir = new Vector2(0, 1);
2) Даже если писать new Vector2(0, 1) в теории он должен полететь строго вверх, но никак не под углом. Для этого нужно объект либо повернуть, либо так и указать new Vector2(1, 1), т.е. лететь вверх и вправо, т.е. под углом
3) При отскоке от сторон на одинаковый угол достаточно помнить, что при достижении какой-либо стороны - скорость меняется на противоположную (без учета сил трения, сил отскока и прочего). А-ля угол падения равен углу отражения. А значит при достижении правой или левой стороны (то есть ось X), достаточно изменить направление движение на противоположное для данной оси: X = -X;. А так как по вертикали он (объект) итак будет двигаться в заданном направлении, то получится отскок на угол. С отскоком по вертикали все точно также.
Из вышесказанного следует:
Vector2 dir; Transform myTransform;
public float vx = 1f; public float vy = 1f; public float speed = 1f;
void Start() { //InvokeRepeating("Move", 0.07f, 0.07f); myTransform =transform; dir = new Vector2(vx, vy); }
void Update() { myTransform.Translate(dir * speed * Time.deltaTime); }
// void Move() { transform.Translate(dir * speed * Time.deltaTime); }
void OnCollisionEnter2D(Collision2D coll) {
if (coll.gameObject.name.StartsWith("bright") || coll.gameObject.name.StartsWith("bleft")) { vx = -vx; }
if (coll.gameObject.name.StartsWith("btop") || coll.gameObject.name.StartsWith("bbottom")) { vy = -vy; }
dir = new Vector2(vx, vy); }
4) По поводу рандома. Можно использовать две вещи
Собственно класс из .Net: System.Random Из Unity: Random.Range - который сгенерирует число в заданном диапазоне
Например вместо
vx = -vx;
можно написать
var sign = Mathf.Sign(vx); var random = Random.Range(1f, 2f);
vx = random * sign * -1;
vx примет значение в диапазоне от 1 до 2. sign - нужен здесь, чтоб установить корректно значение vx, ибо мы не знаем в данный момент времени какое значение у него имеется: положительное или отрицательное. А так берем знак, генерируем число, присваиваем его с противоположным знаком.
5) По поводу углов поворота у Юнити есть много различных вариантов и это проще все вычитать самому. Кто-то делает разные параметры X и Y и в результате достигается угол, кто-то использует transform.localRotation, кто-то метод transform.Rotate(). Есть вот даже пример:
public class FollowPath: MonoBehaviour { public float speed; public float rotationSpeed; //transform Transform myTrans; //object position Vector3 myPos; //object rotation Vector3 myRot; //object rotation float angle; // Use this for initialization void Start() { myTrans = transform; myPos = myTrans.position; myRot = myTrans.rotation.eulerAngles; } // Update is called once per frame void FixedUpdate() { //converting the object euler angle's magnitude from to Radians angle = myTrans.eulerAngles.magnitude * Mathf.Deg2Rad; //rotate object Right & Left if (Input.GetKey(KeyCode.RightArrow)) { myRot.z -= rotationSpeed; } if (Input.GetKey(KeyCode.LeftArrow)) { myRot.z += rotationSpeed; } //move object Forward & Backward if (Input.GetKey(KeyCode.UpArrow)) { myPos.x += (Mathf.Cos(angle) * speed) * Time.deltaTime; myPos.y += (Mathf.Sin(angle) * speed) * Time.deltaTime; } if (Input.GetKey(KeyCode.DownArrow)) { myPos.x += Mathf.Cos(angle) * Time.deltaTime; myPos.y += Mathf.Sin(angle) * Time.deltaTime; } //Apply myTrans.position = myPos; myTrans.rotation = Quaternion.Euler(myRot); } }
Где само движение построено на вычислении угла и подстановке в transform.position
myPos.x += (Mathf.Cos (angle) * speed) * Time.deltaTime; myPos.y += (Mathf.Sin (angle) * speed) * Time.deltaTime;
Для вашего примера можно попробовать что-то такое:
private Vector2 dir; private Transform myTransform;
public float speed; public float angle; public float vx = 1; public float vy = 1;
void Start() { myTransform = transform; InvokeRepeating("Move", 0.05f, 0.05f);
dir = Vector2.right;
angle = Vector2.Angle(Vector2.right, new Vector2(vx, vy)); myTransform.localRotation = Quaternion.Euler(0, 0, angle); }
void Move() { myTransform.Translate(dir * speed * Time.deltaTime); }
void OnCollisionEnter2D(Collision2D coll) { if (coll.gameObject.name.StartsWith ("bright") || coll.gameObject.name.StartsWith("bleft")) { vx = -vx; }
if (coll.gameObject.name.StartsWith ("btop") || coll.gameObject.name.StartsWith("bbottom")) { vy = -vy; }
angle = Vector2.Angle(Vector2.right, new Vector2(vx, vy)); if (coll.gameObject.name.StartsWith ("bleft") && vy < 0 || coll.gameObject.name.StartsWith ("bright") && vy < 0 || coll.gameObject.name.StartsWith("btop")) { angle = -angle; }
myTransform.localRotation = Quaternion.Euler(0, 0, angle); }

Но лучше подольше почитать про вращения и как их оптимизировать и применить к себе.

Комментариев нет:

Отправить комментарий