3

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! :)

Community
  • 1
  • 1
Jul
  • 79
  • 1
  • 1
  • 9
  • You can do this without colliders, just write the code you are using to move your character and I will explain you how you can set the boundaries programatically – Ignacio Alorre May 21 '18 at 11:53
  • Vector3 dir = Vector3.zero; dir.y = Input.acceleration.x; player.transform.Translate(new Vector2(dir.y, 0) * Time.deltaTime * 2000f); – Jul May 21 '18 at 12:59
  • Sorry for the bad formatting. I'm new to stackoverflow. :) – Jul May 21 '18 at 13:04
  • This is the code in my Update-Function. – Jul May 21 '18 at 13:05

4 Answers4

8

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;
}
Amit Matsil
  • 91
  • 1
  • 5
3

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 ;
 }
Ignacio Alorre
  • 7,307
  • 8
  • 57
  • 94
  • Thanks for your answer! I added the code to my answer. – Jul May 21 '18 at 13:07
  • @Jul Try my udpated answer now. – Ignacio Alorre May 21 '18 at 13:11
  • @Jul By the way, you should check the units in your screen, I use the magic number 0 and 50 for the left and right limit, but you may need to add something else there – Ignacio Alorre May 21 '18 at 13:12
  • This code is working. But if I slide with my player to the side of the screen, my player he stucks and I can't move him anymore. How can I fix this issue? – Jul May 21 '18 at 14:10
  • @Jul I have updated my answer. I will add as well a tutorial which may be interesting for you – Ignacio Alorre May 21 '18 at 17:21
  • I tried this code, but I didn't get success. Because I have a 2D Game I added a Rigidbody2D to my Player-GameObject. But I didn't really understand your code upstairs. And it didn't work because there is no (normal) Rigidbody attached. So I tried to solve it with a wall at the side, but my player's rigidbody isn't colliding. What can I do now? :) – Jul May 22 '18 at 11:46
  • @Jul have you added to the walls rigidbody and colliders as well? – Ignacio Alorre May 22 '18 at 11:59
  • I have updated my question. Please have a look at the images, I added. – Jul May 22 '18 at 12:59
  • @Jul and still not detected? so what happens exactly? The player ignore the walls and continue moving beyond? – Ignacio Alorre May 22 '18 at 13:03
  • The player is just moving through the wall and it seems like nothing happen. – Jul May 22 '18 at 13:21
  • Do I have to change some settings in my rigidbody2D or Box/Edge Collider2D? – Jul May 22 '18 at 13:21
  • @Jul Ok, it may be the way you are moving the player which ignores the colliders. Try to change the Update() for what the scrip I just added in my answer. – Ignacio Alorre May 22 '18 at 13:48
  • Thanks for your try to help me. I tried to implement this code in my game. But it didn't worked. The player was still hanging at my "zero" point and I couldn't move him. Is this code alright? :) And by the way: Sorry for the late reply. – Jul May 22 '18 at 20:42
  • @Jul That is a code I used some time ago, but the input was the position of the mouse, instead of the acceleration of the phone – Ignacio Alorre May 23 '18 at 04:52
  • 1
    @Jul I added a new comment with a new option. You need to check and modify the left and right limit and also the speed. I can not set this for you since it depends on what you are trying to achieve. Also you need to ensure you are using the "y" axis. In your initial question you are using it, not sure if it is correct or if it is the "x" axis instead. But I kept with the "y" just in case. – Ignacio Alorre May 23 '18 at 05:08
  • Thanks for your answer. I will try it tomorrow. :) – Jul May 23 '18 at 21:14
  • Thanks for your answer. It looks like it's working. Good job! Thank you very much! :) – Jul May 24 '18 at 11:37
0

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.

  • Thanks for your answer. Looks a bit too big for me to use. But anyway thank you for your answer :) If there is no other solution I'll try to get introduced in your code. – Jul May 22 '18 at 12:16
0

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

}