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};
    }

}
Другие вопросы по тегам