Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 TheGalacticShaman · Dec 21, 2019 at 03:03 AM · collisionmovementraycast3dcharacter controller

How to add platform motion to player controller without parenting? - Mostly working code

Hi! I am currently playing around with character controllers in unity and I wanted to try make a 3d platformer. Everything is going well except I am struggling with the code for adding a platforms velocity to the players movement.

On another post I found this code here, which is apparently from an old unity tutorial that no longer exists:

 void GetEnvInfluence()
     {
             if (activePlatform != null )
             {
                 newPlayerGlobalPosition = activePlatform.TransformPoint(playerLocalPosition);
                 envVelocity = (newPlayerGlobalPosition - playerGlobalPosition);
 
                 if (envVelocity != Vector3.zero)
                 {
                     playerController.Move(envVelocity);
                 }
                     
                 previousPlatformVelocity = (newPlayerGlobalPosition - playerGlobalPosition) / Time.deltaTime;
 
                 newGlobalPlatformRotation = activePlatform.rotation * activeLocalPlatformRotation;
                 rotationDiff = newGlobalPlatformRotation * Quaternion.Inverse(activeGlobalPlatformRotation);
 
                 rotationDiff = Quaternion.FromToRotation(rotationDiff * transform.up, transform.up) * rotationDiff;
                 transform.rotation = rotationDiff * transform.rotation;
             }
 
             else
             {
                 previousPlatformVelocity = Vector3.zero;
             }
 
             activePlatform = null;
 
             Move();
           
             if (activePlatform != null)
             {
                 playerGlobalPosition = transform.position;
                 playerLocalPosition = activePlatform.InverseTransformPoint(transform.position);
 
                 activeGlobalPlatformRotation = transform.rotation;
                 activeLocalPlatformRotation = Quaternion.Inverse(activePlatform.rotation) * transform.rotation;
             }
     }

I have managed to get this code working within my own script, and everything is working pretty great! I only have two issues that I am stuck on.

  1. Currently this code uses the "onControllerColliderHit" function to determine the platform transform. This is fine, but I am using my own spherecast for other ground detection systems and I would like to use it in this case too. For some reason, everything works fine when using the controller collision, but using the raycast to determine the platform transform leads to the character flying off. Using the collision isnt that big of a deal, but it would be preffered if I could use my raycast too. .

  2. My other problem is when the platform changes direction, the player does not register this for at least one frame, causing the player to move a small increment in the old direction of the platform after it has already changed direction, causing these little slips each time this happens.

Is this code just outdated? Is there a better solution to this now? I would not like to use the parenting method as I think this way will be better for my game. Any help would be greatly appreciated :)

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

1 Reply

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

Answer by lgarczyn · Dec 21, 2019 at 07:31 PM

This is an unfortunately pretty complex subject.


Parenting is often the best option for a physics-based character (using a non-kinematic rigidbody). Simply set the parent on collision enter, and leave on collision exit. This breaks the "don't have rigidbodies as parents to each other" rule, but it's a pretty outdated rule.


For kinematic rigidbodies and character controllers, the best way is to modify your Platform script. Simply use your Raycast to detect if the player is on a collider, and if it is, use GetComponent to obtain the Platform script. You may want to use RaycastAll if you want to be able to be pulled by the platform if you're only partially on it.

Your Platform script should run first (use the script order tool), and always store the difference between the next position and the previous position. When you detect if your character is on the ground, try to get that difference, and add it to your movement script offset.


Do note that both the platform script and the player script need to run on FixedUpdate, otherwise just make the the platform store its last velocity in a frame-agnostic manner (divide the delta post by fixedDeltaTime).

Comment
Add comment · Show 3 · 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 TheGalacticShaman · Dec 21, 2019 at 11:03 PM 0
Share

Hey thanks for your reply! Im glad its not just me, ive tried to come up with different solutions over the last few days with nothing working perfectly hahah.

I did consider deriving the extra velocity from the platform script, but I was hoping I could figure out a way that my player script could do this independently, so that anything that is moving (platforms, enemies, objects etc) could have its velocity obtained without the need for extra code on each of the objects.

Am I just over complicating it? If i cant find another solution then I think your proposed one sounds like the best thing for now.

I think the problem with my current code is that the player gets the velocity from the previous frame, which leads to the little "nudge" when the platform changes direction.

Again, thanks for your time. I really appreciate the advice

avatar image lgarczyn TheGalacticShaman · Dec 22, 2019 at 06:54 PM 1
Share

Any non-kinematic rigidbody can have its velocity obtained, however it will only ever be the last frame's velocity. That is because the next physics update might have collisions that you couldn't predict. You can limit that with raycasts, but it's complicated.


Any kinematic rigidbody needs a script to move, and all these scripts will always inherently be able to calculate their velocity.


In general, yes, you are overcomplicating things. All objects should implement their own behaviors and provide information about themselves, ins$$anonymous$$d of being moved or analyzed by others.


The clean way to do it would be yo create a Smart$$anonymous$$inematic class inheriting from $$anonymous$$onoBehaviour, that requires a rigidbody component. That class will have a:

  1. GetVelocity function that returns its speed (currentPos - lastPos) / Time.fixedDeltaTime

  2. $$anonymous$$ovePosition function that calls rigidbody.$$anonymous$$ovePosition, but also sets lastPos

  3. GetRigidbody function that returns the rigidbody

  4. private bool has$$anonymous$$oved to check that GetVelocity is not called before $$anonymous$$ovePosition


Simply make all your platforms and kinematic objects inherit from that class to be able the get the velocity of all of them easily.

avatar image TheGalacticShaman lgarczyn · Dec 22, 2019 at 09:31 PM 1
Share

You're right, that is a good solution! thank you for pointing me in the right direction, I dont know why I thought I could get it to work from the previous frame. I appreciate the help :)

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

217 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 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 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

Continuously rotate a gameobject on 1 axis perpendicularly to another gameobject's normal? 1 Answer

Player movement ignores some collision 0 Answers

Prevent random movement allowing movement through obstacles 1 Answer

Issues with Bullet Ricochet 1 Answer

Raycast for 2d with touch. 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