Gravity for Character Control

Hello monkeys,



I’m having an issue that I can’t solve. I’m building up an attack system for my game, and while developing the structure for ranged units, I’m facing a problem I can’t solve.



So far, I’ve managed to create the projectile that will go from the attacker’s position, to the defender’s position. For now, I want it to be a homing projectile (follows the target even if he walks).


  • So, I create a Geometry (sphere in this case) and set it’s translation to the attacker position.
  • Then, I create a CharacterControl with a sphere shape with the same radius.
  • Because 2 CharacterControl’s can’t collide, I created then a GhostControl to detect the collision.
  • I then added both these control to the geometry
  • Set the gravity for the CharacterControl
  • Attach to the physics space
  • Set the gravity AGAIN



    On my update logic, here’s what I do:

    [java]projectil.setWalkDirection(projectil.getDefenderLocation().subtract(projectil.getLocation()).normalizeLocal());[/java]



    This works really really good so far. The problem is that, for positive gravity, the curve that the object does I can control by changing the value of the gravity. Found out that around 2 or 3 positive gravity does the motion I want to cause. Higher values (like 100) causes, of course, a bad behaviour. Problem is that the curve is on the wrong side, so I need the gravity to be negative.



    Now, for negative gravity (that means, go up), swapping the value of the gravity doesn’t change nothing. So this means:


  • Gravity = +1 (low gravity)
  • Gravity = +10 (medium gravity)
  • Gravity = +100 (high gravity)


  • Gravity = -1 (low gravity)
  • Gravity = -10 (same low gravity)
  • Gravity = -100 (same low gravity)



    I’ve even recorded 2 videos, one with positive (+100 gravity) and the other with negative (-100 gravity)



    http://www.youtube.com/watch?v=sG8jooL4Rqw


http://www.youtube.com/watch?v=gwewi_BqmIY


What is wrong with this approach? And for non-moving targets, should I use RigidBody and an applyImpulse to have a better curve? Because I wanted a really nice parable.

I don’t exactly know how the gravity in the character works (its not “real” bullet gravity and not correlated with the physics spaces gravity) but I suggest doing the movement of the sphere yourself and not with a character control. If you need it to push away other stuff, use a kinematic rigidbody.

1 Like

So, to calculate the trajectory, I would need to do some math calculations.



tangent X = (Sy - Syo + gt^2) * (Sx - Sxo)



tangent ^ -1 ( tangent X ) = X



Vo = (Sx - Sxo) / (t * cosX)



S = distance

g = gravity

t = time in the air



I think this is correct. I just have no idea how to get the values from the 3D space (like the initial position vector is (1.5, 7.13, 2.62) and the final is something like (-2.7, 4.56, 3.31) ). Maybe it’s because 4 am, but how could I make some math for a 2D plane given 2 vectors from a 3D plane?

You don’t need to solve for the trajectory at the start though, you just need to iterate each step which is much simpler.



Essentially you store a velocity for your object. Give it an initial acceleration up and forwards…each frame apply an acceleration downwards (modified for tpf)…that will give you a nice curve automatically…(it’s essentially the same way real gravity works!

@zarch said:
You don't need to solve for the trajectory at the start though, you just need to iterate each step which is much simpler.

Essentially you store a velocity for your object. Give it an initial acceleration up and forwards...each frame apply an acceleration downwards (modified for tpf)....that will give you a nice curve automatically...(it's essentially the same way real gravity works!


Yeah, but to give it an initial velocity, I would need to calculate it, or else I could end up with the projectile that was launched not hitting the target.

Update logic
[java]projectil.setDirection(projectil.getDefenderLocation().subtract(projectil.getLocation()).normalizeLocal().addLocal(projectil.getAcceleration().addLocal(projectil.getGravity().mult(tpf))).addLocal(projectil.getInitialVelocity()));[/java]

Initial velocity
[java]Vector3f initialVelocity = target.getLocation().subtract(attacker.getLocation()).normalizeLocal().addLocal(Vector3f.UNIT_Y.mult(3f));[/java]

For a certain combination of range, initial velocity and gravity this works, but if it's closer or further than this range, the projectile misses the target. I think I missed something.

http://www.youtube.com/watch?v=sfRf92NPfSo

Homing projectiles are easy, just adjust them in the air to home in on the target…



You will never hit a moving target even if you allow for current movement as they can always change course…

I don’t know how to home a moving target and having the launched projectile describing a parabole in the mid air. Doesn’t need to be a tall one, but just a curve to describe just like an arrow being shot.

Something like (entirely untested):



[java]private static final float INITIAL_UP_ACC = 1f;



class Projectile {



Vector3f velocity = new Vector3f(0,INITIAL_UP_ACC,0);

Spatial target;

Spatial projectile;

float acceleration;



update(float tpf) {

Vector3f move = target.getWorldLocation().subtract(projectile.getWorldLocation());

velocity.addLocal(move.multLocal(tpf*acceleration));

projectile.move(velocity);

}



}

[/java]

1 Like

This will accelerate faster the further apart the objects are. To change it to a constant normalizeLocal() move before multiplying tpf and acceleration.

Well, that didn’t work. It ended up with a circular movement around the target. So, I’ve came up with a similar solution:



[java]projectil.setDirection(projectil.getDefenderLocation().subtract(projectil.getLocation()).normalizeLocal(), tpf);



void setDirection(Vector3f direction, float tpf) {

CharacterControl control = (CharacterControl) moving;

control.setWalkDirection(velocity.add(direction.mult(speed)));

velocity.multLocal(0f, 1 - tpf, 0f);

}[/java]



It works well for now. Thanks both for the help!

Hmm, yeeh. My formula was essentially gravity-esq so you could get an orbit. The normalize might have helped.



Glad you found a solution anyway :slight_smile:

Normalizing would give me a constant orbit, and the projectile would never hit ^^ I need this for an attack system.

Actually no. With the system above the acceleration reduced the closer you were. Normalizing the acceleration means that it would always be at full strength - and hence would help pull the projectile in towards the target.



Really though for a proper homing behaviour you would probably need to look at the difference between your velocity and their location and vary the acceleration angle so it homes in rather than just heading directly towards.

I didn’t managed to get it working as you said @zarch :confused:

Fair enough :slight_smile:



Well if you have a solution you are happy with then it’s all good.