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.

alt text

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

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

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)

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.