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 Shubius · Feb 17, 2013 at 09:50 PM · collisionraycastcharactercontrollerraycastingcollisiondetection

Help Understanding Raycast

I am attempting to develop a replacement character controller to use with 2D games in Unity. The default character controller is a capsule and therefore the rounded edges make for annoying behavior near ledges and the mandatory z depth dependent on the size of the capsule does not play well with 2D games in a 3D environment. This one will be a box collider which will allow modifiable character z depths.

I am not using physics (via rigidbodies) in order to have complete control over collision detection. I am attempting to raycast from the edges of the box collider and limiting the ray casting to the direction the player is attempting to move (for performance). For instance if the player was moving right I am casting a ray from the right middle, top-right corner, and bottom-right corners to the right (the direction) at a distance of what the next movement would be. I am simply changing the position of the player's transform if no collision is detected. If a collision is detected I am returning CollisionFlags indicating where the collision took place and not moving the character to the newly desired position.

Currently all the code seems to be working well except the rays always return false. I have verified the following conditions:

  1. My colliders are on the same z plane.

  2. Drawing the ray indeed shows that it is moving in the correct direction and distance.

  3. I have stopped using layers for now to ensure that incorrect use of LayerMask is not the issue.

  4. I have made the colliders on my character and the test ground piece "fat" (changed them from 2D toolkit's default 0.2 to 20 for z-scale.

  5. The player is starting well above the ground piece and is falling into and past the ground piece very slowly.

  6. My code for movement works fine as I can move left and right and the correct Log statements (as seen in my code) display just as they should.

  7. Currently I am not moving the character but I am letting gravity (my gravity) be applied in order to narrow the problem to only one of the conditional statements in my collision detection code.

    void checkMovement() {

       horizontal = Input.GetAxis ("Horizontal");
          vertical = Input.GetAxis ("Vertical");
     
          //...other code here but I can assure you this is being called as it should
          else if (!isJumping && !grounded) //apply gravity
               movement.y = -gravitySpeed;
     
          movement.z = 0.0f;  //never move into the z axis
          //my code is attempting to mimic the next statement
          //lastCollision = playerCharController.Move(movement * Time.deltaTime);
          lastCollision = playerMove(movement * Time.deltaTime);
     }
     
     //Cache all variables for playerMove()
    
     public int collisionLayerToIgnore = 0; 
    
     private float distance = 0.0f; 
    
     private Vector3 colliderTop = new Vector3(0.0f, 0.0f, 0.0f);
    
     private Vector3 colliderBottom = new Vector3(0.0f, 0.0f, 0.0f);
    
     private Vector3 colliderLeft = new Vector3(0.0f, 0.0f, 0.0f);
    
     private Vector3 colliderRight = new Vector3(0.0f, 0.0f, 0.0f);
    
     private Vector3 right = new Vector3(1.0f, 0.0f, 0.0f);
    
     private Vector3 left = new Vector3(-1.0f, 0.0f, 0.0f);
    
     private Vector3 up = new Vector3(0.0f, 1.0f, 0.0f);
    
     private Vector3 down = new Vector3(0.0f, -1.0f, 0.0f);
    
     private CollisionFlags playerMove(Vector3 toThisPoint)
     {
          CollisionFlags flags = 0;
     
          //Not using layer masks right now
          //collisionLayerToIgnore = 1 << LayerMask.NameToLayer("LevelGeometry");
     
          //Get the x and y values in world space for the edges of the box collider for convenience
          colliderTop.x = playerCollider.bounds.center.x;
          colliderTop.y = playerCollider.bounds.center.y + playerCollider.bounds.extents.y;
          colliderTop.z = playerCollider.bounds.center.z;
          colliderBottom.x = playerCollider.bounds.center.x;
          colliderBottom.y = playerCollider.bounds.center.y - playerCollider.bounds.extents.y;
          colliderBottom.z = playerCollider.bounds.center.z;
          colliderLeft.x = playerCollider.bounds.center.x - playerCollider.bounds.extents.x;
          colliderLeft.y = playerCollider.bounds.center.y;
          colliderLeft.z = playerCollider.bounds.center.z;
          colliderRight.x = playerCollider.bounds.center.x + playerCollider.bounds.extents.x;
          colliderRight.y = playerCollider.bounds.center.y;
          colliderRight.z = playerCollider.bounds.center.z;
     
          //Cast rays from the edge middle and corners at a distance
          //equal to the x value of the given point ignoring all colliders not in collisionLayer.
          //Adding the vectors representing the centers of two sides results in a vector that
          //represents the corner between those two sides.
         
          //Check diagonal movement
          if (toThisPoint.x > 0 && toThisPoint.y > 0)
          {
            //...some code
          }
     
          else if (toThisPoint.x > 0 && toThisPoint.y < 0)
          {
            //...some code
          }
     
          else if (toThisPoint.x < 0 && toThisPoint.y > 0)
          {
            //...some code
          }
     
          else if (toThisPoint.x < 0 && toThisPoint.y < 0)
          {
            //...some code
          }
     
          //Check strict horizontal movement
          else if (toThisPoint.x > 0)
          {
            //..some code
          }
     
          else if (toThisPoint.x < 0)
          {
            //..some code
          }
     
          //Check strict vertical movement
          //Here is where the magic "isn't" happening
          else if (toThisPoint.y > 0)
          {
               Debug.Log("toThisPoint.y < 0");
               distance = -1 * toThisPoint.y;
           //distance = Mathf.Infinity;
     
               Debug.DrawRay(colliderBottom, new Vector3(0.0f, distance, 0.0f), Color.red, 100.0f);
               //...as you can see I have ignored layermask for now
           if (Physics.Raycast(colliderBottom, down, distance)//, collisionLayerToIgnore)
               ||Physics.Raycast(colliderBottom + colliderRight, down, distance)//, collisionLayerToIgnore)
               ||Physics.Raycast(colliderBottom + colliderLeft, down, distance))//, collisionLayerToIgnore))
              flags = flags & CollisionFlags.Below;
          }
     
          //.. up vertical direction code
     
          //If no collision will happen then move the player to the new location
          if (flags == 0)
          {
               playerTransform.position = playerTransform.position + toThisPoint;
               Debug.Log("Collision Flags: None");
          }
     
          if ((flags & CollisionFlags.Sides) == CollisionFlags.Sides)
               Debug.Log("Collision Flags: Sides");
     
          else if ((flags & CollisionFlags.Above) == CollisionFlags.Above)
               Debug.Log("Collision Flags: Above");
     
          else if ((flags & CollisionFlags.Below) == CollisionFlags.Below)
               Debug.Log("Collision Flags: Below");
     
          return flags;
     }
    
    
    

Like I said, currently flags always gets set to none but when I don't press left or right control reaches the "toThisPoint.y < 0" Log statement and draws the ray correctly.

I have tried calling the methods from within Update()/FixedUpdate() with the same results. I also tried using a toggle to only used every other Update()/FixedUpdate().

Am I not grasping the function of Physics.Raycasting correctly. I have spend a full night with no sleep researching everything I could find on using the different Physics.Raycast methods and have scoured the forums for answers. If they are out there and I missed them please direct me appropriately.

Any ideas will be much appreciated.

Comment
Add comment · Show 1
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 Starkid225 · Feb 17, 2013 at 09:56 PM 0
Share

I would advise looking at the Physics.Raycast in the Unity Scripting Documentation for more information.

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by Owen-Reynolds · Feb 17, 2013 at 10:43 PM

"Fat" colliders? There's a special rule that rays don't hit anything they start inside of. So maybe the ground is too fat?

Sometimes easier to start with something working. Maybe set up a fresh scene with one object using a very simple script to raycast towards another:

public string hitWho;

 RaycastHit H;
 if(Physics.Raycast(transform.position, transform.forward, out H, 20) {
   hitWho=H.transform.name;
 }

else hitWho="";

Running in scene view, turn it and move it around. Add the bottom/sides math for start pos and see if that works... . Eventually you will add one more thing that breaks it, and know exactly what the problem was.

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 Shubius · Feb 20, 2013 at 07:34 PM

So for anyone who has issues with getting raycasting to work like I did the solution MAY be simple. Unfortunately all raycasting is disabled be default in the editor between layers (including custom layers!!!). I could not find this in the documentation and only accidently noticed it while changing the gravity for my scene. Just "UNCHECK" the box in the "Ignore Raycast" row representing the layer you would like to allow raycasting to work between and you will be fine.alt text


physicsfix.png (22.9 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

11 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Obstacle avoidance 1 Answer

[Solved] Character Controller Explosion Detection 1 Answer

Raycast object as far as possible? 1 Answer

What's a reliable way to detect if an object is no longer being hit by a ray? 1 Answer

Pixel Perfection collision on 3d animated object 0 Answers


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