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 ScorchedPsyche · Mar 28, 2014 at 04:16 PM · collisionmovementraycastdistanceray

Unreliability of Physics.Raycast.Distance for player movement?

I have a script which tries to detect for collisions with Raycasting being executed on the Update() function. However, my tests proved this to be unreliable, since the distance is different every time I run the game and test the Hit Distance of the Raycast.

What I'm trying to do is: cast a Ray to the ground, if a collision is detected and the minimum distance is reached, then stop vertical movement.

I've attached a picture of two different iterations of the same script being run with BIG differences on the results in-game. alt text

As you can see, on one iteration the Raycast distance was detected when the user was still above the plane. However, on the other one, the player's feet was already underground when the distance was detected.

I've thought of doing this on FixedUpdate(), but not only this feels like a cheap workaround but also, according to this official unity video, I should be using this script on Update(), not the other way around: http://unity3d.com/learn/tutorials/modules/beginner/scripting/update-and-fixedupdate

Now, I want a fluid gameplay and a responsive script. I don't want random things happening on my game and want it to work as I tell it to. I'll attach the scripts below and I'd appreciate any input:

PlayerPhysics.cs

 using UnityEngine;
 using System.Collections;
 
 public class PlayerPhysics : MonoBehaviour {
     public LayerMask collisionMask;
 
     public bool grounded;
     public float _movementSpeed = 5;
     public float _gravity = 4;
     private float _skin = .005f;
 
     private float deltaX;
     private float deltaY;
     private float deltaZ;
 
     private Ray ray;
     private RaycastHit hit;
     private BoxCollider bc;
 
     // Use this for initialization
     void Start () {
         bc = GetComponent<BoxCollider>();
     }
 
     public void Move (float h, float v) {
         deltaX = 0;
         deltaY = 0;
         deltaZ = 0;
 
         Vector3 rayOrigin = new Vector3();
         rayOrigin.x = transform.position.x + bc.center.x;
         rayOrigin.y = transform.position.y + bc.center.y - bc.size.y/2;
         rayOrigin.z = transform.position.z + bc.center.z;
         ray = new Ray(rayOrigin, Vector3.down);
         Debug.DrawRay(ray.origin, ray.direction);
 
         if (Physics.Raycast(ray,out hit, collisionMask)) {
             Debug.Log(hit.distance);
             if (hit.distance > _skin) {
                 deltaY -= _gravity;
             } else {
                 grounded = true;
             }
         }
 
         if (!grounded) {
         }
 
         // Moves the target
         transform.Translate(new Vector3(deltaX, deltaY, deltaZ) * Time.deltaTime, Space.World);
     }
 }

PlayerController.cs

 using UnityEngine;
 using System.Collections;
 
 [RequireComponent (typeof (PlayerPhysics))]
 
 public class PlayerController : MonoBehaviour {
     private PlayerPhysics playerPhysics;
 
     // Use this for initialization
     void Start () {
         playerPhysics = GetComponent<PlayerPhysics>();;
     }
     
     // Update is called once per frame
     void Update () {
         float h = Input.GetAxisRaw("Horizontal");
         float v = Input.GetAxisRaw("Vertical");
         
         playerPhysics.Move(h, v);
     }
 }


pic3.jpg (355.5 kB)
Comment
Add comment · Show 4
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 supernat · Mar 28, 2014 at 05:59 PM 0
Share

What exactly are you using the raycast for? Could you explain the mechanics, what you expect, and what isn't working? Is there a specific reason/limitation that you aren't using the built-in physics to handle the player standing, stepping, walking on a ground plane?

avatar image ScorchedPsyche · Mar 28, 2014 at 06:14 PM 0
Share

What I'm trying to do is: cast a Ray to the ground, if a collision is detected and the $$anonymous$$imum distance is reached, then stop vertical movement.

I'm not using the physics system because my movement will be sort of grid-based and my character won't need any physics response to the world/objects on the game. The character just needs to walk around detecting map collision.

avatar image joedartjr · Mar 28, 2014 at 06:41 PM 0
Share

The difference you are seeing is probably caused by the Update rate at which the Raycast actually calculates new variables. The Raycast only calculates new variables each-frame if set to Update; so if the character is moving at a different rate, or the framerate of the game differs you will always get a different outcome. You could try adjusting the Fixed Timestamp inside of the Time $$anonymous$$anager options, but I don't think it will make all that much of a difference in this case. This is simply not going to work the way you want it to, it's just not how game logic is calculated.

avatar image supernat · Mar 28, 2014 at 07:11 PM 0
Share

You may have better luck also by moving the code to the FixedUpdate(). Otherwise, let's say you have a really long time between Update() calls. Your player may have been just under your threshold for distance to platform in the last frame but be past it in this frame. You will need to add some more complex code to extrapolate where the player will be next frame (again, do it all in FixedUpdate). When you deter$$anonymous$$e in frame 0 that the player should pass through the object in frame 1, and then in frame 1 your raycast returns false, you know the player must have gone too far, and you'll need to adjust the player's position to match. This may cause a slight jolt, i.e. the player mesh already got drawn below the object but the next frame is now above (or on) the object.

It's not real real complicated stuff, but Unity has already done all of this with the physics engine and even offers an Extrapolate mode for rigid bodies to calculate collision. I would try to find a way to use the built-in physics. It doesn't necessitate that you have to use all of the features of the physics, but it sure is helpful with jumping and moving onto solid objects.

0 Replies

· Add your reply
  • Sort: 

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

22 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to determine multiple points along a ray? 1 Answer

help with AI avoidance script 0 Answers

Raycast based tile navigation 0 Answers

detect Ray Crossing? Intersecting? 1 Answer

Keep minimum distance while moving. 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