Here’s my entire modified SmoothLookAt script.
However, something’s wrong and the turret wont rotate “fully” when the “local mode” is enabled.
var target : Transform;
var local : boolean = true;
var damping = 6.0;
var smooth = true;
var xMin : float = 0;
var xMax : float = 0;
var yMin : float = 0;
var yMax : float = 0;
var zMin : float = 0;
var zMax : float = 0;
var clampX : boolean = false;
var clampY : boolean = false;
var clampZ : boolean = false;
var x : boolean = true;
var y : boolean = true;
var z : boolean = true;
private var xA : float;
private var yA : float;
private var zA : float;
var debug : boolean = false;
var debugBox : GameObject;
@script AddComponentMenu("Camera-Control/Smooth Look At")
function LateUpdate () {
if (target) {
if (smooth)
{
if (local) {
xA = transform.localEulerAngles.x;
zA = transform.localEulerAngles.y;
zA = transform.localEulerAngles.z;
// Look at and dampen the rotation
var rotation : Vector3 = Quaternion.LookRotation(transform.InverseTransformPoint(target.position)).eulerAngles;
if (clampX) rotation.x = Clamp(rotation.x, xMin, xMax);
if (clampY) rotation.y = Clamp(rotation.y, yMin, yMax);
if (clampZ) rotation.z = Clamp(rotation.z, zMin, zMax);
transform.localRotation = Quaternion.Slerp(transform.localRotation, Quaternion.Euler(rotation), Time.deltaTime * damping);
if (!x) transform.localEulerAngles.x = xA;
if (!y) transform.localEulerAngles.y = yA;
if (!z) transform.localEulerAngles.z = zA;
}
else {
xA = transform.localEulerAngles.x;
zA = transform.localEulerAngles.y;
zA = transform.localEulerAngles.z;
// Look at and dampen the rotation
var rotation2 : Vector3 = Quaternion.LookRotation(target.position-transform.position).eulerAngles;
if (clampX) rotation2.x = Clamp(rotation2.x, xMin, xMax);
if (clampY) rotation2.y = Clamp(rotation2.y, yMin, yMax);
if (clampZ) rotation2.z = Clamp(rotation2.z, zMin, zMax);
//transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(rotation2), Time.deltaTime * damping);
transform.rotation = Quaternion.Euler(rotation2);
if (!x) transform.localEulerAngles.x = xA;
if (!y) transform.localEulerAngles.y = yA;
if (!z) transform.localEulerAngles.z = zA;
}
}
else
{
// Just lookat
transform.LookAt(target);
}
}
if (debug) Debug.Log(transform.InverseTransformPoint(target.position).ToString()+" "+transform.worldToLocalMatrix.MultiplyPoint3x4(target.position));
if (debugBox) debugBox.transform.localPosition = transform.InverseTransformPoint(target.position);
}
function Start () {
if (xMin < 0) xMin = 360-Mathf.Abs(xMin);
if (yMin < 0) yMin = 360-Mathf.Abs(yMin);
if (zMin < 0) zMin = 360-Mathf.Abs(zMin);
if (xMin == 0 xMax == 0) clampX = false;
else clampX = true;
if (yMin == 0 yMax == 0) clampY = false;
else clampY = true;
if (zMin == 0 zMax == 0) clampZ = false;
else clampZ = true;
// Make the rigid body not change rotation
if (rigidbody)
rigidbody.freezeRotation = true;
}
function Clamp (val : float, min : float, max : float) : float {
if (val < min val > 180) return min;
else if (val > max val < 180) return max;
else return val;
return val;
}
You wanted me to elaborate a bit on the InverseTransformDirection here, so here I am. =)
The reason why I said that a Direction would be better is because unlike LookAt the LookRotation requires a Direction to face instead of a point to face. In your script supplying a point works probably because your turret is in the center (0,0,0) of the parents coordinate system, so a point in that space is therefore also a direction for the turret. If you move your turret away from the center it would no longer face the correct direction, but rather face an imaginary point offset by the same amount the turret has been offset from the center.
Calculating the correct local direction with InverseTransformDirection will solve that problem as we also take into account the position of the turret.