Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
7
Question by TurboHermit · Apr 20, 2012 at 03:13 PM · physicsrigidbodycharacter controllerknockback

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?

Comment
Add comment · Show 3
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image unfoundfate · Apr 21, 2012 at 01:31 PM 0
Share

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

avatar image HitStop · Jun 07, 2013 at 08:58 AM 0
Share

Would it be feasible to temporarily disable the character controller?

avatar image Sciman101 · Jun 09, 2015 at 06:29 AM 0
Share

Tried it myself, works perfectly!

4 Replies

· Add your reply
  • Sort: 
avatar image
34
Best Answer

Answer by aldonaletto · Apr 21, 2012 at 01:49 PM

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);
           }
         }
       }
       ...
    
    
    
    
    
    
    
    
    
    
Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image TurboHermit · Apr 23, 2012 at 11:31 AM 0
Share

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.

avatar image s_guy · Apr 18, 2013 at 03:58 AM 1
Share

This is good stuff. +1 from me. It should have more votes I$$anonymous$$O.

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.

avatar image aldonaletto · Jun 15, 2013 at 01:23 AM 0
Share

@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 Send$$anonymous$$essage.

avatar image barnacle-balogh · Dec 12, 2017 at 11:30 PM 0
Share

Thanks @aldonaletto ! This is super helpful for me!

avatar image StellarVeil · Apr 18 at 08:37 PM 0
Share

This works except that sometimes the force applied on Y gets glitchy where the object isn't thrown into the air with the intended value, like barely gets lifted off the ground by 1 inch and sometimes it's too strong. I'm not sure what's the cause but it seems dir.normalized is one possible cause as its value fluctuates depending on the positioning of the target and force source.

avatar image
14

Answer by hamcav · Sep 04, 2013 at 11:08 PM

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;
         }
     }

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Taloose · Oct 26, 2018 at 11:08 PM 0
Share

Oh I love you. So glad I scrolled down.

avatar image artificialstupidity · Aug 11, 2019 at 09:59 AM 0
Share

uhh so, how do you get this to work?

avatar image
4

Answer by Swibo · Oct 07, 2017 at 08:35 AM

If you like to keep number of scripts on gameobjects to a minimum, like me, then you can use this script.

I've modified hamcav's script to a more centralized approach.

 using UnityEngine;
 
 using System.Collections.Generic;
 
 public class ImpactReceiver : MonoBehaviour
 {
     static Dictionary<GameObject, List<Vector3>> forcesOnGameObjects = new Dictionary<GameObject, List<Vector3>>();
 
     // Update is called once per frame
     void Update()
     {
         List<GameObject> gameObjectsToRemove = new List<GameObject>();
 
         //our shit
         foreach (KeyValuePair<GameObject, List<Vector3>> gameObjectToBeMoved in forcesOnGameObjects){
             GameObject target = gameObjectToBeMoved.Key;
 
             if (target == null) {
                 gameObjectsToRemove.Add(gameObjectToBeMoved.Key);
                 continue;
             }    
 
             List<Vector3> impacts = gameObjectToBeMoved.Value;
             Vector3 finalImpact = Vector3.zero;
             foreach (Vector3 impact in impacts) finalImpact += impact;
 
             if (finalImpact.magnitude > .2f)    {
                 target.GetComponent<CharacterController>().Move(finalImpact * Time.deltaTime);
             }
 
             for (int i = 0 ; i < impacts.Count ; i++){
                 forcesOnGameObjects[gameObjectToBeMoved.Key][i] = Vector3.Lerp(impacts[i], Vector3.zero, 5 * Time.deltaTime);
             }
         }
         foreach (GameObject gameObjectToRemove in gameObjectsToRemove){
             forcesOnGameObjects.Remove(gameObject);
         }
     }
 
     public static void AddImpactOnGameObject(GameObject target, Vector3 impact)
     {
         // add object with impact to tuple
         if (!forcesOnGameObjects.ContainsKey(target))
         {
             List<Vector3> existingImpacts = new List<Vector3>();
             existingImpacts.Add(impact);
             forcesOnGameObjects.Add(target, existingImpacts);
         }
         else
         {
             List<Vector3> existingImpacts = forcesOnGameObjects[target];
             existingImpacts.Add(impact);
             forcesOnGameObjects[target] = existingImpacts;
         }
     }
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by SlavCabbag · Jul 17, 2021 at 02:03 PM

I made it affect your character locally and got rid of the magnitude thing which might have been a mistake or something but here it is.

To use put this script on your thing with the character controller (probably your player) and when you are going to trigger it use

 ImpactReceiver.AddImpactOnGameObject(//the game object you put the script on//, new Vector3(x value, y value, z value);


 using UnityEngine;
 
 using System.Collections.Generic;
 
 public class ImpactReceiver : MonoBehaviour
 {
     static Dictionary<GameObject, List<Vector3>> forcesOnGameObjects = new Dictionary<GameObject, List<Vector3>>();
 
     // Update is called once per frame
     void Update()
     {
         List<GameObject> gameObjectsToRemove = new List<GameObject>();
 
         //(their) our (☭) shit
         foreach (KeyValuePair<GameObject, List<Vector3>> gameObjectToBeMoved in forcesOnGameObjects)
         {
             GameObject target = gameObjectToBeMoved.Key;
 
             if (target == null)
             {
                 gameObjectsToRemove.Add(gameObjectToBeMoved.Key);
                 continue;
             }
 
             List<Vector3> impacts = gameObjectToBeMoved.Value;
             Vector3 finalImpact = Vector3.zero;
             foreach (Vector3 impact in impacts) finalImpact += impact;
 
 
             finalImpact = finalImpact.x * transform.right + transform.forward * finalImpact.z;
                 target.GetComponent<CharacterController>().Move(finalImpact * Time.deltaTime);
 
             for (int i = 0; i < impacts.Count; i++)
             {
                 forcesOnGameObjects[gameObjectToBeMoved.Key][i] = Vector3.Lerp(impacts[i], Vector3.zero, 5 * Time.deltaTime);
             }
         }
         foreach (GameObject gameObjectToRemove in gameObjectsToRemove)
         {
             forcesOnGameObjects.Remove(gameObject);
         }
     }
 
     public static void AddImpactOnGameObject(GameObject target, Vector3 impact)
     {
         // add object with impact to tuple
         if (!forcesOnGameObjects.ContainsKey(target))
         {
             List<Vector3> existingImpacts = new List<Vector3>();
             existingImpacts.Add(impact);
             forcesOnGameObjects.Add(target, existingImpacts);
         }
         else
         {
             List<Vector3> existingImpacts = forcesOnGameObjects[target];
             existingImpacts.Add(impact);
             forcesOnGameObjects[target] = existingImpacts;
         }
     }
 }



Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

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

Answers Answers and Comments

21 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

I can't push a Rigidbody with Character Controller 1 Answer

How to get a character controller to interact with rigidbodies with C# 0 Answers

How to setup character Collisions? 2 Answers

How to keep rigidbody from falling through terrain? 2 Answers

CharacterController jumps when colliding with kinematic rigidbodies 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges