From “transform.png”
Setup with two wall (green and cyan) which have their own rotation different in Z axis at 30 degree.
Their direction is different, but they have the same normal at front (yes, their normal is same at front).
How should I rotate my character to follow the direction of the wall when he is climbing up, according to the normal from the collision?
I know I can do it like:
character.transform.rotation = wall.transform.rotation or
character.transform.forward = -wall.transform.forward
But I want to solve it from the collision normal, because I want the character be OK to climb up in the front, or at both side, or in the back of the wall.
From “mark.png”
This is the result of my script, it put an orange normal mark at the collision point on the wall.
See, both the wall in the front have the same normal.
The marking result at the cyan wall side is not what I want. I want it to follow the direction of the wall.
Below is my script:
void GrabAiming(Collision theCollision)
{
if (theCollision.gameObject.tag.StartsWith("Grabbable"))
{
ContactPoint contact = theCollision.contacts[0];
grabPointWork = contact.point;
grabNormalWork = contact.normal;
grabTransformAim = theCollision.gameObject.transform;
Quaternion r = Quaternion.LookRotation(-grabNormalWork);
GameObject MarkNormalClone = (GameObject)Instantiate(normalMark, grabPointWork, r);
}
}
How should I modify it?
Thank You.
first Using code tags properly - Unity Engine - Unity Discussions
then you seem to be confused as to what a normal is. It is the perpendicular outward direction of your mesh triangle. you won’t get the gameObjects rotation from a normal.
here’s a read on tangents and normals.
if i get it correctly you want your character to adapt the z rotation of your walls?
Hi,
Please let me clarify.
I want my character to rotate according to all 3 axis of the wall. And the character will face to the wall no matter he climb up
in the front, or at both side, or in the back of the wall. So I guess the collision normal should be invloved.
transform.forward = -contacts[0].normal;
and transform.rotation.z = theCollision.collider.transform.rotation.z;
I have modified my code.
void GrabAiming(Collision theCollision)
{
if (theCollision.gameObject.tag.StartsWith("Grabbable"))
{
ContactPoint contact = theCollision.contacts[0];
Vector3 grabPointWork = contact.point;
Vector3 grabNormalWork = contact.normal;
Transform grabTransformAim = theCollision.transform;
Quaternion rotationNormal = Quaternion.LookRotation(grabNormalWork);
float yAngleDifference = grabTransformAim.eulerAngles.y - rotationNormal.eulerAngles.y;
float sensitivity = 10f;
Quaternion r = Quaternion.LookRotation(-grabNormalWork);
if (Mathf.Abs(yAngleDifference) >= -sensitivity && Mathf.Abs(yAngleDifference) <= sensitivity) //Collide from forward
r.eulerAngles = new Vector3(r.eulerAngles.x, r.eulerAngles.y, -grabTransformAim.rotation.eulerAngles.z);
if (Mathf.Abs(yAngleDifference) >= (360 - sensitivity) && Mathf.Abs(yAngleDifference) <= (360 + sensitivity)) // Collide from forward
r.eulerAngles = new Vector3(r.eulerAngles.x, r.eulerAngles.y, -grabTransformAim.rotation.eulerAngles.z);
if (Mathf.Abs(yAngleDifference) >= (180 - sensitivity) && Mathf.Abs(yAngleDifference) <= (180 + sensitivity)) // Collide from back
r.eulerAngles = new Vector3(r.eulerAngles.x, r.eulerAngles.y, grabTransformAim.rotation.eulerAngles.z);
if (yAngleDifference >= (270 - sensitivity) && yAngleDifference <= (270 + sensitivity)) // Collide from right
r.eulerAngles = new Vector3(r.eulerAngles.x, r.eulerAngles.y, -grabTransformAim.rotation.eulerAngles.x);
if (yAngleDifference >= (-90 - sensitivity) && yAngleDifference <= (-90 + sensitivity)) // Collide from right
r.eulerAngles = new Vector3(r.eulerAngles.x, r.eulerAngles.y, -grabTransformAim.rotation.eulerAngles.x);
if (yAngleDifference >= (90 - sensitivity) && yAngleDifference <= (90 + sensitivity)) // Collide from left
r.eulerAngles = new Vector3(r.eulerAngles.x, r.eulerAngles.y, grabTransformAim.rotation.eulerAngles.x);
if (yAngleDifference >= (-270 - sensitivity) && yAngleDifference <= (-270 + sensitivity)) // Collide from left
r.eulerAngles = new Vector3(r.eulerAngles.x, r.eulerAngles.y, grabTransformAim.rotation.eulerAngles.x);
GameObject MarkNormalClone = (GameObject)Instantiate(normalMark, grabPointWork, r);
}
}
May be its a little bit complicated, but it at least work for my purpose. Now I can just copy the normal mark rotation to rotate the character.
Welcome if anyone can help to simplify it.
Thank You.
Improved some accuracy.
void GrabAiming(Collision theCollision)
{
if (theCollision.gameObject.tag.StartsWith("Grabbable"))
{
ContactPoint contact = theCollision.contacts[0];
Vector3 grabPoint = contact.point;
Vector3 grabNormal = contact.normal;
Transform grabTransformAim = theCollision.transform;
Quaternion rotationNormal = Quaternion.LookRotation(grabNormal);
float rotateY = grabTransformAim.eulerAngles.y - rotationNormal.eulerAngles.y;
float deviation = 10f;
Quaternion r = new Quaternion();
if (Mathf.Abs(rotateY) >= -deviation && Mathf.Abs(rotateY) <= deviation) // Collide from forward
{
r = Quaternion.LookRotation(-grabTransformAim.forward);
r.eulerAngles = new Vector3(r.eulerAngles.x, r.eulerAngles.y, -grabTransformAim.rotation.eulerAngles.z);
}
if (Mathf.Abs(rotateY) >= (360 - deviation) && Mathf.Abs(rotateY) <= (360 + deviation)) // Collide from forward
{
r = Quaternion.LookRotation(-grabTransformAim.forward);
r.eulerAngles = new Vector3(r.eulerAngles.x, r.eulerAngles.y, -grabTransformAim.rotation.eulerAngles.z);
}
if (Mathf.Abs(rotateY) >= (180 - deviation) && Mathf.Abs(rotateY) <= (180 + deviation)) // Collide from back
{
r = Quaternion.LookRotation(grabTransformAim.forward);
r.eulerAngles = new Vector3(r.eulerAngles.x, r.eulerAngles.y, grabTransformAim.rotation.eulerAngles.z);
}
if (rotateY >= (270 - deviation) && rotateY <= (270 + deviation)) // Collide from right
{
r = Quaternion.LookRotation(-grabTransformAim.right);
r.eulerAngles = new Vector3(r.eulerAngles.x, r.eulerAngles.y, -grabTransformAim.rotation.eulerAngles.x);
}
if (rotateY >= (-90 - deviation) && rotateY <= (-90 + deviation)) // Collide from right
{
r = Quaternion.LookRotation(-grabTransformAim.right);
r.eulerAngles = new Vector3(r.eulerAngles.x, r.eulerAngles.y, -grabTransformAim.rotation.eulerAngles.x);
}
if (rotateY >= (90 - deviation) && rotateY <= (90 + deviation)) // Collide from left
{
r = Quaternion.LookRotation(grabTransformAim.right);
r.eulerAngles = new Vector3(r.eulerAngles.x, r.eulerAngles.y, grabTransformAim.rotation.eulerAngles.x);
}
if (rotateY >= (-270 - deviation) && rotateY <= (-270 + deviation)) // Collide from left
{
r = Quaternion.LookRotation(grabTransformAim.right);
r.eulerAngles = new Vector3(r.eulerAngles.x, r.eulerAngles.y, grabTransformAim.rotation.eulerAngles.x);
}
GameObject MarkNormalClone = (GameObject)Instantiate(normalMark, grabPoint, r);
}
}