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 iPedro · Oct 09, 2011 at 10:28 PM · platformerpushmoving-platform

Horizontal platform passes through CharacterController

Using the code from the Unity 2D Platform tutorial I am able to get a vertically moving platform working no problem but when I change the platform to move horizontally the following issue is encountered:

  1. When standing still the platform passes through the CharacterController

  2. The character controller is not 'pushed' forwards or backwards by the platform

This exact same problem happens in the tutorial example itself if you move the platforms to go in a Horizontal pattern instead of the vertical 'elevator' pattern.

The desired behavior is that the CharacerController be pushed by the horizontal platform in either direction.

FACTS:

  1. Unity 3.4

  2. The platform isKinematic = true

  3. The platform has a rigidBody

  4. The platform has a box collider

CODE: The player controls (attached to PlayerObject)

 using UnityEngine;
 using System.Collections;
 
 public class CPlayerControls : MonoBehaviour 
 {
     //Public
     public float mSpeed = 3.0f;
     public float mJumpSpeed = 8.0f;
     public float mGravity = 20.0f;
     
     //Private
     private Vector3 mMoveDirection = Vector3.zero;
     private CharacterController mController;
     
     
     ////////////BEGIN Moving platform support
     private Transform activePlatform;
     private Vector3 activeLocalPlatformPoint;
     private Vector3 activeGlobalPlatformPoint;
     private Vector3 lastPlatformVelocity;
     /////////END Moving platform support
     
     // Use this for initialization
     void Start () 
     {
         this.mController = this.GetComponent<CharacterController>();
     }
     
     // Update is called once per frame
     void Update () 
     {
         // Character is on the ground
         if(this.mController.isGrounded)
         {
             this.mMoveDirection = new Vector3(Input.GetAxis("Horizontal"), 0.0f, 0.0f);
             this.mMoveDirection = this.transform.TransformDirection(this.mMoveDirection);
             this.mMoveDirection *= this.mSpeed;
             
             // Player Jump
             if(Input.GetButton("Jump"))
             {
                 this.mMoveDirection.y = this.mJumpSpeed;
             }
             
             //Player Super Jump
             if(Input.GetButtonDown("Jump") && Input.GetButton("Fire1"))
             {
                 this.mMoveDirection.y = this.mJumpSpeed + 5.0f;
             }
                 
         }
         
         // Character is NOT on the ground
         if(!this.mController.isGrounded)
         {
             this.mMoveDirection.x = Input.GetAxis("Horizontal");
             this.mMoveDirection.x *= this.mSpeed;
         }
         
         /////////BEGIN MOVING PLATFORM SUPPORT
         if (activePlatform != null) 
         {
             Vector3 newGlobalPlatformPoint = activePlatform.TransformPoint(activeLocalPlatformPoint);
             Vector3 moveDistance = (newGlobalPlatformPoint - activeGlobalPlatformPoint);
             
             if (moveDistance != Vector3.zero)
                     this.mController.Move(moveDistance);
             
             lastPlatformVelocity = (newGlobalPlatformPoint - activeGlobalPlatformPoint) / Time.deltaTime;
         }
         else 
         {
             lastPlatformVelocity = Vector3.zero;
         }
     
         activePlatform = null;
         ///////END MOVING PLATFORM SUPPORT
         
         //Moving player
         this.mMoveDirection.y -= this.mGravity * Time.deltaTime;
         this.mController.Move(this.mMoveDirection * Time.deltaTime);
             
         ////////BEGIN Moving platform support
         if (activePlatform != null) 
         {
             activeGlobalPlatformPoint = transform.position;
             activeLocalPlatformPoint = activePlatform.InverseTransformPoint (transform.position);
         }
         ///////END Moving platform support
     }
     
     void FixedUpdate () 
     {
         // Make sure we are absolutely always in the 2D plane.
         Vector3 pos = new Vector3(this.transform.position.x, this.transform.position.y, 0.0f);
         this.transform.position = pos;
     }
     
     void OnControllerColliderHit (ControllerColliderHit hit)
     {
         print(hit.moveDirection);
         
         if (hit.moveDirection.y > 0.01) 
             return;
         
         // Make sure we are really standing on a straight platform
         // Not on the underside of one and not falling down from it either!
         if (hit.moveDirection.y < -0.9 && hit.normal.y > 0.9) 
         {
             activePlatform = hit.collider.transform;    
         }
     }
     
 }

