- Home /
CharacterController "breaks" collision, goes haywire
Setup: I have a 2D XZ planed world that my character controller moves around in (top-down view). I have a tilemap with many mesh colliders (rectangular).
Question: Whenever I place polygonal colliders in the world (of any type) my character can seemingly "break" through them. When I push up against them for long enough, my character just "snaps" and starts rotating rapidly around the Y axis (3D space), or goes invisible. How do I prevent this?
What I've already tried: I've tried increasing the collider depth of all objects involved in these scenarios, I have attached a rigidbody and locked rotation on the X and Z axes, and locked position on the Y axis, and I have manually tried updating the EulerAngles every frame by setting the Y rotation to 0 every frame. This appears to help somewhat, yet still the character "breaks".
I find this sort of humorous, if the character tries hard enough, he can somehow break the rules of programming, and enter into the 3D world...VERY frustrating.
Here's the character script, if it helps:
using UnityEngine;
using System.Collections;
public class DungeonPlayerBehaviorScript : MonoBehaviour {
private const float VELOCITY = 40;
private const float ROTATION_SPEED = 1024.0f; // Degrees per second
private CharacterController controller;
private Vector3 direction;
private tk2dSpriteAnimator animator;
private Quaternion qTo;
private bool joystickConnected;
void Start () {
//ONLY FOR TESTING PURPOSES
//TODO: Make multiplayer-compatible joystick and input system
if (Input.GetJoystickNames ().Length > 0) {
joystickConnected = true;
} else {
joystickConnected = false;
}
animator = GetComponent<tk2dSpriteAnimator>();
Light2D.RegisterEventListener (LightEventListenerType.OnEnter, onBeamEnter);
}
void Update () {
updateFrameVariables();
if (joystickConnected) {
joystickMovementUpdate();
} else {
keyboardMovementUpdate();
}
if (controller.velocity.sqrMagnitude > 0) {
animator.Play ("forward");
} else {
animator.Play ("idle");
}
}
private void joystickMovementUpdate() {
if (direction.sqrMagnitude > 0.1f) {
qTo = Quaternion.LookRotation(direction);
qTo.eulerAngles = new Vector3(90, qTo.eulerAngles.y + 90, 0);
}
transform.eulerAngles = new Vector3(90, transform.eulerAngles.y,0);
transform.rotation = Quaternion.RotateTowards(transform.rotation, qTo, ROTATION_SPEED * Time.smoothDeltaTime);
controller.Move (new Vector3(Input.GetAxis ("Left Joystick Horizontal") * VELOCITY, 0, -Input.GetAxis ("Left Joystick Vertical") * VELOCITY) * Time.smoothDeltaTime);
}
private void keyboardMovementUpdate() {
transform.LookAt (Camera.main.ScreenToWorldPoint (Input.mousePosition));
controller.Move (new Vector3(Input.GetAxis ("Keyboard Horizontal") * VELOCITY, 0, Input.GetAxis ("Keyboard Vertical") * VELOCITY) * Time.smoothDeltaTime);
}
private void updateFrameVariables() {
controller = GetComponent<CharacterController>();
direction = new Vector3(Input.GetAxis ("Right Joystick Horizontal"), 0, Input.GetAxis ("Right Joystick Vertical"));
}
void onBeamEnter(Light2D light, GameObject go) {
Debug.Log (go.tag);
if (go.CompareTag ("Mob One")) {
go.GetComponent<MobOneBehaviorScript> ().State = 1;
}
}
void LateUpdate()
{
Camera.main.transform.position = new Vector3(transform.position.x, 2, transform.position.z);
}
}
Answer by MuseumTourGames · Aug 18, 2013 at 12:15 AM
The problem was that my CharacterController height was not high enough, and my player was "stepping" over the other object :)
This can also happen when it is too high. The bottom really counts as being curved, and charCont.$$anonymous$$ove runs physics-like code to decide whether to stepOver/around/getStuck.
It's a little bit trial&error whether a cube is heigh enough to be a wall or is merely a step.
Answer by Owen-Reynolds · Aug 17, 2013 at 05:40 PM
Sounds like an extra rigidbody on the player is causing the problem. Generally RBs and CC's on the same object fight each other.
Unlike a rigidbody "physics object", a characterController will never decide to just spin (your "rapidly spin around y" issue.) Rotation is completely controlled by the particular script, and most of them are pretty boring -- they rotate a fixed rate L/R based on arrow keys.
Sadly the problem still arises when I remove the rigidbody and only use the character controller...