Unity 2D: как столкнуться со стороной экрана
Сейчас я работаю над 2D-игрой для Android. На моей сцене есть игрок, и если пользователь наклоняет свое устройство, объект игрока движется по земле. Но он просто выходит за пределы экрана слева и справа. Я пытался сделать "стену", но безуспешно. У моего игрока-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;
}
Этот код работает для меня!:)
4 ответа
Вы можете разместить на своей сцене, за пределами региона, который будет отображаться на вашем устройстве, 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 ;
}
Это создаст краевые коллайдеры вокруг экрана (для 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;
}
В прототипе я создаю решение, которое я получил, создавая "стены" с объектами без спрайтов в границах и проверяя, есть ли что-то с 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)
Прикрепите этот скрипт к основному объекту холста.
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};
}
}