CODE: The platform controller (attached to PlatformObject)

 using UnityEngine;
 using System.Collections;
 
 public class CMovingPlatformController : MonoBehaviour 
 {
     public GameObject targetA;
     public GameObject targetB;
     
     float speed = 0.05f;
     
     void FixedUpdate () 
     {
         float weight = Mathf.Cos(Time.time * speed * 2 * Mathf.PI) * 0.5f + 0.5f;
         this.transform.position = targetA.transform.position * weight + targetB.transform.position * (1-weight);
     }
 }

Any help is 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

3 Replies

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

Answer by iPedro · Oct 11, 2011 at 07:38 PM

Figured it out, it's not the most elegant solution and in all honesty I still expect there to be a better one but for anyone that falls into a similar snake pit here is my solution:

in the platform controller script I added the following

 void OnCollisionStay(Collision collisionInfo) 
     {
         CPlayerControls playerControls = collisionInfo.gameObject.GetComponent<CPlayerControls>();
         
         foreach (ContactPoint contact in collisionInfo.contacts) 
         {
             //Debug.DrawRay(contact.point, -contact.normal * 10, Color.white);
             
             float fDir = contact.normal.x;
             
             if(fDir < 0.0f)
                 fDir += 0.6f;
             else
                 fDir -= 0.6f;
             
             playerControls.HorizontalPlatformCollision(-fDir);
             
         }
     }

In the character controller script I added the following method:

 public void HorizontalPlatformCollision(float pDirection)
     {
         this.mMoveDirection = new Vector3(pDirection, 0.0f, 0.0f);
         this.mMoveDirection = this.transform.TransformDirection(this.mMoveDirection); // Transforms direction from local space to world space
         this.mMoveDirection *= this.mSpeed;
         
         //Moving player
         this.mMoveDirection.y -= this.mGravity * Time.deltaTime;
         this.mController.Move(this.mMoveDirection * Time.deltaTime);
     }


This results in achieving my desired behavior.

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
1

Answer by jtbentley · Oct 10, 2011 at 03:52 AM

When moving physics objects, they must be moved within the FixedUpdate loop, because it is synchronous with the physics timestep. Moving in the update means that you might be exceeding tolerances etc inbetween the physics iterations.

Here's a citation from the unity manual

FixedUpdate should be used instead of Update when dealing with Rigidbody. For example when adding a force to a rigidbody, you have to apply the force every fixed frame inside FixedUpdate instead of every frame inside Update.

Also, you should never directly edit the transform of a rigid body, you should only edit its location through rigidbody functions...

Rigidbody.MovePosition

For kinematic rigidbodies it applies friction based on the motion of the rigidbody. This lets you simulate moving platforms with rigidbodies sitting on top of the elevator. If you want other rigidbodies to interact with the kinematic rigidbody you need to move it in the FixedUpdate function.

Comment
Add comment · Show 2 · 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 iPedro · Oct 10, 2011 at 04:32 PM 0
Share

So just to re-iterate:

I am using a CharacterController to move my player object and calling CharacterController.$$anonymous$$ove as described in the documentation.

I am not directly setting the transform except in fixed update where I make sure it always stays in the 2D world by setting the z position to 0. This was taken directly from the Unity 2D platformer (Lerpz) tutorial so I assume it's ok in this context.

$$anonymous$$y question still is how to achieve the following:

"The desired behavior is that the CharacerController be pushed by the horizontal platform in either direction."

With these clarifications is your advise still the same?

Thanks.

avatar image vxssmatty · Oct 11, 2011 at 10:25 PM 0
Share

2D world by setting the z position to 0. no longer need todo this, the Rigidbody has axis and rotation locks... maybe these will help, i doubt it.. but that the way todo those now.

avatar image
0

Answer by jtbentley · Oct 10, 2011 at 11:21 PM

Have you tried increasing the Skin Width?

Comment
Add comment · Show 1 · 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 iPedro · Oct 11, 2011 at 04:48 PM 0
Share

Thanks for sticking with me :) The character is a 2D sprite made with Sprite$$anonymous$$anager 2 so there is no skin width as far as I can tell.

I think the solution is to apply a force to the character when a collision occurs with the moving platform, but I'm not exactly sure how i go about doing that yet....

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

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Make a Platform push a character controller? 2 Answers

Stay on Moving Platform without Character Controller 1 Answer

Moving platform clips through character controller 2 Answers

Character Controller and Kinematic Collision 1 Answer

Keeping the player on a moving platform? 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