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:
- When standing still the platform passes through the CharacterController
- 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:
- Unity 3.4
- The platform isKinematic = true
- The platform has a rigidBody
- 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!
Thanks for sticking with me :) The character is a 2D sprite made with SpriteManager 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....
– iPedro