I am trying to make my character to avoid obstacles while moving.
the target is defined on click and character moves to it on every frame by updating transform.position (so no physics here).
every obstacle has collider and character has trigger. on TriggerStay event of the character I have managed to get some info about the contact point:
Vector3 point = other.ClosestPointOnBounds(transform.position);
Vector3 dist = point - transform.position;
and the best thing I came to is to:
Vector3 perp = Vector3.Cross(transform.forward, dist.normalized);
float dir = Vector3.Dot(perp, transform.up);
transform.position -= transform.right * dir;
but it does not work as I was expected. actually it does not work at all.
how to correct character position, So it appears to be smoothly deflected of obstacle, while moving to the target?
EDIT: here is the screenshot
white rays show the direction of contacts, so they are multiple.
what i want is that the character can avoid obstacles while moving to his target.
for now i came to new idea:
float correction = Vector3.Dot(transform.right, dist.normalized) / 10;
transform.position += transform.right * correction;
it somewhat works as i want, but character is constantly jumping from one place to another. don't know how to fix this.
also tried correcting direction of movement by substracting the vector of contact from vector of movement, but character is also moves jerky and rotates stupidly.
You can try something like:
Vector3 perp = Vector3.Cross(transform.forward, other.transform.up);
transform.position -= perp.normalized * other.bounds.size.x / 2f;
You seem to not use Vector3.Cross proper way. Read here about it: Unity3D docs link
Related
I want to make a game in Unity where a person can pick a surface and walk along all of its sides. I've gotten the movement working, but when I rotate my character around certain angles of corner the character flips 180 degrees in some direction (it's different depending on the corner) and when I want them to move forward the game freaks out as they keep going across the corner over and over again, turning, and going forward across the border again. I'd strongly prefer to keep my character from doing these 180-degree spins and I think it's just due to a flaw in the formula I use to calculate the angle they stand at (which is based around making sure their transform.up is aligned with the point they are meant to stand on). Any ideas on how I fix this rotation formula in Update?
Current formula:
angle = Vector3.Angle(closestPoint, transform.position);
var t = transform;
var angles = t.eulerAngles;
t.LookAt(GravityWellPoint.transform.position);
t.RotateAround(transform.position, -transform.right, 90);
transform.rotation = Quaternion.Lerp(transform.rotation, t.rotation, Time.deltaTime * 5.0f);
Got this solution from a different forum and it worked:
So this is actually not a trivial problem to solve. If you try doing it by calculating angles etc you almost always end up with a similar spinning/flipping issue in certain positions. You can solve it by doing the maths, but its a pain. I usually like to use Quaternion.LookRotation to solve this kind of problem. you can feed in the desired forward and upward directions. So you can calculate the desired upward direction like so:
Vector3 targetUpDirection = transform.position - GravityWellPoint.transform.position;
Then you would do the following:
transform.rotation = Quaternion.LookRotation(transform.forward,targetUpDirection);
but this doesnt quite work. LookRotation will ensure that your forward direction is exactly the one you specify, and then chooses the upward direction that's the closest possible to the one you specify. So you will find that we don't actually manage to point our object upwards in the way we intended. However, there is an unintuitive solution we can apply instead.
Calculate the upward direction in the same way, then use LookRotation to rotate our object to point its forward face in exactly our desired upwards direction, and its upward face towards the current forward direction:
Vector3 targetUpDirection = transform.position - GravityWellPoint.transform.position;
transform.rotation = Quaternion.LookRotation(targetUpDirection, transform.forward);
Now our object is aligned perfectly, but is the wrong way up. We can use LookRotation again, to swap the upwards and forwards directions:
transform.rotation = Quaternion.LookRotation(transform.up, transform.forward);
For clarity/TLDR here is the complete code for my solution:
//find the desired up direction:
Vector3 targetUpDirection = transform.position - other.position;
//face forward/upward via black magic
transform.rotation = Quaternion.LookRotation(targetUpDirection, transform.forward);
transform.rotation = Quaternion.LookRotation(transform.up, transform.forward);
So, my map is sideways so I can use tilemaps. But, I have this enemy, works good, BUT it looks at me sideways as if I am not sideways, so the transform.lookAt will not work with sideways maps unless I modify the input by a certain number, but I tried and cannot get it to work. Any suggestions?
Here is the lookAt code:
Vector3 lookAt = PlayerController.instance.transform.position;
lookAt.y = transform.position.y;
transform.LookAt(lookAt);
I am not sure if I understand it correctly, but I propably had the same problem some time ago. You can make it work if you use transform.Forward or Quaternion rotation
You can simply assign a value to Transform.right or Transform.up according to your needs like e.g.
Vector2 direction = PlayerController.instance.transform.position - transform.position;
transform.right = direction;
I'm trying to create a game where a ball is launched off from a circle, much like a cannon, but it can be launched into any direction, 360ยบ because the circle which the ball is attached to can rotate. So, I was thinking of using Rigidbody2D.AddForce() but I'm not sure how to define the direction I want the force to be applied. I want it to be the direction perpendicular to the ball/player's movement but I don't know how to define that. Thanks for any help! :)
If you get the direction that the ball is travelling (as say degrees) you can add a certain angle to that and use the angle to determine the force that needs to be applied.
I'm assuming that the ball/player has no ridged body, if it does then you can just grab the direction directly. Also since your using circle to describe the spawned shape i'm going to assume your working in 2D.
Vector3 lastPosition;
void Update()
{
//launch the ball before updating the last position
lastPosition = transform.position;
}
Vector3 launchDirection()
{
Vector3 ballDirection = transform.position - lastPosition;
float angle = Mathf.Atan2(ballDirection.x, ballDirection.y) * Mathf.Rad2Deg;
//the direction should be perpendicular to direction of movement
float angle += 90;
return new Vector2(Mathf.Cos(angle), Mathf.Sin(angle));
}
I haven't ran the code in unity but it looks like it should work. Basically to get the direction you store the last position and compare it to the current direction to work out the delta (if your using a ridged body to move around then grab the direction from that instead) then use atan2 to get the angle. To make the launch direction perpendicular to the ball I added 90 degrees (you might want -90 depending on what side you need the circle to launch from). Now that we have the angle that you want the ball to shoot out from, use that with Sin and Cos to get the XY of the angle.
There you have it that will get you the direction perpendicular to movement, you your using 3 dimensions it's basically the same maths just with a few numbers thrown in to pad the return value.
Oh if your object always faces the direction of movement transform.right also works :P
I'm making a 3D game. One feature I want is 'classic' bouncing projectiles where bullets etc richocet off of surfaces. The issue I'm having is that my code works fine on some surfaces but not others. I've recorded a 15 second video to illustrate:
You tube vid
In the example the normals on the walls to the left are facing -Z and facing Z to the right. The walls are identical models and their normals are all correctly pointing outwards. You can see that the shot correctly bounces off one set of walls but not the other.
The code I'm currently using in OnCollision() is:
transform.LookAt(Vector3.Reflect(transform.position - startPosition, contact.normal.normalised));
Where the Vector3 startPosition is assigned when first firing the projectile and on each bounce. The rest of the code is simple stuff which would have no effect on this issue apart perhaps from in FixedUpdate where I do this to propel the projectile forward:
rigidbody.AddForce(transform.forward * speed);
I've tried the following which all give identical results:
Vector3 velocity = transform.forward;
velocity = 2 * (Vector3.Dot(velocity, Vector3.Normalize(contact.normal))) * Vector3.Normalize(contact.normal) - velocity; //Following the formula v' = 2 * (v . n) * n - v
transform.LookAt(velocity);
transform.LookAt(Vector3.Reflect(rb.velocity, contact.normal));
transform.LookAt(Quaternion.AngleAxis(180, contact.normal) * transform.forward * -1);
I've also tried using the rigidbody but I'm not sure how to proceed there:
rigidbody.AddTorque(Vector3.Reflect(rigidbody.velocity, contact.normal.normalized),ForceMode.Impulse);
Any idea what could be going wrong? Thanks.
Just putting the answer in the right place to be used by people with the same problem.
Solution was to assign the Reflect to a Vector3 during the collision then in FixedUpdate use that vector in the rb.AddForce like:
target = Vector3.Reflect(transform.forward, contact.normal.normalized);
rb.AddForce(target.normalized * projSpeed);
I have 2 AI game objects which are both capsules. Considering the first capsule AI is named X and the second capsule AI is named Y, I try to make Y move away from X (escape from him) while X is chasing Y (following him). I have no idea how to do that, I would appreciate a direction.
I tried to do what's written here, but they both move through walls even though they have capsule collider, I tried to do this:
http://forum.unity3d.com/threads/getting-objects-to-move-away-from-my-users-gameobject.142468/
but they only move in one direction and through walls.
Vector3 position = transform.position;
Vector3 targetPosition = target.transform.position;
Vector3 direction = position - targetPosition;
transform.position += direction * 2.0f * Time.deltaTime;`
You are moving them with transform.Translate. Moving the transform means "Put the object at the given position regardless of environment". If you want them to interact, you need to either use the CharacterController component and its methods or a rigidbody component and move it with force.