Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by andylatham · Feb 27, 2015 at 11:16 AM · collisionraycastingplatformer

2D platformer player intersecting floors and walls

Hi, I'm a bit of a newbie to Unity (and to making games), but I'm trying to build a retro-style 2D platform game along the lines of Super Mario Bros. I'm using 2D raycasting rather than physics to achieve that classic feel, but I'm having a problem where my player character is intersecting the floors and walls that I've set up. They stop his movement, but he sits a little inside them.

I'm using 16-bit-style pixel graphics, so I'm trying to keep the positions of all assets integers rather than floats.

I'm not sure what I'm doing wrong so I'm including my whole character controller code. I'd really appreciate any help from anyone.

Thanks very much!

 using UnityEngine;
 using System.Collections;
 
 public class PlayerController : MonoBehaviour {
 
     public int positionX, positionY;
     public int speed;
     public LayerMask playerLayerMask;
 
     private float moveHorizontal, moveVertical;
     private Animator animator;
     private RaycastHit2D hitFront1, hitRear1, hitBottom1, hitTop1;
     private int distXToMove, distYToMove;
     private bool jump;
     private int jumpCount;
     private bool jumping;
     private int fallAccel;
     private int fallAccelMax;
 
     void Start()
     {
         animator = this.GetComponent<Animator> ();
         jumping = false;
         fallAccelMax = 10;
         fallAccel = 0;
         jumpCount = 15;
     }
 
 
     void Update ()
     {
         GetPosition ();            // Get player position.
 
         GetPlayerInput ();        // Get input from the player.
 
         PerformPhysics ();
 
         AnimateSprite ();        // Choose correct animation.
 
         CollisionDetection ();    // Detect collisions with objects.
 
         TranslatePlayer ();        // Move the player.
     }
 
 
     void GetPosition()
     {
         positionX = (int)transform.position.x;    // Store initial position.
         positionY = (int)transform.position.y;    //
     }
 
 
     void GetPlayerInput ()
     {
         moveHorizontal = (int)Input.GetAxis ("Horizontal");    // Get direction.
 
         distXToMove = (int)(moveHorizontal * speed);
 
         if (!jumping)
         {
             jump = Input.GetKeyDown ("joystick button 1");
             if (jump)
                 jumping = true;
         }
     }
 
 
     void PerformPhysics()
     {
         if (!hitBottom1 && fallAccel < fallAccelMax && !jumping)
             fallAccel++;
         else if (hitBottom1)
             fallAccel = 0;
 
         distYToMove = (int)(-fallAccel);
 
         if (jumping)
         {
             if (jumpCount > 0)
             {
                 distYToMove = jumpCount;
                 jumpCount--;
             }
             else
             {
                 jumpCount = 15;
                 jumping = false;
             }
         }
     }
 
 
     void AnimateSprite()
     {
         if (moveHorizontal != 0)
         {
             // Play run animation if moving horizontally.
             animator.SetInteger ("PixelMeState", 1);
 
             // Reflect player in X if moving left.
             if (moveHorizontal < 0)
                 transform.localScale = new Vector2(-1, 1);
             else if (moveHorizontal > 0)    
                 transform.localScale = new Vector2(1, 1);
         }
         // Play idle animation by default.
         else
             animator.SetInteger ("PixelMeState", 0);
     }
     
 
     void CollisionDetection()
     {
     // Check for collision from RHS of character.
     hitFront1 = Physics2D.Raycast(transform.position + new Vector3 (5, 12, 0), 
                 new Vector3 (distXToMove, 0, 0), distXToMove, playerLayerMask);
     // Draw line to show ray from RHS of character.
     Debug.DrawRay (transform.position + new Vector3 (5, 12, 0), 
                    new Vector3 (distXToMove, 0, 0), Color.green);
 
     // Check for collision from LHS of character.
     hitRear1 = Physics2D.Raycast(transform.position + new Vector3 (-6, 12, 0), 
                    new Vector3 (distXToMove, 0, 0), distXToMove, playerLayerMask);
     // Draw line to show ray from LHS of character.
     Debug.DrawRay (transform.position + new Vector3 (-6, 12, 0), 
                    new Vector3 (distXToMove, 0, 0), Color.red);
 
     // Check for collision from bottom of character.
     hitBottom1 = Physics2D.Raycast(transform.position, new Vector3 (0, distYToMove, 0), 
                  distYToMove, playerLayerMask);
     // Draw line to show ray from bottom of character.
     Debug.DrawRay (transform.position, new Vector3 (0, distYToMove, 0), Color.grey);
 
     // Check for collision from top of character.
     hitTop1 = Physics2D.Raycast(transform.position + new Vector3 (0, 24, 0),
               new Vector3 (0, distYToMove, 0), distYToMove, playerLayerMask);
     // Draw line to show ray from top of character.
     Debug.DrawRay (transform.position + new Vector3 (0, 24, 0), 
                    new Vector3 (0, distYToMove, 0), Color.cyan);
     }
 
 
     void TranslatePlayer()
     {
         // If wall will be reached this frame, and the player isn't already there,
         // move the remaining distance to the wall.
         if (hitFront1 && hitFront1.collider.tag == "Wall" && distXToMove > 0)
             distXToMove = (int)hitFront1.distance;
 
         // If wall will be reached this frame, and the player isn't already there,
         // move the remaining distance to the wall.
         if (hitRear1 && hitRear1.collider.tag == "Wall" && distXToMove < 0)
             distXToMove = (int)hitRear1.distance;
 
         // If platform will be reached this frame, and the player isn't already there,
         // move the remaining distance to the platform.
         if (hitBottom1 && hitBottom1.collider.tag == "Platform" && distYToMove < 0)
             distYToMove = (int)hitBottom1.distance;    
 
         // If platform will be reached this frame, and the player isn't already there,
         // move the remaining distance to the platform.
         if (hitTop1 && hitTop1.collider.tag == "Ceiling" && distYToMove > 0)
             distYToMove = (int)hitTop1.distance;
 
 
         positionX += distXToMove;        // Increment position
         positionY += distYToMove;        //
 
         // Set new player position.
         transform.position = new Vector2 (positionX, positionY);
     }
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by andylatham · Feb 28, 2015 at 10:57 PM

I managed to solve the problem. Well it was actually a number of problems. Firstly I had set up all the graphic elements to have pivots at their bases rather than their centres. However the ray casting was occurring relative to the centre of the player character. So first I changed all the pivots to the object centres and tweaked the ray casting.

This didn't solve my problem though. However after a lot of hair-tearing, I realised that there were a couple of minus signs in the wrong places in my collision detection code. Fixing these solved my problem and now the character detects collisions with pixel-perfect accuracy.

Thanks for the help! :)

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by alok-kr-029 · Feb 27, 2015 at 11:20 AM

