- Home /
How to prevent rigidbody with capsule collider from walking off the edge of cube mesh if button held down?
I can't seem to figure out how to do this within Unity.
This kind of mechanic can be seen in Minecraft when holding down left shift, so that the player can place blocks adjacent to one he is standing on, by basically hovering over the very edge of the block.
Edit #1: Movement Script Info (I put it here in case it is somehow relevant, but I don't need an implementation that works with my current movement system, just the idea of how to do the mechanic):
I use a raycast to determine if the player is grounded, then I use a slightly modified wiki script for movement:
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
float percentofpercent = Mathf.Abs(horizontal) + Mathf.Abs(vertical) - 1;
if (percentofpercent > 0.1f)
{
percentofpercent = percentofpercent * 10000;
percentofpercent = Mathf.Sqrt(percentofpercent);
percentofpercent = percentofpercent / 100;
float finalMultiplier = percentofpercent * .25f;
horizontal = horizontal - (horizontal * finalMultiplier);
vertical = vertical - (vertical * finalMultiplier);
}
if (vertical > 0) {
vertical = vertical * forwardSpeed;
}
else if (vertical < 0) {
vertical = vertical * backwardSpeed;
}
horizontal = horizontal * strafeSpeed;
Vector3 vel = transform.TransformDirection(new Vector3(horizontal, rigidbody.velocity.y, vertical));
rigidbody.AddForce(new Vector3(vel.x - rigidbody.velocity.x, 0, vel.z - rigidbody.velocity.z), ForceMode.VelocityChange);
Edit #2: What I am talking about is the mechanic prevents you from being able to fall off of the edge of a block, it acts as if there is a wall an arbitrary distance away for every open edge of that current block the player is on, while also letting you hover an arbitrary distance off of that edge that normally would cause you to fall down (so that you can look at the side of that block without falling off), and this is true for any blocks you happen to walk against on the same plane, and connected to that initial block.
My only thought was to create a collision mesh on top of the block that basically had 4 walls and a floor that had dimensions larger than the block the player was currently standing on, and constantly checking for which block the player was on top of in order to reposition this mesh. But I really hate the thought of it, and was wondering if anyone had implemented this mechanic before and had a more elegant solution.
In the multicolored example, those individual collision meshes would only exist for each block when that player is on/near it and the key is held down. Again, I despise the idea of doing it in such a backwards way, and was hoping someone had implemented this before or knew how Minecraft did it, before I go ahead and do this hacky approach.
I also can't just give the player a box collider with a larger area, because that wouldn't work if the player is completely surrounded by walls on 3 edges of the block he is on, and also, while a bigger box collider will allow the player to go farther over an edge, it will do nothing to stop him from falling off.
I'm not specifically looking for an answer that works with my movement system, although I did edit my question to include my basic movement script.
I am looking to understand what kind of different solutions there are to this problem.
Answer by Namey5 · Oct 14, 2014 at 08:08 AM
All you would have to do is change the capsule collider to a box collider, then lock the rotation on the vertical axis' via the rigidbody component. If you wanted this only to happen on holding a button down, you could add both the capsule collider and the box collider & configure them, then have a script something like this:
#pragma strict
var bCol : BoxCollider; //Box collider
var cCol : CapsuleCollider; //Capsule collider
function Start () {
bCol = gameObject.GetComponent(BoxCollider);
cCol = gameObject.GetComponent(CapsuleCollider);
}
function Update () {
if (Input.GetKey(KeyCode.LeftShift)){ //If you wanted this to happen when pushing left shift, like in your example
bCol.enabled = true; //Disable/Enable the selected colliders
cCol.enabled = false;
} else {
bCol.enabled = false; //Swap the first Disable/Enable
cCol.enabled = true;
}
}
You could implement your script with this or vice/versa. To be perfectly honest, I'm not 100% sure what you are trying to accomplish, this is purely going off the given example, but I hope it helps, Namey5.
*Updated my question with more information ins$$anonymous$$d of putting the block of text here. See Edit #2.