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 youngapprentice · Dec 14, 2013 at 01:07 AM · movementcurvenormalslope

Move Object Along Ground Using Raycast

Hi, all!

I have a character in a sidescroller/platformer. So the Z axis is not a problem here. When I press A or D, the character moves horizontally. This is great, until I come upon a ramp or a curve. He just walks into it and stops.

I want to be able to move my character along the slope of the point immediately in front of him without just setting his transform.up to the hit.normal. This would not look very realistic in most cases.

So I decided I would draw a ray immediately in front of him, get the normal of the current face, and take the negative reciprocal of the slope of the normal in order to get the slope of the line tangent to the face.

Then I take a deltaX value and set the Y equivalent to the deltaX*m + transform.position.y

This does not work at all.

After doing some debugging, I decided to draw a Debug.Rays of the normal and of the calculated tangent. The normal is yellow and comes from the player's feet and the tangent is red, stretching from the player's feet (As an Origin) to the point along the line one unit away. On a flat surface, it works great. However, on a curved surface it doesn't work. What's up? I will offer some sample code and a few pictures.

Thanks! - YA

This is when he is on a flat surface. The red is the calculated tangent, the normal is yellow, and the ray test is cyan (It is a bit in front of the player so I know what is coming up before the player is over it)

alt text

This is when the player steps onto a gently-sloping ramp

alt text

Totally off...

Here is the code running the Debug and the rays.

     ray = new Ray( new Vector2( p.x + c.x + s.x * Mathf.Sign(deltaX), p.y + c.y + s.y/(3)), new Vector2( 0, -1 ) );
     Debug.DrawRay( ray.origin, ray.direction, Color.cyan );
     if( Physics.Raycast( ray, hit, s.y, collisionMask )) {
             var    slopeVec : Vector3 = hit.normal;
             var normSlope : float = ( slopeVec.y - transform.position.y) / (slopeVec.x - transform.position.x );
             slope = Mathf.Pow( (slopeVec.y/slopeVec.x), -1 )*-1; //Tangent line is negative reciprocal of normal
 //            Debug.Log( slope  + "˚");
             Debug.DrawRay( transform.position, hit.normal, Color.yellow, 0.0, false);
             Debug.DrawLine( Vector3( transform.position.x,  transform.position.y, 0 ), Vector3( transform.position.x+1, (transform.position.x+1)*slope + transform.position.y, 0 ), Color.red, 0.0, false );
             if( Mathf.Abs( slope ) > (0.05) ) onRamp = true;
             else onRamp = false;
     }


Comment
Add comment · Show 2
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 robertbu · Dec 14, 2013 at 01:20 AM 0
Share

Apart from your specific issues, I'm having trouble visualizing what you are trying to accomplish. You say:

without just setting his transform.up to the hit.normal. This would not look very realistic in most cases.

So how do you want the character to behave? Do you want him to orient to the normal over time rather than in a single frame? Or are you looking for some other orientation with respect to the surface?

avatar image youngapprentice · Dec 14, 2013 at 04:30 AM 0
Share

I understand your confusion. I do not want to change the players orientation. I just want to change his movement direction to the tangent of the surface he is standing on.

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by robertbu · Dec 14, 2013 at 04:47 AM

If all you need is a movement vector, then all you need to do is calculate a vector from your current position to the position of the raycast. How you calculate that will depend on the pivot point of the character. If the pivot point is at the feet of the character (which has been recommend in a couple of writeup I've read on game development), then the movement vector will be:

 var moveDirection = (hit.point - transform.position).normalized;

If your pivot is further up, say 0.5 units up, from the feet then the calculation is a bit more complicated:

 var moveDirection = ((hit.point + hit.normal * 0.5) - transform.position;

As an alternate, you can raycast directly down from the character and use the cross product to find the direction.

 var moveDirection = Vector3.Cross(hit.normal, transform.right);

I may have the parameters backwards in the Vector3.Cross().

Comment
Add comment · Show 4 · 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 youngapprentice · Dec 15, 2013 at 02:53 AM 0
Share

I was able to achieve a suitable result with both. Thanks! Now that I have the moveDirection as a vector 3, do I just translate the character by moveDir?

avatar image youngapprentice · Dec 15, 2013 at 03:00 AM 0
Share

This is what is going on now for calculation and moving the character ($$anonymous$$oving is bottom portion). I can go up and down ramps with a thin slope, but ramps that are even mildly steep will cause the player to fall through the floor and do other whacky things. (deltaPlatPos.x is just for left/right moving platforms)

             var moveDir = Vector3.Cross(transform.right, hit.normal);
             Debug.DrawRay( transform.position, moveDir, Color.red, 0.0, false );
             Debug.DrawRay( transform.position, hit.normal, Color.yellow, 0.0, false);
             deltaRampPos = (deltaX+padding)*moveDir.y;
     }
         
     var finalTransform : Vector2 = new Vector2( deltaX + deltaPlatPos.x, deltaY + deltaRampPos );
      transform.Translate( finalTransform, Space.World );
avatar image youngapprentice · Dec 15, 2013 at 04:19 PM 0
Share

Should I post a video? And honestly, the ultimate goal is to just get him to successfully move along ramps and curved surfaces, so if you have another suggestion I will take it!

avatar image robertbu · Dec 15, 2013 at 05:22 PM 0
Share

Anytime you move a character by directly changing the transform (even a short distance using Time.deltaTime), you teleport that character. And if that teleport happens to go through the mesh and you are using that mesh for your ground, you fall through. If you are using a Rigidbody, you might have better luck with Rigidbody.$$anonymous$$ovePosition(). Or if you are using a character controller, using Simple$$anonymous$$ove() or $$anonymous$$ove() will help.

But the typical way I've seen this problem handled is that the character is moved forward to the new position, then a raycast is made in some downward direction for some height above the character, then the position of the character is adjusted based on the raycast so that the character is guaranteed to sits on the mesh. From what I've seen here, you can use Vector3.down for your raycast. Sometimes the '-transform.up' of the character is a better solution. And occasionally raycasting to an interior point is best (say for a planet).

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

16 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

Related Questions

iTween for Dynamically Moving Objects around a Sphere 0 Answers

2D Game, Character Slides off Slopes, Need to be Able to Walk on Them 1 Answer

Itween for curved orbital movement? 1 Answer

Terrain Slope Bouncing 1 Answer

How can I define two-dimensional curves? (like: circle) 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