- Home /
Answer by duck · May 18, 2010 at 01:37 PM
The built-in CharacterController class has special status in the physics engine which means that it doesn't interact with other physics objects by default.
In order to be able to push objects around, you need to add a script, as described in the CharacterController class manual page. It gives this example:
// this script pushes all rigidbodies that the character touches var pushPower = 2.0;
function OnControllerColliderHit (hit : ControllerColliderHit) { var body : Rigidbody = hit.collider.attachedRigidbody;
// no rigidbody
if (body == null || body.isKinematic) { return; }
// We dont want to push objects below us
if (hit.moveDirection.y < -0.3) { return; }
// Calculate push direction from move direction,
// we only push objects to the sides never up and down
var pushDir = Vector3 (hit.moveDirection.x, 0, hit.moveDirection.z);
// If you know how fast your character is trying to move,
// then you can also multiply the push velocity by that.
// Apply the push
body.velocity = pushDir * pushPower;
}
I'm also interested in this for future reference, how do you make it so they can only push certain objects, is that simply by na$$anonymous$$g a specific game object and if so what would that script look like... sorry, new to this whole scripting thing too. ;)
Answer by titegtnodI · Aug 19, 2012 at 07:50 PM
I use a modified version of the example. It's more useful if you want to interact via physics, I personally think my solution makes more sense. This solution will apply force to the point of contact. This means that if you bump into the corner, the object will rotate, if you hit the top, it will tip over. It's by no means absolutely perfect but it is better and still very simple.
The one also works with up and down so if you ever wanted to use a teeter totter you could. If you tried to simply enable downwards movement on the original script you won't get the intended results. I put this right into the CharacterMotor script which Unity provides, it really works nicely and makes things fun.
// this script pushes all rigidbodies that the character touches
var pushPower = 2.0;
var weight = 6.0;
function OnControllerColliderHit (hit : ControllerColliderHit)
{
var body : Rigidbody = hit.collider.attachedRigidbody;
var force : Vector3;
// no rigidbody
if (body == null || body.isKinematic) { return; }
// We use gravity and weight to push things down, we use
// our velocity and push power to push things other directions
if (hit.moveDirection.y < -0.3) {
force = Vector3 (0, -0.5, 0) * movement.gravity * weight;
} else {
force = hit.controller.velocity * pushPower;
}
// Apply the push
body.AddForceAtPosition(force, hit.point);
}
Nice ! What is your variable movement ? "$$anonymous$$ identifier: 'movement'."
I could be wrong but I believe it's in the default Character$$anonymous$$otor script. If it's not use a number like "20" (my value) or "10" (the default) ins$$anonymous$$d of "movement.Gravity".
thanks so much for this piece of code. i hate to be lazy but this is absolutely perfect, lightweight, and very straightforward.
I had to fix this by changing hit.controller.velocity
to hit.controller.velocity.magnitude * hit.normal * -1
.
The force being applied was not pointing the right direction some times, such as when the object the character was colliding with would resist the movement and make it move sideways.
Answer by AMartin223 · Jun 25, 2014 at 05:25 PM
The simpler, cleaner, less buggy solution is just simply:
function OnControllerColliderHit (hit : ControllerColliderHit) {
var body : Rigidbody = hit.collider.attachedRigidbody;
if (body != null && !body.isKinematic)
body.velocity += controller.velocity;
}
I added this script (C# version of above) to my CharacterController gameobject.
using UnityEngine;
using System.Collections;
public class ControllerCollderHit : $$anonymous$$onoBehaviour {
void OnControllerColliderHit(ControllerColliderHit hit)
{
Rigidbody body = hit.collider.attachedRigidbody;
if (body != null && !body.is$$anonymous$$inematic)
body.velocity += hit.controller.velocity;
}
}
This doesn't work at all, when my character hit rigidbody object, it's velocity immediately sets to zero vector, so that adding it's own velocity to hit rigidbody doesn't moving at all.
Answer by Whimsical · Jul 29, 2010 at 12:57 AM
I've recently come up with a funky solution to a similar problem: I had to go through a revolving door, pushing the blades of the door with my CharacterController. The revolving door was done with a (very very low poly) mesh collider and a RigidBody component held in place by a vertical hinge joint.
After I found out that a CharacterController isn't able to influence RigidBodies I created a new CapsuleCollider with the same size like the one my CharacterController used, attached a RigidBody component to it and wrote a very little script that always places this new CapsuleCollider at the same position that my CharacterController currently occupies. - That way the Capsule was pushing the doors like it would be pushed by the CharacterController itself. I then added a few lines of code to my script to switch off all physics on the CapsuleCollider at a certain distance from the door so that I could save the calculations for the physics when not needed.
That's probably not a good solution at all, but it worked perfectly and without any noticeable negative effect.
Answer by ARM95 · Dec 24, 2020 at 02:11 AM
How do you intend on using the push action? It it just for non scripted objects or an object that will 'use' the gameobject/rigid for a purpose?
Your answer
Follow this Question
Related Questions
Camera gets flung off of the map when the player collides with certain objects. 0 Answers
Velocity data from OnCollisionEnter is delayed (incorrect) 3 Answers
Rigidbody necessary to use collision detection 0 Answers
Avoid Player bouncing when colliding with objects 3D 1 Answer
OnCollisionEnter of Projectile detects parent with rigidbody instead of child objects with collider 2 Answers