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.
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);
}
}
}
…
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;
}
}