- Home /
Moving an object using rigidbody.AddForce & keyboard input.
I'm making a simple top down shooter to get to grips with Unity and have hit a snag.
When the player moves within range of an enemy, the enemy should start following the player. This works using the following in FixedUpdate:
function FixedUpdate()
{
if (player)
{
distance = Vector3.Distance( player.transform.position, transform.position);
if ( distance < 1.5 && distance > 0.05 )
{
var delta = player.transform.position - transform.position;
delta.Normalize();
var speed = moveSpeed * Time.deltaTime;
print("close");
rigidbody.MovePosition(rigidbody.position + (delta * speed));
}
}
}
However, It doesn't work if I use:
rigidbody.AddForce(rigidbody.position + (delta * speed));
Furthermore, it doesn't even work if I use:
rigidbody.AddForce(transform.forward * 10000,ForceMode.Impulse);
There's just no movement at all when using AddForce. It's probably something really simple but I couldn't find an answer on the forums/online.
Has anyone encountered this before?
I should say that I also intend to get the player to move using rigidbody.AddForce and the WASD keyboard input, hence my original title. Apologies for any confusion. Either way, it's the AddForce which is proving problematic.
Answer by Tomer-Barkan · Oct 09, 2013 at 10:26 AM
Most likely your rigidbody is set to be kinematic - that means it's not affected by external forces, so AddForce()
will not affect it. Make sure that the kinematic checkbox in the rigidbody is off. Also, AddForce()
applies the force for the time of the FixedUpdate
, so there's no need to multiply it by Time.deltaTime (and even if you did, you'd want to use Time.fixedDeltaTime when you use it in FixedUpdate()). Last, the vector you want to pass to AddForce
, is in the direction of the force you want to apply, I'll assume forward.
So the code should be:
rigidbody.AddForce(transform.forward * 100)
you can play with the number to get the accelleration you want. Keep in mind that this
Thanks for the info re Time.DeltaTime & Time.fiexedDeltaTime. I'll be sure to do look into this a bit more.
Re the physics issue, neither of the objects are $$anonymous$$inematic, so it can't be that.
The documentation states that both rigidbody.$$anonymous$$ovePosition & rigidbody.AddForce take a vector 3. The snippet posted above is to make the enemy move toward the player. I can't understand why it works for $$anonymous$$ovePosition, but not for AddForce.
I appreciate it'll probably easier to make the enemy transform.forward, then change his rotation to look at the player, but that still doesn't resolve why AddForce doesn't work, and I'll need my player to move on impulse via WASD input.
Any other suggestions on what I can try?
Thanks again.
Addforce should work as long as your object is not kinematic, or you haven't locked X/Y/Z position accidentally.
Why don't you share the rest of your class, and maybe a screenshot of the inspector (specifically of the rigidbody and collider).
One more thing to consider - if the mass of your object is too large, the force might be negligible. Try using Force$$anonymous$$ode.VelocityChange
as the second parameter to AddForce()
, just for testing. This will ignore the object's mass.
One more thing to try - try changing the velocity manually (ie rigidbody.velocity = somethingl
). If it doesn't move that way, it might be colliding with something or some other forces might be applied there such as friction.
I've been playing around and rather stupidly the problem seems to be that drag was set too high, (I guess $$anonymous$$ovePostion was forcing the movement).
Everthing works fine if I use: rigidbody.$$anonymous$$ovePosition(rigidbody.position + (delta * speed));
The enemy follows the players position, within a certain range.
Weirdly, if use:
rigidbody.AddForce(rigidbody.position + (delta * speed));
The enemy moves directly toward the top of the screen along the Z axis. It's movement is unaffected by the player position, except when the player is out of range. It's almost as if it's using transform.forward, though the enemies rotation doesn't effect movement direction...
I am limiting motion on the Y (up) axis, and rotation on the Z & X axis, but have tested both with and without these constraints and/or box collider. It operates directly, whichever setup I'm using.
If posting screen grabs of anything would be useful, please let me know, but I can't think of any info I've left out. I can work up a simplified test scene too, if that would help, though it's pretty basic stuff already.
$$anonymous$$y total script for the enemy object is super-basic, but is as follows for anyone interested:
#pragma strict
var moveSpeed : float = 0.0;
var rotSpeed : float = 0.0;
var player : GameObject;
var distance : float;
var mult : float;
function Start()
{
moveSpeed = Random.Range( 0.15, 0.5);
rotSpeed = Random.Range( 0.0, 30.0);
player = GameObject.FindGameObjectWithTag("Player");
}
function Update()
{
if (!player)
{
Debug.Log ("ERROR could not find Player!");
return;
}
}
function FixedUpdate()
{
if (player)
{
distance = Vector3.Distance( player.transform.position, transform.position);
if ( distance < 1.5 && distance > 0.05 )
{
var delta = player.transform.position - transform.position;
delta.Normalize();
var speed = moveSpeed * Time.deltaTime;
print("player is close");
//rigidbody.$$anonymous$$ovePosition(rigidbody.position + (delta * speed)); //<-- this line works.
rigidbody.AddForce(rigidbody.position + (delta * speed)); //<-- this line moves straight along the z axis.
}
}
}
//collisions
function OnCollisionEnter(hit : Collision)
{
if(hit.gameObject.tag == "bullet")
{
Destroy (gameObject);
}
}
AddForce adds force in the direction of the vector you pass it. So if you want to stay in place, you pass it Vector3.zero. On the other hand, $$anonymous$$ovePosition receives the position you want to move it to. So in this case, if you want to stay in place, you pass rigidbody.position.
You see the difference? The starting point for $$anonymous$$ovePosition is rigidbody.position, so when you add the delta to the position, you get the new position which works fine.
When you do the same with AddForce, it messes things up, because your starting point should be 0, not rigidbody.position.
I hope I made myself clear, anyway the fix is simple, use AddForce(delta * speed);
Your answer
Follow this Question
Related Questions
FixedUpdate vs. Update for instantaneous ForceMode's 1 Answer
Add force in the OnStateUpdate. 0 Answers
Foces only change during collision 1 Answer
making perpetual movement 1 Answer