I have been searching for a long while now and i did nto find any anwser to my issue so i thought lets ask for help.
I have a turret [Turret and gun is one mesh, no seperate rotation] and i want it to rotate towards the targets.
This is pretty easy and not a problem, but i want to be able to place the turret anywhere i want.
For example on the walls/roofs/ diagonal areas.
This changed the situation, as the rotation takes the world coordinates instead of the local rotation.
For example if the turret is placed on the wall it should have its base against the wall at all times, instead it rotates like it was on a flat surface.
As shown in the image below, the turret should also have a limit of how far up and down it can aim.
The turrets can rotate all around but should be limited to the up and down movement/aiming.
And all this should be done in the local rotation as the it should stick to the [wall/ground/vehicle]
I hope anyone can help me out on this or point me in the right direction.
Calculate the rotation with tanks’ body as upwards,
Slerp over time to the direction,
Constrain the local xz angles after aligning the desired rotation.
Attach this to the root where you control the tank. This way your tower rotates only on its local Y, which will calculate the angle to face the target.
hey, i thought i share my solution as well.
its kinda next level because it rotates on 2 axis without a lerp on a fixed rotationspeed takin its local rotation into a count.
it took me a long while to figure this one out, because like you said its a kinda difficult topic, without any hints on how to do it exactly. so here you go.
using UnityEngine;
**
public class RotateToTarget : MonoBehaviour
{
public Transform gun; // the part of the Turret you want to rotate UP/Down "the barrel for example"
public float turretDegreesPerSecond = 45.0f; // this is the left right rotation speed (put the script on this object)
public float gunDegreesPerSecond = 45.0f; // this is the rotation speed (its for the gun or the part you want to rotate Up and Down)
**
// those are not to modify
private Quaternion qTurret,qGun,qGunStart;
private Transform trans;
void Start()
{
trans = transform;
qGunStart = gun.transform.localRotation;
}
public void RotateAtTarget(Transform f) // "f" is the focuspoint or "target". you can call this function from another script "if(target) -> RotateToTarget(TargetFocus);"
{
float distanceToPlane = Vector3.Dot(trans.up, f.position - trans.position);
Vector3 planePoint = f.position - trans.up * distanceToPlane;
qTurret = Quaternion.LookRotation(planePoint - trans.position, transform.up);
transform.rotation = Quaternion.RotateTowards(transform.rotation, qTurret, turretDegreesPerSecond * Time.deltaTime);
Vector3 v3 = new Vector3(0.0f, distanceToPlane, (planePoint - transform.position).magnitude);
qGun = Quaternion.LookRotation(v3);
gun.localRotation = Quaternion.RotateTowards(gun.localRotation, qGun, gunDegreesPerSecond * Time.deltaTime);
}
Edit: I know see that this doesn’t fully address your problem. This only constrains the the turret to not aim into the wall/surface, and doesn’t place a restriction relative the tangent of the surface you are attached to (the left most and right most example in your image). It would probably be better to take a bit of a different approach to do that, rather than just extending my solution. I may edit this with a more relevant solution, or I may just leave this as is in case it’s still useful to people anyway.
–
Hopefully the comments in the code sample explain it well enough so I don’t have to explain it again (not sure about answer guidelines here though, since this is my first).
In case it’s not clear, the “normal” should be the normal of the surface the turret is on, in my test code I just set it to be the initial forward direction, so the turret will be constrained to [maxAngle] degrees from the original forward direction.
using UnityEngine;
using System.Collections;
public class Turret : MonoBehaviour {
public Transform target;
public float maxAngle;
Vector3 normal;
void Start () {
normal = transform.forward;
}
void Update () {
//Get the vector pointing from this transform to the target position
Vector3 toTarget = target.position - transform.position;
Debug.DrawRay(transform.position, toTarget, Color.blue);
//Find the angle between the normal and the vector towards the target
float angle = Vector3.Angle(normal, toTarget.normalized);
//Find the axis which we would rotate around to go from our normal toward the target
Vector3 axis = Vector3.Cross(normal, toTarget.normalized);
Debug.DrawRay(transform.position, axis, Color.green);
//Rotate the normal around our found axis, clamping the angle to our defined maxAngle
Vector3 targetDir = Quaternion.AngleAxis(Mathf.Clamp(angle, 0, maxAngle), axis) * normal;
Debug.DrawRay(transform.position, targetDir, Color.red);
//Rotate our transform to face the new target direction
Quaternion targetRotation = Quaternion.LookRotation(targetDir);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, 1 * Time.deltaTime);
}
}