- Home /
Making a Character Controller push another Character Controller
Hello.
We are trying to implement a system for pushing Character Controllers using a Character Controller. Most likely this would require triggering a simplemove in the second CC after either an OnControllerColliderHit or OnTriggerEnter. Here is the simple script being used:
//this script goes on the player
public var speed : float = 15.0;
public var duration : float = 0.25;
private var controller : CharacterController;
function Start(){
controller = GetComponent(CharacterController);
}
function Knockback(direction : Vector3){
var startTime = Time.time;
while(Time.time < (startTime + duration)){
controller.SimpleMove(direction*speed);
yield;
}
}
function OnControllerColliderHit (hit : ControllerColliderHit) {
Knockback();
}
//function OnTriggerEnter (other : Collider) {
//if (other.CompareTag ("Player")) {
// Knockback();
// }
There is one error:
Assets/PushCharacterControllers.js(20,13): BCE0017: The best overload for the method 'PushCharacterControllers.Knockback(UnityEngine.Vector3)' is not compatible with the argument list '()'.
And here is the setup. We are using a standard FPS controller (right) with a parented trigger box as suggested. The FPS controller does not have a rigidbody attached. The character controller being tested for the collision is a duplicate of the FPS, except the camera and all the related movement and camera scripts have been removed. As the name suggests, this character controller has a rigidbody attached.
Would really appreciate some help with this script, it is a very simple script but at this stage none of the changes we have made seem to be improving the situation. Or, if there is a better method feel free to suggest it. In brief, the main purpose of this functionality will be for the attacking system, for example when the Player attacks an NPC/another Player, the hit will push them back a specified distance.
Looking forward to suggestions. Thank you
[1]: http://answers.unity3d.com/questions/188315/making-colliders-or-rigidbodies-move-a-character-c.html
Answer by Hamesh81 · Feb 05, 2012 at 07:57 PM
Quite surprised no one has answered this yet cos, it's pretty simple hey. J.K answered a similar question here but I'll post the script below for ease of use.
using UnityEngine;
public class Push : MonoBehaviour {
public Vector3 speed;
public void OnTriggerStay(Collider col) {
CharacterController ctrl = col.gameObject.GetComponent(typeof(CharacterController)) as CharacterController;
if (ctrl) {
ctrl.SimpleMove(speed);
}
}
}
It's in C# and if I remember correctly there was a line or two which needed fixing up. Other than that though, attach it to a trigger and whenever a character controller will enter it will get pushed by a constant force based on the variable you set. With a bit more work you may be able to change it to have one CC be able to push another. Hope that helps.
Cheers
Not exactly what I was looking for, but the closest so far. Thanks a lot buddy.
Answer by Kaze_Senshi · Feb 01, 2012 at 11:26 AM
Hmmm if the extension of the PushCharacterControllers.js is js you should wanting to use the unity's javaScript. Look at these two lines:
...
Vector3 pushAmt; // global "pushed by RBs" accumulator
...
void OnTriggerEnter(cc : Collider) {
...
In the first line you are putting the variable type in the front of the name ( C# variable declaration style ), in the later, you are using the parameter with the javaScript variable declaration style. So, it seems that you are mixing the things, try to change every variable to javascript style, for example:
Vector3 pushAmt (C#) -> var pushAmt : Vector (js)
You are absolutely right. Thank you for pointing that out, the script was in fact written in C# and I mistook it to be JS. How embarrassing! I have updated the script (and error) in the question and am still getting one error in regards to the moveDirection. Any idea as to what is wrong?
Well I don't know how you fixed it. If you mix the things like the code above, the compiler will become some crazy and give some errors close from the line with the "mix error". I think that you forgot to convert the functions too to the javascript style. For example the line above of the moveDirection is wrong, to fix it just change the "void" to the word "function":
void FixedUpdate() [C#] -> function FixedUpdate () [JavaScript]
By "fixed" I meant that I converted the necessary lines back to C# (see the question for the full script) which is what the original script was written in. I am not getting a mixed error, but I am getting an error about the moveDirection which I believe is because it hasn't been declared as a variable. Something like this needs to be added I think:
private var moveDirection : Vector3 = Vector3.zero;
But I'm not exactly sure.
Answer by Owen-Reynolds · Feb 02, 2012 at 03:27 AM
I think I might not have understood the set-up when I suggested that. I assumed you were starting with a Unity standard characterController script, on the player. I'm seeing an elaborate one named ThirdPersonController.js. I know there was a simpler one without the animation hooks. Most people posting about how to alter movement are starting with some varient.
That script would be on a model with only a character controller (no rigidbody -- using both tends to give odd effects, but OK to have an inactive RB, ready for a ragdoll.) It works fine, but purposely doesn't respond to anything hitting it. It looks something like (this is just to give the idea. You probably have it, and if you're using something else to move the player, not sure my idea works):
public Vector3 moveDirection = Vector3.zero;
public void FixedUpdate () {
float mvSpd = Input.GetAxis("Vertical");
if (grounded) {
......
}
// Apply gravity
moveDirection.y -= gravity * Time.deltaTime;
// == move dir computed, tweak it here but using it:
// moveDirection+=pushAmt .....
// Move the controller
CharacterController controller = GetComponent<CharacterController>();
CollisionFlags flags = controller.Move(moveDirection * Time.deltaTime);
grounded = (flags & CollisionFlags.CollidedBelow) != 0;
}
moveDirection
is recomputed from scratch each update, so it would be pointless to change it when we got hit. But, we could add the extra pushAmt
var, have OnTriggerEnter change that and tweak moveDir that way (in the == part above.)
It really does give a "bump" effect. It looks a tiny bit odd, but not much. For example, if you're knocked backwards you won't lose traction the way you really would, and will recover a tad too quickly.
Thank you Owen. As illustrated above, I am using the Unity FPS Controller from the Standard Assets to test the script. This is of coarse only for testing purposes; a CC will be used in the actual game but not the FPS controller. Understandably it will have a custom movement script/s and not use those in the Unity Standard Assets. I was hoping that this script could be separate from character movement, so that I could potentially attach it to some NPC's but be able to choose which have this ability and which do not. For example, the big/strong NPC's can push the player, but the small/weaker NPC's cannot. If that makes sense. I think this forum post is a similar example of what I am trying to achieve.
I have updated the script in the question and added the two errors I am getting. I commented out the "if grounded" part as it was causing an error the way it was and I am not sure what should be placed there. Haha, I thought I was beginning to understand the original script but now it's different again :)
Just to clarify: this script is to be placed on the FPS controller, or on the parented trigger box, or on the object/s being hit by the FPS? Secondly, do either of these two objects need a rigidbody?
Sorry. The idea was those three code chunks are ADDED to an existing movement script, which is already using moveDirection. The new code I typed isn't meant to be used at all -- just an example "is your current move script something like this?" and where the new stuff would go.
$$anonymous$$y example (just rechecked it) has a capsule collider with isTrigger on the player, right next to the characterController (I thought it needed parenting to have both, but it doesn't.) No rigidBody, as usual.
The objects pushing us are rigidBodies. Normally they won't push a charController object (the original problem.) The code keys off their speed. I believe it could also check the weight, for your "heavy" NPCS
The code lines are added to the current movement script. Again, the lines are (they should be translatable into javaScript, if you use that):
// add to globals:
Vector3 pushAmt;
// Add to Update or FixedUpdate, just before using moveDirection:
moveDirection += pushAmt;
pushAmt*=0.95f; // 0.95 is an arbitrary "friction" number
// add as normal event:
void OnTriggerEnter(Collider cc) {
Rigidbody rb = cc.rigidbody;
if(rb!=null) {
pushAmt += rb.velocity*0.5f;
}
}
Thank you so much for your effort. I think I understand quite well how it works now. It seems to work as expected when integrated with the FPS scripts, however for the in game character (& NPCs) the locomotion system is going to be used, and I am yet to test how it'll work with this more complex system. As I said before I was hoping rather than making multiple movement scripts, I would attach a separate script handling this functionality to the necessary characters. But either way, thank you so much for your effort in helping me try to figure this out. Wish there were more helpful people like you here. Cheers :)
Your answer
Follow this Question
Related Questions
how to make character controller push rididbodies 1 Answer
FPS Character Controller with the push DOWN rigidbodies ability 0 Answers
Making Colliders/Triggers or Rigidbodies move a Character Controller 5 Answers
Is there a way to make a wallrunning system using the character controller? 1 Answer
Why is my push rigidbody script not effected by mass? 2 Answers