Jul
Jul

Reputation: 79

Unity 2D: How to collide with side of screen

I'm working currently at a 2D Game for Android. There is a player in my scene and if the user tilts his device the player Object is moving on the ground. But he is just moving out of the screen at the left and the right side. I tried to make a "wall" but I had no success. At my player-Gameobject there is an edge collider. Now my question is: how can my player gameobject collide with the side of the screen?

This is my code:

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

    }

Thank you very much! :)

Jul

EDIT:

Image 1 is my Wall's and Image 2 my Player's.

I'm trying to solve it with a wall at the side of the screen. These are the images of This is the image of my players inspector. Did I add the right things?

This is the inspector of my player.


Solved

Solution code:

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

This code is working for me! :)

Upvotes: 3

Views: 13411

Answers (4)

Shubham Pandit
Shubham Pandit

Reputation: 47

In case if you want to generate collider on the borders of the canvas (2D)

Attach this script in the main canvas object.

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

}

Upvotes: 0

Amit Matsil
Amit Matsil

Reputation: 101

This will generate edge colliders around the screen (for 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;
}

Upvotes: 9

Ignacio Alorre
Ignacio Alorre

Reputation: 7605

You can place in your scene, outside of the region which will be displayed in your device 2 empty game objects with a collider, so the player will crash against them.

You can also limit by code the boundaries within the player can move. You apply this using Mathf.Clamp(), and there you will need to set the boundaries in the x coordinate for your scene.

You will see that instead of modifying the position of the player using its transform, we use the rigidbody instead.

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

    }
}

You can check the whole tutorial here: https://unity3d.com/earn/tutorials/projects/space-shooter/moving-the-player?playlist=17147

Update Other options:

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

}

Update 2:

Without Clamp, just setting the limits on the script

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

Upvotes: 4

David Franco
David Franco

Reputation: 46

In a prototype i'm creating the solution i had arrived was creating "walls" with objects without sprites in the borders and checking if there is something there with Raycast with a script like this:

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

Maybe it's not the best solution or the shortest one, but it's working wonders to me.

Good luck.

Upvotes: 0

Related Questions