Have you adjusted the colliders properly

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image andylatham · Feb 27, 2015 at 01:21 PM 0
Share

All the platforms and walls have 2D box colliders applied to them. They're just simple rectangles and the colliders are exactly the same size. The player's box collider is slightly smaller than the sprite, but the bottom edge of the collider is precisely where the bottom of the sprite is, so it should stand perfectly on the floor.

avatar image
0

Answer by hexagonius · Feb 28, 2015 at 10:53 AM

Collider and visual differences

I made a simple setup, from left to right:

  1. 2 cubes, 1x1x1, boxcollider, upper one plus rigidbody

  2. 1 cube, 1x2x1

  3. 2 quads, renderer without material, boxcollider2d, upper one plus rigidbody2d

As one can immediately see that 3D physics and 2D physics are completely different on how they are handled. The cubes overlap, the quads even have gaps. You can also see, that all three setups have different heights in total, adding up of course when there's more colliders.

The 2D colliders use some kind of skin width as the charactercontroller does, but its width is neither accessible nor documented.

On a jam I found increasing the size of a sprite via scale by 0.03 was quite good, but in total I think you're pretty much out of luck with Unity and pixel precision while using pyhsics.


box.png (11.0 kB)
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Issues with 2d Player controller(Kinematic) 0 Answers

Problems defining when OnCollisionEnter should start functioning. 1 Answer

Physics-free collision problems 0 Answers

How to move player after hitting object 0 Answers

Raycast object as far as possible? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges