- Home /
Advice on keeping distance using AddForce
Hi,
I have 2 objects which both move in 3D space. I was using transform position, but I am now converting to Physix for a more realistic movement and collisions.
I have all the Vector3 positions working, and the detection of distance etc to trigger the movements. So for example if not in range, trigger code to move closer to the object until it is. The same goes if an object is too close. If it is move away until the min distance value is met.
What I am investigating before I jump into the conversion, is the best way to implement the Physics based movement.
Is there a way to AddForce in the direction of a Vector3? Most examples that I find are more focused on player control. Would it be best to have the rigidbody transform rotate in the direction of the object I want to move closer to then AddForce until in range?
The other question is how would I go about about moving in the opposite direction to move away. If the rigidbody transform is pointing at the object I want to move away from (as theorised above) can I apply a negative force to move to move in the opposite direction? Or would it just be best to invert the transform while the object is too close?
Everything is written in UnityScript.
I hope this makes sense ;)
Thanks
Paul
Hey, this probably won't cover all your questions, but here it is. I'm assu$$anonymous$$g you want an enemy to chase the player. If this works, just tell me and I'll convert this into an answer.
var enemyRigidbody : Rigidybody;
var playerTransform : Transform;
var distance : float = 3;
var speed : float = 5;
function FixedUpdate () {
var pPos : Vector3 = playerTransform.position;
var ePos : Vector3 = enemyRigidbody.transform.position;
var curDist : float = Vector3.Distance(ePos,pPos);
enemyRigidbody.AddForce(((curDist > 10)?(pPos-ePos):(ePos-pPos)).normalized*speed/*,Force$$anonymous$$ode.Force*/);
}
-- $$anonymous$$
That looks interesting $$anonymous$$, thanks for that! I will test it over the co$$anonymous$$g days, as I am in the process of converting everything else and will be doing the movement last.
Answer by fafase · Dec 03, 2012 at 01:49 PM
So you want to move an object towards a direction.
Vector3 direction = target.position - transform.position;
rigidbody.AddForce(direction*speed);
This will get your object in the direction. No need for angle compared to x-axis, teh vector indicates all that.
For the opposite direction simply revert the vector:
Vector3 direction = target.position - transform.position;
rigidbody.AddForce(-direction*speed);
See the minus sign?
Now this is goign to add force constantly so they will add up to reach warp speed. You could then cance the previous force to get a smoother effect:
Vector3 previous = new Vector3(0f,0f,0f);
void Update(){
rigidbody.AddForce(-previous*speed); //Cancel previous
Vector3 direction = target.position - transform.position;
rigidbody.AddForce(direction*speed); //Give new force
previous = direction; //Store for next round
}
In the end, you are adding F0 then next frame you add -F0 and add F1 and so on.
There might be better solution though...
This looks great fafase. I am at work at the moment, but hope to start work on the physics movement tonight when I get home. I'll post an update, vote etc when done.
By the way, I forgot one detail. The destination is not normalized. It means that at large distance, the vector is large and so is the velocity and when getting closer the vector is smaller then you get a smaller velocity. If you want the guy to move always the same velocity add:
direction.Normalize();
fafase, you should use FixedUpdate for Physics operations, but since you cancel the previous out, it shouldn't be a problem ;).
Hi fafase, I just realised that the example you gave is in C# so I am trying to convert it to UnityScript....
Got the first part done:
var direction : Vector3 = attackerStatusScript.targetFollow.position - transform.position; rigidbody.AddForce(direction*currentSpeedSetting);
Answer by DavidDebnar · Dec 03, 2012 at 01:39 PM
I made some changes to the code. I doesn't involve physics anymore, but it'd be quite easy to implement.
#pragma strict
var enemyTransform : Transform;
var playerTransform : Transform;
var distance : float = 3;//distance the enemy's going to try keep
var deadZone : float = 1;//this is some kind of offset, in this dead zone, the enemy won't move. It's used to eliminate weird behaviour. Try to set it to 0 and see what happens.
var speed : float = 5;
/*var prev : Vector3;*/
function FixedUpdate () {
var pPos : Vector3 = playerTransform.position;//position of the player
var ePos : Vector3 = enemyTransform.position;//position of the enemy
var curDist : float = Vector3.Distance(ePos,pPos);//distance between p and e
var direction : Vector3 = (curDist > distance+deadZone?pPos-ePos:((curDist < distance-deadZone)?ePos-pPos:Vector3.zero)).normalized;//the direction between p and e. Note the use of ternary operators to determine if the direction should be towards the player, from the player or 0.
/*enemyTransform.rigidbody.AddForce(-prev*speed, ForceMode.Force);*/
enemyTransform.rigidbody.AddForce(direction*speed, ForceMode.Force);//you can change the force mode, if you want different behaviour.
/*prev = direction;*/
}
--David
Hi $$anonymous$$,
Thanks but as mentioned in the original post, I am changing from transform position movement to physics based movement. This is critical for my desired end result.
I updated the code. It now uses Physics, has comments that'll hopefully give you some insight on the code. Also, if you want to eli$$anonymous$$ate the previous movement as fafas did, just remove / / form the code.
Sweet! I will try and get on to this part of my code next. I'll update as soon as I have any news etc. Thanks for the input $$anonymous$$, always appreciated, I'm giving a thumbs up to you all.
Sorry $$anonymous$$ but I opted for fafase's solution. The best I can do is give your answer an upvote. Thanks for the time you spent on it. $$anonymous$$uch appreciated.