Unity3D - Unexpected results from Vector3.Reflect - unity3d

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);

Related

SpriteKit / Swift ApplyImpulse in current node direction

unfortunately I have a supposedly simple "problem".
The Situation:
I want to code my first "space shooter ... or something like that" with SpriteKit
So I have (currently :-)):
One Node,
Three Buttons: 1 button for turning left, 1 for right & 1 for acceleration.
Turning is solved. Using impulse for giving the node a new direction
...The problem is :
Acceleration.
I also use the impulse for getting the node "forward". But it don't want to move forward in the direction in which the node was turned.
My ideas solving the Problem:
using the radiant of the zRotation, calculating the degrees, figuring out the CGVector via using "rad * cos(degree)" / "rad * sin(degree)".
result
the node is not moving in the direction it should. especially if the rad is a negative figure ... :-D
So question is: How can I set an impulse / velocity for moving my future spaceship forward to the set direction .
thanks for your help!
greetings
Sascha
The below code is taken from this video, where they are making a bullet go in the same direction as the space ship is pointing.
The adjusted rotation is required if your sprites texture orientation is pointing up, whereas SpriteKit uses the right direction as 0 rotation.
let speed: CGFloat = 1
let adjustedRotation = zRotation + (CGFloat.pi / 2)
let dx = speed * cos(adjustedRotation)
let dy = speed * sin(adjustedRotation)
spaceship?.physicsBody?.applyImpulse(CGVector(dx: dx, dy: dy))

Unity3d Billiard/Pool aiming issue

I'm trying to calculate what angle to hit a pool ball and predict where ball will go to..
I thought target ball should move within a normal direction.. but it moves
on totally different direction
RaycastHit2D hit = Physics2D.CircleCast(cue.position, _radius, dir, 100f, ~(ignoreLayer));
if (hit.collider != null)
{
Debug.DrawRay(hit.collider.transform.position, -1f * hit.normal,
Color.green, Time.fixedDeltaTime);
}
Here is result:
Set velocity
rb.velocity = dir * force;
Result:
How to find exact move direction, Thanks
Edit:
I have tried Double Radius Casting this works only half way.. only when ray inside inner circle
I suppose this is just a limitation of the physics engine, which is optimized for speed and use in games, and is not so exact.
Trying this myself in a simple 2D scene, I found that if I set the friction to 0.01 and the bounciness to 1.0, it works the way I would expect. (in Unity 2020.1)
In the small sample scene I added, there is a ball aiming at another so that the resulting angle should be 45 degrees. And after setting the phyics-mat to the properties with friction 0.01 and bounciness 1.0, the resulting angle is as expected.
With the default-mat I get the same behaviour you described.
Did you forget to assign the physics materials?
Have you single-stepped to the point of contact and checked if the aiming is correct?
my sample project trying this

vector math in unity to avoid obstacles

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

Unity Quaternion.LookRotation Not Working

I am working with Unity 5 and making the logic of some NPC characters that will walk through a plane randomly and with animations. When the characters reaches the destination, a new target is generated after 3 seconds. The animator works fine and so does the pathfinding. Now I want the model to face forward the correct direction.
I am having a weird issue were the model does not seem to follow any conventional relation. First, it works almost fine, since the rotation is almost the one expected. The second path is deviated and after the third one is almost backwards. Is like if somehow the model were calculating the rotation related to something I have no clue.
This is part of the code I am using:
Vector3 look = targetPosition - transform.position;
Quaternion targetRotation = Quaternion.LookRotation(look.normalized,Vector3.up);
Quaternion newRotation = Quaternion.Lerp(transform.rotation, targetRotation, turnSmoothing * Time.deltaTime);
rb.MoveRotation(newRotation);
I have also tried setting the transform Euler angles, and this code:
float turnAngle = Mathf.Atan2( look.z, look.x ) * Mathf.Rad2Deg;
float smoothAngle = Mathf.LerpAngle( transform.eulerAngles.y, -turnAngle, rb.velocity.magnitude * Time.deltaTime );
rb.MoveRotation( Quaternion.Euler( 0, smoothAngle, transform.eulerAngles.z ));
Always the same result. Am I missing something? I have read about the root motion in the animator but I have disabled animations and the patter persists. Also, the model seems to have the correct Z direction set. Its driving me nuts!!
Any input is appreciated.
First of all, i want to say that you should be using Quaternion.Slerp for rotation interpolations. Lerp is a more linear interpolation wheras Slerp will make rotations seem more natural. Although i do not believe this to be the issue here.
I don't ever really use Quaternion functions, so to me your code looks fine. I can however suggest to maybe try an approach using Vector3.RotateTowards or even transform.Rotate, they should be able to get you what you are trying to accomplish here.
EDIT: I just noticed you are using rigidBody.MoveRotation after your custom Lerp interpolation. Unity API states:
Use Rigidbody.MoveRotation to rotate a Rigidbody, complying with the
Rigidbody's interpolation setting.
So, RigidBody already has its own interpolation it will try to do against your custom interpolation. The issue may lie there, because you are not setting the rotation explicitly. Try just inserting your target direction into MoveRotation and rigidbody will try and get you there. It is not an immediate rotation.
Check that your look vector is not near zero length. If you feel a root animation overwrites your rotation use simple cubes instead of NPC characters. To debug your look direction use targetRotation instead of newRotation. You can render debug lines to visualize the line NPC to target. Good luck.
I have not enough reputation points to write this as comment.

How to move object based on its angle?

I am using Unity3d with mono develop(c#).
My object is Arrow.It gets Random Angel at starting.When i click on arrow ,it should be move like gun shooting some Point.How to achieve this?can any one help?
The forward Vector3 on the Transform belonging to your GameObject describes which direction is forward for the object.
An example given on the linked page is rigidbody.velocity = transform.forward * 10;. So if you were to put that line of code in your FixedUpdate function then your GameObject would move forward at a velocity of 10 * framerate.