Reputation: 1438
im trying to move between a path made from different objects. I apply a constant speed with Translate() and Rotating with the perpendicular vector from the object on the right using Raycasting
Although it turns , is it does not rotate fast enough to fully turn and moves out of the path.
Any ideas how to fix this? Or some other way to implement it?
any help will be appreciated
image to help visualize: Raycast and Rotation image
void Update()
{
RaycastHit hit;
if (!Physics.Raycast(transform.position, Vector3.right, out hit))
return;
MeshCollider meshCollider = hit.collider as MeshCollider;
if (meshCollider == null || meshCollider.sharedMesh == null)
return;
Mesh mesh = meshCollider.sharedMesh;
Vector3[] normals = mesh.normals;
int[] triangles = mesh.triangles;
Vector3 n0 = normals[triangles[hit.triangleIndex * 3 + 0]];
Vector3 n1 = normals[triangles[hit.triangleIndex * 3 + 1]];
Vector3 n2 = normals[triangles[hit.triangleIndex * 3 + 2]];
Vector3 baryCenter = hit.barycentricCoordinate;
Vector3 interpolatedNormal = n0 * baryCenter.x + n1 * baryCenter.y + n2 * baryCenter.z;
interpolatedNormal = interpolatedNormal.normalized;
Transform hitTransform = hit.collider.transform;
interpolatedNormal = hitTransform.TransformDirection(interpolatedNormal);
Vector3 targetDir = Vector3.Cross(interpolatedNormal, Vector3.up); // Get the perpendicular vector
Vector3 newDir = Vector3.RotateTowards(transform.forward, targetDir, 20f, 0f);
transform.rotation = Quaternion.LookRotation(newDir); // Rotate Object
transform.Translate(0,0,0.2f); // Constant Speed
Debug.DrawRay(transform.position, perp,Color.red);
}
Upvotes: 0
Views: 1753
Reputation: 5035
First thing: you seem not to be using data from HitInfo struct - and believe it or not it already contains a .normal Vector3 member, calculated during the raycast (or lazily calculated when requested, I am not sure but it makes no difference), it's best to use it rather than roll your own, simpler and less error prone (your manual finding of the normal looks correct neverless, I haven't tried it though)
Second thing: your last line has a Quaternion.Lerp with t=0.05 which means for each new rotation, you are still taking 95% of the original rotation, which is pretty darn slow rotation indeed. Try something in the range of Time.deltaTime (which is rougly an equivalent of getting close within a second)
Third thing: for rotation its better to use Slerp rather than Lerp, unless you are realt concerned about performance, which doesn't seem to be an issue considering the rest of the code.
Fourt thing: instead of hardcoding linear and rotation speed, try to use multiplies of Time.deltaTime, this way they won't be framerate dependend (as they currently are)
Fifth thing: I have a feeling you shouldn't be setting your target rotation based on normal at current position. The way you are doing it now your rotation lags behind - you should be raycasting from a position one step in the future from your current position, so you know what rotation to take so it is correct by the time you make that step. Currently you set target a future rotation to a rotation correct now, which will lag a frame. Alternatively you could just move the translate step to the top of the loop, the transform will update and the rest should flow as it does.
Finally, your image link doesn't work.
I hope that helps at all
Upvotes: 1
Reputation: 765
I don't think this is a good method, but it works for me. Maybe this can help you.
public float fixedDist = 2.0f;
void WallDetect() {
RaycastHit hit;
if (!Physics.Raycast(transform.position, transform.TransformPoint(Vector3.right) - transform.position, out hit))
return;
Vector3 perp = Vector3.Cross(hit.normal, Vector3.up);
Vector3 targetDir = Vector3.Project(transform.forward, perp).normalized;
Vector3 currentDir = transform.TransformPoint (Vector3.forward) - transform.position;
RaycastHit hit2;
if (Physics.Raycast (transform.position, -hit.normal, out hit2)) {
Vector3 fixedPos = hit2.point + hit.normal * fixedDist;
Vector3 predictPos = fixedPos + targetDir;
transform.position = Vector3.MoveTowards (transform.position, predictPos, 0.01f);
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation (predictPos - transform.position), 0.05f);
}
}
Upvotes: 0