Unity 2D - Impulse by angle

Hello, i need to create a script that must give an impulse for the player, but, the impulse need to have an limit in an angle and need to loose strength according with the distance.

How can i do this in C# script ? Can you guys can give me an example, or explain for me ?

Here is some simple 3D based solution, you can create something like that in 2D:

using UnityEngine;
using System.Collections;

public class ImpulseCreator : MonoBehaviour 
    public float Force = 10f;
    public float Angle = 30f;
    public float Distance = 10f;

    void FixedUpdate()
        var hits = Physics.SphereCastAll(transform.forward, Distance, transform.forward);
        for (var i = 0; i < hits.Length; i++)
            var rigid = hits*.collider.GetComponent<Rigidbody>();*

if (rigid != null)
var vector = hits*.collider.transform.position - transform.position;*
if (Vector3.Angle(vector, transform.forward) <= Angle)
rigid.AddForce(transform.forward * Force * (1 - Mathf.Min(vector.magnitude / Distance, 1f)));

void OnDrawGizmos()
Gizmos.color = Color.red;
Vector3 forwardPos = transform.position + transform.forward * Distance;
float rad = Mathf.Tan(Angle * Mathf.PI / 180) * Distance;
Gizmos.DrawLine(transform.position, forwardPos);
Gizmos.DrawLine(transform.position, forwardPos + transform.up * rad);
Gizmos.DrawLine(transform.position, forwardPos - transform.up * rad);
Gizmos.DrawLine(transform.position, forwardPos + transform.right * rad);
Gizmos.DrawLine(transform.position, forwardPos - transform.right * rad);


First, adding an impulse to an object requires the object to have a rigibody ; code looks like this:

Vector3 forceVect = new Vector3 (x, y, z);
Rigidbody.AddForce(forceVect, Forcemode.Impulse);

Now you have to determinate how much strengh you’re going to put in that impulse and in what direction. Ii should be something like “normalizedVector3 * forceAmount” so you can change independently both of them.

Angle limit is maths: you have one Vector3 between the center of your ‘actor’ and the center of your player ; and an other Vector3 between which perpendicular to ‘actor’ (it should be like transform.forward or transform.up). You can compute the angle between these two with Vector3.Angle(); … if the angle is within your limit value, force is to be added, else, not.

Vector3 dirVect = playerTransform.position - actorTransform.position;
Vector3 normalVect = actorTransform.transform.up; //or whatever it is
float angleValue = Vector3.Angle(dirVect, normalVect);

float angleLimit = 30; //Let's say you want +/- 30degs of angle limit
if (angleValue < angleLimit && angleValue > -angleLimit) {
   //Add force
} else {
   //Don't add force, or whatever behaviour you want

Last step is to choose the amount of force we want to add with the impulse.
First, the direction: let’s say you want to add a force perpendicularly to the actor despite how close the player is from the limits (hence we’ll use normalVect but you can choose any direction), then you want it to be normlalized ton only have the direction information. So we use normalVect.normalized (note that transform.up or transform.foward are already normalized but if you use a random direction, remember this step).

Second, intensity: you need to think of how you want the amount of force to diminish based on distance: is it linear ? square root ? at some power ? Let’s say you want it to be linear.

Distance to the player can be easily computed with Vector3.Magnitude(dirVect);.

float distance = Vector3.Magnitude(dirVect);

Force amount will follow this kind of law:

forceAmount = - coeff x distance + offset (with coeff > 0)

If the player is further than offset/coeff from the actor, the force added would be < 0, so we’ll need to add a condition (if) to check the distance and set the force to 0 if the player is too far.

float coeff = 1.06f; //How fast force amount reduces with distance
float offset = 106; //Force to impulse when distance is equal to 0

Vector3 forceVect;
if (distance < offset/coeff) {
   forceVect = normalVect.normalized * (- coeff * distance + offset);
} else {
   forceVect = Vector3.zero;

Now you have all the tools you need to build a nice script that will kick that player away :slight_smile: