Страницы

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

четверг, 2 января 2020 г.

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

#c_sharp #unity3d #случайные_числа


Есть текстура, бегает в неком радиуса, стукаясь об стенки - получает новое направление. 

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



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); } Но лучше подольше почитать про вращения и как их оптимизировать и применить к себе.

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

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