x


Force on Character Controller (Knockback)

Hi, I'm working on a pretty big project in which this is rather important. I'm using a Character Controller component with a customized movement script. It doesn't have a Rigidbody component attached to it, so I thought that excludes physics.

However, what I want to accomplish is... That when the player is hit by an projectile, it gets knocked back, depending on the speed and mass of the projectile. I already have the projectile and all, I just need some headstart on scripting these physics-like things without having to use a rigidbody.

Anyone any suggestions?

more ▼

asked Apr 20, 2012 at 03:13 PM

Danzou gravatar image

Danzou
395 121 110 118

Could alter the players transformation.position and use a ray to check if anything is behind them.

Apr 21, 2012 at 01:31 PM unfoundfate

Would it be feasible to temporarily disable the character controller?

Jun 07, 2013 at 08:58 AM HitStop
(comments are locked)
10|3000 characters needed characters left

2 answers: sort voted first

You can add the script below to each character (CharacterController is required!). When a bullet hits the character, you must get this script (let's call it ImpactReceiver.js) and call the function AddImpact passing the impact direction (the bullet direction, for instance) and the force you want to apply.

var mass = 3.0; // defines the character mass
var impact = Vector3.zero;
private var character: CharacterController;

function Start(){
  character = GetComponent(CharacterController);
}

// call this function to add an impact force:
function AddImpact(dir: Vector3, force: float){
  dir.Normalize();
  if (dir.y 

0) dir.y = -dir.y; // reflect down force on the ground impact += dir.normalized * force / mass; }

function Update(){ // apply the impact force: if (impact.magnitude > 0.2) character.Move(impact * Time.deltaTime); // consumes the impact energy each cycle: impact = Vector3.Lerp(impact, Vector3.zero, 5*Time.deltaTime); }

Some examples:

  • When shooting with raycast (weapon script):
  ...
  if (Physics.Raycast(ray, hit)){
    if (hit.rigidbody){ // it the object hit is a rigidbody, add force:
      hit.rigidbody.AddForce(ray.direction * force);
    } else { // but if it's a character with ImpactReceiver script, add impact:
      var script: ImpactReceiver = hit.gameObject.GetComponent(ImpactReceiver);
      if (script) script.AddImpact(ray.direction, force);
    }
    ...
  • When applying explosion force (explosion script):
  ...
  colliders = Physics.OverlapSphere (explosionPosition, explosionRadius);
  for (var hit in colliders) {
    if (hit.rigidbody){ // if it's a rigidbody, add explosion force:
      hit.rigidbody.AddExplosionForce(explosionPower, explosionPosition, explosionRadius, 3.0);
    } else { // but if it's a character with ImpactReceiver, add the impact:
      var script: ImpactReceiver = hit.transform.GetComponent(ImpactReceiver);
      if (script){
        var dir = hit.transform.position - explosionPosition;
        var force = Mathf.Clamp(explosionPower/3, 0, 15);
        script.AddImpact(dir, force);
      }
    }
  }
  ...
more ▼

answered Apr 21, 2012 at 01:49 PM

aldonaletto gravatar image

aldonaletto
57.2k 31 79 292

And what if I want the script to be called OnTriggerEnter, I have an explosion which is a sphere with Trigger collision that automatically grows in size.

Apr 23, 2012 at 11:31 AM Danzou

This is good stuff. +1 from me. It should have more votes IMO.

I think it might be appropriate to simplify things a bit since you can just work with the force vector and not split out a normalized vector and its magnitude.

I recommend Danzou marks this as answered.

Apr 18, 2013 at 03:58 AM s_guy

@s_guy, you're right: I actually used the force vector in my own scripts - it's simpler, and additionally allows to call AddImpact via SendMessage.

Jun 15, 2013 at 01:23 AM aldonaletto
(comments are locked)
10|3000 characters needed characters left

i searched for this, found it , and converted to c# :) thx aldonaletto, its really helpful and amazing

using UnityEngine;

using System.Collections;

public class ImpactReceiver : MonoBehaviour {
    float mass = 3.0F; // defines the character mass
    Vector3 impact = Vector3.zero;
    private CharacterController character;
    // Use this for initialization
    void Start () {
         character = GetComponent<CharacterController>();
    }

    // Update is called once per frame
    void Update () {
     // apply the impact force:
     if (impact.magnitude > 0.2F) character.Move(impact * Time.deltaTime);
         // consumes the impact energy each cycle:
         impact = Vector3.Lerp(impact, Vector3.zero, 5*Time.deltaTime);
    }
    // call this function to add an impact force:
    public void AddImpact(Vector3 dir, float force){
      dir.Normalize();
      if (dir.y < 0) dir.y = -dir.y; // reflect down force on the ground
      impact += dir.normalized * force / mass;
    }
}
more ▼

answered Sep 04, 2013 at 11:08 PM

hamcav gravatar image

hamcav
130 3 5 8

(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x3110
x3080
x313
x20

asked: Apr 20, 2012 at 03:13 PM

Seen: 7314 times

Last Updated: Sep 04, 2013 at 11:08 PM