• 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 ChiefSlaya · Feb 19, 2017 at 08:48 AM · physicscharacter controller

Snowboarding character controller

I am currently trying to create a character controller that will allow the player to slide down slopes while maintaining control of their direction - in other words, a fairly simple snowboarding game. (I'm actually going to be using it for penguins sliding on their stomach but this has the same requirements). Note that ramps and cliffs should work as expected, with the player becoming airborne until they hit the ground.

I posted a thread on Twitter detailing my struggles here, but here is the best-functioning code I've managed so far:

 // First, calculate our old trajectory
 Vector3 oldTrajectory = transform.position - oldPosition;
 
 // Objects in motion tend to stay in motion, so we start with that same motion first
 Vector3 newTrajectory = oldTrajectory;
 
 // If we're grounded, we'll take that into account for sliding purposes
 if (cc.isGrounded)
 {
     // First get the slope underneath us
     RaycastHit hit;
     if (Physics.Raycast(transform.position, -oldNormal, out hit, 2f) || Physics.Raycast(transform.position, Vector3.down, out hit, 2f))
     {
         oldNormal = hit.normal;
         Vector3 downSlopeRight = Vector3.Cross(hit.normal, GRAVITY_DIRECTION);
         Vector3 downSlopeDirection = Vector3.Cross(downSlopeRight, hit.normal);

         Vector3 movementForce = downSlopeDirection *
             (gravity * Time.fixedDeltaTime * Vector3.Dot(downSlopeDirection, GRAVITY_DIRECTION)) *
             (1 + (newTrajectory.magnitude * Vector3.Dot(downSlopeDirection, newTrajectory.normalized)));
                 
         newTrajectory += movementForce * slopeImpact * Time.fixedDeltaTime;
     }
 }
 // Otherwise, normally account for gravity
 {
     newTrajectory += gravity * GRAVITY_DIRECTION * Time.fixedDeltaTime * Time.fixedDeltaTime;
 }

 oldPosition = transform.position;
 cc.Move(newTrajectory)  

Essentially: Take our current momentum, add gravity directed by the slope, and accelerate even more if the slope matches our trajectory (I can't even remember why I put that part in). This kind of works but especially when rocking back and forth in a divot, you notice that the momentum isn't really being handled properly (see here).

I attempted a second approach, where the player simply moves in the direction they're facing, and they gain speed while moving down a slope or lose it while going up. I couldn't figure out a way to get this to work at all:

 // First, take the real distance we moved, and convert it to fairy numbers (time-independant measurements)
 Vector3 newMomentum = (transform.position - oldPosition) / Time.fixedDeltaTime;
 
 // If we're grounded, we'll take that into account for sliding purposes
 if (cc.isGrounded)
 {
     // First get the slope underneath us
     RaycastHit hit;
     if (Physics.Raycast(transform.position, -oldNormal, out hit, 2f) || Physics.Raycast(transform.position, Vector3.down, out hit, 2f))
     {
         oldNormal = hit.normal;
         Vector3 downSlopeRight = Vector3.Cross(hit.normal, GRAVITY_DIRECTION);
         Vector3 downSlopeDirection = Vector3.Cross(downSlopeRight, hit.normal);
         Vector3 facingDirectionOnSlope = Vector3.Cross(transform.right, hit.normal);
 
         // All we want to do is move the player faster if they're facing down the slope, or slower if facing up
         // (will also slide them backwards eventually which is funny)
         float speed = newMomentum.magnitude;
         speed += gravity * slopeImpact * Vector3.Dot(downSlopeDirection, newMomentum.normalized);
         newMomentum = facingDirectionOnSlope * speed;
     }
 }
 else
 {
     // WE ADD GRAVITY BECAUSE THE GRAVITY DIRECTION IS DOWN
     newMomentum += gravity * Time.fixedDeltaTime * GRAVITY_DIRECTION;
 }
 
 // Update oldPosition after everything else (just in case we use it) but BEFORE CHANGING IT
 oldPosition = transform.position;
 
 cc.Move(newMomentum * Time.fixedDeltaTime);  

I tried a few different variations on this but I couldn't get it to work.

This approach is ideal, where the player can choose their direction and slopes give them speed (later I'd gently rotate them towards facing down the slope), as opposed to the other one relying on momentum and directing gravity. I just can't seem to figure out how to get it to work.

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

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.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

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

Related Questions

Gun script using Physics.Raycast not working? 2 Answers

Inconsistent jumping with character controller 1 Answer

How to keep rigidbody from falling through terrain? 2 Answers

CharacterController jumps when colliding with kinematic rigidbodies 1 Answer

Player moves slowly by itself? 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