Сейчас я работаю над 2D-игрой для Android. В моей сцене есть игрок, и если пользователь наклоняет свое устройство, объект игрока движется по земле. Но он просто выходит за пределы экрана слева и справа. Я пытался сделать «стену», но безуспешно. У моего player-Gameobject есть краевой коллайдер. Теперь мой вопрос: как мой игровой объект игрока может столкнуться с боковой стороной экрана?
Это мой код:
public GameObject player;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
Vector3 dir = Vector3.zero;
dir.y = Input.acceleration.x;
player.transform.Translate(new Vector2(dir.y, 0) * Time.deltaTime * 2000f);
}
Большое спасибо! :)
Июл
Обновлено:
Изображение 1 - моя стена, а изображение 2 - мое игрока.
Пытаюсь решить стеной сбоку от экрана. Это изображения
Код решения:
Vector3 position = player.transform.position;
translation = Input.acceleration.x * movementSpeed * 50f;
if (player.transform.position.x + translation < LeftlimitScreen)
{
position.x = -LeftlimitScreen;
}
else if (transform.position.x + translation > RightlimitScreen)
{
position.x = RightlimitScreen;
}
else
{
position.x += translation;
player.transform.position = position;
}
Этот код у меня работает! :)
Vector3 dir = Vector3.zero; dir.y = Input.acceleration.x; player.transform.Translate (новый Vector2 (dir.y, 0) * Time.deltaTime * 2000f);
Извините за плохое форматирование. Я новичок в stackoverflow. :)
Это код в моей функции обновления.
Вы можете разместить в своей сцене за пределами области, которая будет отображаться на вашем устройстве, 2 пустых игровых объекта с коллайдером, чтобы игрок столкнулся с ними.
Вы также можете ограничить с помощью кода границы, которые игрок может перемещать. Вы применяете это с помощью Mathf.Clamp (), и там вам нужно будет установить границы в координате x для вашей сцены.
Вы увидите, что вместо изменения положения игрока с помощью его преобразования мы используем вместо этого твердое тело.
public class PlayerController : MonoBehaviour
{
public float speed;
public float tilt;
public Boundary boundary;
void FixedUpdate ()
{
float moveHorizontal = Input.GetAxis ("Horizontal");
float moveVertical = Input.GetAxis ("Vertical");
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
rigidbody.velocity = movement * speed;
rigidbody.position = new Vector3
(
Mathf.Clamp (rigidbody.position.x, boundary.xMin, boundary.xMax),
0.0f,
5.0f
);
}
}
Вы можете просмотреть весь учебник здесь: https://unity3d.com/earn/tutorials/projects/space-shooter/moving-the-player?playlist=17147
Обновлять Другие варианты:
//You select here the speed you consider
float speed = 1.0f;
void Update () {
Vector3 dir = Vector3.zero;
float InputValue = Input.acceleration.x * speed;
//You need to set the values for this limits (max and min) based on your scene
dir.y = Mathf.Clamp(InputValue, 0.5f, 50.5f);
player.transform.position = dir;
}
Обновление 2:
Без зажима, просто устанавливая ограничения на скрипт
void Update () {
Vector3 position = player.transform.position ;
translation = Input.acceleration.x * speed;
if ( player.transform.position.y + translation < leftLimitScreen )
position.y = -leftLimitScreen ;
else if ( myTransform.position.x + translation > rightLimitScreen )
position.y = rightLimitScreen ;
else
position.y += translation ;
player.transform.position = position ;
}
Спасибо за Ваш ответ! Я добавил код к своему ответу.
@Jul Попробуйте мой обновленный ответ сейчас.
@Jul Кстати, вы должны проверить единицы на своем экране, я использую магическое число 0 и 50 для левого и правого предела, но вам может потребоваться добавить туда что-то еще
Этот код работает. Но если я проведу со своим плеером в сторону экрана, мой игрок застрянет, и я больше не смогу его двигать. Как я могу исправить эту проблему?
@Jul Я обновил свой ответ. Я также добавлю учебник, который может быть вам интересен
Я пробовал этот код, но безуспешно. Поскольку у меня есть 2D-игра, я добавил Rigidbody2D в свой Player-GameObject. Но я не совсем понял ваш код наверху. И это не сработало, потому что к нему не прикреплено (нормальное) Rigidbody. Я попытался решить эту проблему со стеной сбоку, но твердое тело моего игрока не сталкивается. Что я могу сделать сейчас? :)
@Jul вы также добавили к стенам твердое тело и коллайдеры?
Я обновил свой вопрос. «Пожалуйста, взгляните на изображения», - добавил я.
@Jul и все еще не обнаружен? так что именно происходит? Игрок игнорирует стены и продолжает двигаться дальше?
Игрок просто движется сквозь стену и вроде ничего не происходит.
Нужно ли мне изменить какие-то настройки в моем rigdbody2D или Box / Edge Collider2D?
@Jul Хорошо, это может быть способ перемещения игрока, который игнорирует коллайдеры. Попробуйте изменить Update () для сценария, который я только что добавил в свой ответ.
Спасибо за попытку мне помочь. Я попытался реализовать этот код в своей игре. Но это не сработало. Игрок все еще висел в моей «нулевой» точке, и я не мог его сдвинуть. Этот код в порядке? :) И кстати: извините за поздний ответ.
@Jul Это код, который я использовал некоторое время назад, но вводом было положение мыши, а не ускорение телефона
@Jul Я добавил новый комментарий с новой опцией. Вам необходимо проверить и изменить левый и правый предел, а также скорость. Я не могу установить это для вас, так как это зависит от того, чего вы пытаетесь достичь. Также вам необходимо убедиться, что вы используете ось «y». В своем первоначальном вопросе вы используете его, не зная, правильно ли он или это ось «x». Но на всякий случай оставил букву «у».
Спасибо за Ваш ответ. Завтра попробую. :)
Спасибо за Ваш ответ. Похоже, работает. Отличная работа! Большое спасибо! :)
В прототипе я создаю решение, к которому пришел, создавая «стены» с объектами без спрайтов в границах и проверяя, есть ли там что-то с Raycast с помощью такого скрипта:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour {
RaycastHit2D[] hit;
Vector2[] directions;
private Vector2 targetPosition;
private float moveSpeed;
private float moveHDir;
private float wallPos;
private bool hitLeft;
private bool hitRight;
// Use this for initialization
void Start () {
directions = new Vector2[2] {Vector2.right, Vector2.left};
hitLeft = false;
hitRight = false;
}
// Update is called once per physics timestamp
void FixedUpdate () {
foreach (Vector2 dir in directions) {
hit = Physics2D.RaycastAll(transform.position, dir);
Debug.DrawRay(transform.position, dir);
if (hit[1].collider != null) {
// Keyboard control
if (Input.GetAxisRaw("Horizontal") != 0) {
moveHDir = Input.GetAxisRaw("Horizontal");
// I have found that a 5% of the size of the object it's a
// good number to set as a minimal distance from the obj to the borders
if (hit[1].distance <= (transform.localScale.x * 0.55f)) {
if (dir == Vector2.left) {
hitLeft = true;
} else {
hitRight = true;
}
wallPos = hit[1].collider.transform.position.x;
// Condition that guarantee that the paddle do not pass the borders of the screen
// but keeps responding if you try to go to the other side
if ((wallPos > this.transform.position.x && moveHDir < 0) ||
(wallPos < this.transform.position.x && moveHDir > 0)) {
moveSpeed = gControl.initPlayerSpeed;
} else {
moveSpeed = 0;
}
} else {
if (dir == Vector2.left) {
hitLeft = false;
} else {
hitRight = false;
}
if (!hitRight && !hitLeft)
{
moveSpeed = gControl.initPlayerSpeed;
}
}
}
}
}
targetPosition = new Vector2((transform.position.x + (moveSpeed * moveHDir)), transform.position.y);
}
}
Может быть, это не лучшее решение или не самое короткое, но оно творит чудеса для меня.
Удачи.
Спасибо за Ваш ответ. Выглядит слишком большим для меня. Но в любом случае спасибо за ответ :) Если другого решения нет, я постараюсь ввести его в ваш код.
Это создаст краевые коллайдеры вокруг экрана (для 2d):
void GenerateCollidersAcrossScreen()
{
Vector2 lDCorner = camera.ViewportToWorldPoint(new Vector3(0, 0f, camera.nearClipPlane));
Vector2 rUCorner = camera.ViewportToWorldPoint(new Vector3(1f, 1f, camera.nearClipPlane));
Vector2[] colliderpoints;
EdgeCollider2D upperEdge = new GameObject("upperEdge").AddComponent<EdgeCollider2D>();
colliderpoints = upperEdge.points;
colliderpoints[0] = new Vector2(lDCorner.x, rUCorner.y);
colliderpoints[1] = new Vector2(rUCorner.x, rUCorner.y);
upperEdge.points = colliderpoints;
EdgeCollider2D lowerEdge = new GameObject("lowerEdge").AddComponent<EdgeCollider2D>();
colliderpoints = lowerEdge.points;
colliderpoints[0] = new Vector2(lDCorner.x, lDCorner.y);
colliderpoints[1] = new Vector2(rUCorner.x, lDCorner.y);
lowerEdge.points = colliderpoints;
EdgeCollider2D leftEdge = new GameObject("leftEdge").AddComponent<EdgeCollider2D>();
colliderpoints = leftEdge.points;
colliderpoints[0] = new Vector2(lDCorner.x, lDCorner.y);
colliderpoints[1] = new Vector2(lDCorner.x, rUCorner.y);
leftEdge.points = colliderpoints;
EdgeCollider2D rightEdge = new GameObject("rightEdge").AddComponent<EdgeCollider2D>();
colliderpoints = rightEdge.points;
colliderpoints[0] = new Vector2(rUCorner.x, rUCorner.y);
colliderpoints[1] = new Vector2(rUCorner.x, lDCorner.y);
rightEdge.points = colliderpoints;
}
Работает как шарм. Благодаря тонну!
Если камера движется (и эта функция должна запускаться в FixedUpdate), я полагаю, это будет загружать процессор?
Да, это может быть полезно, когда ваша камера неподвижна. Вы можете попробовать заставить коллайдеры следовать за камерой, и это может дать вам тот же эффект.
В случае, если вы хотите сгенерировать коллайдер на границах холста (2D)
Прикрепите этот скрипт к основному объекту холста.
using UnityEngine;
public class BorderCollider: MonoBehaviour
{
private EdgeCollider2D _edgeCollider2D;
private Rigidbody2D _rigidbody2D;
private Canvas _canvas;
private float y, x;
private Vector2 _topLeft, _topRight, _bottomLeft, _bottomRight;
private void Start() {
//Adding Edge Collider
_edgeCollider2D = gameObject.AddComponent<EdgeCollider2D>();
//Adding Rigid body as a kinematic for collision detection
_rigidbody2D = gameObject.AddComponent<Rigidbody2D>();
_rigidbody2D.bodyType = RigidbodyType2D.Kinematic;
//Assigning canvas
_canvas = GetComponent<Canvas>();
GetCanvasDimension(); // Finds height and width fo the canvas
GetCornerCoordinate(); // Finds co-ordinate of the corners as a Vector2
DrawCollider(); // Draws Edge collide around the corners of canvas
}
public void GetCornerCoordinate() {
// Assign corners coordinate in the variables
_topLeft = new Vector2(-x,y); // Top Left Corner
_topRight = new Vector2(x,y); // Top Right Corner
_bottomLeft = new Vector2(-x,-y); // Bottom Left Corner
_bottomRight = new Vector2(x,-y); // Bottom Right Corner
}
void GetCanvasDimension(){
y = (_canvas.GetComponent<RectTransform>().rect.height) / 2;
x = (_canvas.GetComponent<RectTransform>().rect.width) / 2;
}
void DrawCollider() {
_edgeCollider2D.points = new[] {_topLeft, _topRight, _bottomRight, _bottomLeft,_topLeft};
}
}
Вы можете сделать это без коллайдеров, просто напишите код, который вы используете для перемещения вашего персонажа, и я объясню вам, как вы можете программно установить границы.