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