- Home /
Keeping object with character controller from staying on top of another character controller object
I have a battle system where the players and enemy have character controllers. However, if a player jumps on top of an enemy, he can stay on top of it. I want to know if there is a way to do the following :
Voted your question up just for providing us with pretty pictures. :)
Thanks, visuals seem to get people a better understand, amirite?
Answer by Jason_DB · Feb 14, 2011 at 01:53 AM
I think that you could easily do this with a trigger collider on top of the enemy. Just put a box-shaped trigger as a child of the enemy on top of its head (slightly above, so that the player would collide with it when on top of the enemy). While the player is in collision with the trigger, just move him. The trigger would have a script like this:
var slideSpeed : float;
//While the player is in collision with the trigger, move him forward
function OnTriggerStay (other : Collider) { var controller = other.GetComponent(CharacterController); if(controller != null){ controller.SimpleMove(forward * slideSpeed); } }
It's kind of a simple solution, but it should slide the player off of the enemy's head effectively.
This would work as well. I still prefer my solution(s) because how the character slides off would then depend on where on top the enemy the player is standing, but hopefully this one is simple enough for SirVictory to understand, because I think I just confuse people a lot with half of my answers. :P
If he's STILL having problems... I think he should stick to using really slippery capsule colliders with locked rotations, because that will certainly accomplish the same effect with absolutely no program$$anonymous$$g required.
Answer by Jason B · Dec 28, 2010 at 01:42 AM
If both the player and monster are basing their collisions on capsule colliders as they should be with character controllers, I should think this would happen naturally... or should.
In the event that it's not, as I'm sure it isn't, you should run OnCollision checks and get your character collider's hit normals (you can debug this by running the aforementioned check and then within that function, send the hit.normal to a GUIText or something). Based on the hit normals, it should be pretty easy to apply dynamic velocity until the player is completely slid off the monster's head (since hit normals are just vectors, with each axis ranging from -1.0 to 1.0).
Basically what I'm saying is, grab the hit normals and do some basic math to figure out an ideal way to apply force to the character using the normal values to push him off. I'm not sure on the math required to do it, but I hope that helps you brainstorm something.
Thanks, (Even though I'm a programmer, I hate math) Hopefully I can figure out what you're talking about. The collisions are doing what they are naturally suppose to do, I just don't want it to (lol).
Once you play around with visualizing hit normals, you'll get a really good idea of what I'm saying (I hope). I'm kind of obsessed with hit normals since learning what they can do (easily detect your character's head hitting the ceiling, detecting if the character is grounded, on an incline, walking against a wall, etc).
I too hate math. I avoid even doing it for my own projects unless I have to, so I won't help you there. :D
Try giving the charactercontroller a $$anonymous$$ove command. Tell it to move in a way relative to the X and Z normals of the collision (for instance, try just telling it to move by the normal amounts times Time.deltaTime).
In a 2D scenario, if you're standing on a 45 degree incline (inclined from left to right), it returns an X hit normal of 0.5. The higher the incline, the faster the charactercontroller moves if you tell the X movement to go the same amount as the incline it's standing on.
I'm sorry, could you provided a code example? I would most appreciate it. All I could manage was charController.$$anonymous$$ove(moveDirection * Time.deltaTime) (pathetic me) SO, would have have to do an OnCollision or would I used something different since I am using Character Controllers with my collision check?
Answer by Jason B · Dec 28, 2010 at 08:59 PM
Sorry, I had to add the code as a second answer. I realized my usual login isn't registered, so I couldn't use it on a different computer, and just decided to properly register a new ID this time (and lose my precious few medals, blah!).
Here's a variable I would use to grab and hold onto the last known collision normal.
private Vector3 hitNormal;
Here's the code I use to grab hit normals of an attached CharacterCollider.
void OnControllerColliderHit(ControllerColliderHit hit)
{
Debug_Text.guiText.text = "Collision normals: " + hit.normal;
hitNormal = hit.normal;
}
Any time the character controller collides, it will report the hot normals to my GUI Text.
Debug_Text is just a variable I have declared at the top of my script.
public GameObject Debug_Text;
It's public so I can just drag and drop the GUI Text into it (I make most of my variables public just out of laziness!).
Okay. So if you play with that, you'll see on-screen what the hit normals look like whenever the attached controller collides with something. What you want to pay attention to is the X and Z coordinates. They'll range from -1.0F to 1.0F depending what angle they're colliding with the monsters.
Applying dynamic motion is now stupid-simple from here. :D Plop this single line of code wherever you want the motion to occur (probably inside an Update). I use SimpleMove rather than Move because in this case you probably want gravity to take effect. If you don't, use Move instead.
gameObject.GetComponent<CharacterController>().SimpleMove(new Vector3(hitNormal.x * Time.deltaTime, 0, hitNormal.z * Time.deltaTime));
What that code does: Finds the CharacterController attached to the game object that this script is attached to. Orders movement. Orders it to move in the direction of the hit normal X value (stored in hitNormal.x), no Y value, and the hit normal Z value (stored in hitNormal.z).
Is that more helpful?
Like I already said at the top of this answer: "I realized my usual login isn't registered, so I couldn't use it on a different computer, and just decided to properly register a new ID this time". Anyways, what about it isn't working, SirVictory? Are you having trouble getting the hit normals, or moving the character?
$$anonymous$$oving the character. Well, for one, I don't think I even set up writing the script correctly. DO you $$anonymous$$d re-writing the code snippets into a script? $$anonymous$$y character doesn't jump correctly anymore and doesn't slide when i write it :P
Answer by user-3061 (yahoo) · Feb 11, 2011 at 07:37 AM
you can try using a trigger collider than sends a sideways force certain tags such that when the "green egg" ( refer to own picture ) when it collides with the fake collider of the " red egg". this ensures smooth sliding of the "green egg" when colliding with the "red egg". Also, check the trigger collider for info on fake colliders. Good luck!
Your answer
Follow this Question
Related Questions
OnCollisionEnter not working with CharacterController 1 Answer
Is there a rigidbody character controller 3rd person that can handel stairs (steps)? 1 Answer
Can't use Rigidbody or Character Controller 0 Answers
How can I make two Character Controllers Collide 2 Answers
How do I detect when two CharacterControllers collide? 0 Answers