Currently I am facing an issue when I pitch my ship down and then turn it to some side the turret rotation will get bugged.
I am not sure how to fix this. I have been reading about polar coordinate spaces from 3D Math Primer for Graphics and Game development and came to the conclusion that in order to rotate the turrets stand I have to change heading and pitch the gun up and down.
It all works correctly until I pitch my ship and then change its heading…
This should not occur if the turret is parented to the ship and the rotation is handled using only local rotation for the turret itself.
Also you will want to use only quaternions, not eulers, as the latter can’t represent all rotations in 3d space. You seem to be using math even (atan2, asin, ewww, ugh) when that aiming could easily be achieved with a lookat target.
Even if you need to make some adjustments to have imprecise aim you’d first look at target, then randomly offset the rotation using Random’s unitSphere and multiplying that with the rotation quaternion (multiply quaternions equals adding the rotations).
But now I am wondering why did that work with transform.parent.InverseTransformPoint.
@CodeSmile
I want to be able to move the stand of my turret only around its UP axis and the gun itself only around its RIGHT axis. So the gun can only pitch up and down. I am not sure how to do that with LookRotation.
Still having issues with this… I simply don’t get unity rotations. I changed from polar coordinate calculation now to this code:
public void AimAt(Vector3 target)
{
TurretBaseRotation(target);
TurretGunRotation(target);
}
private void TurretBaseRotation(Vector3 target)
{
// Get aim position in parent gameobject local space in relation to aim position world space
Vector3 targetPositionInLocalSpace = transform.parent.InverseTransformPoint(target);
// Set "aimPoint" Y position to zero, since this is horizontal rotation n because we dont need it
targetPositionInLocalSpace.y = 0.0f;
// Store limit value of the rotation
Vector3 limitedRotation = targetPositionInLocalSpace;
// limit turret horizontal rotation according to its rotation limit, so how much to the left and how much to the right can it rotate
// Rotate vector around a Cross(Vector3.forard, targetPosInLocalSpace)
Vector3 localSpace = _turretBase.InverseTransformPoint(target);
if (localSpace.x >= 0.0f)
limitedRotation = Vector3.RotateTowards(Vector3.forward, targetPositionInLocalSpace, Mathf.Deg2Rad * maxMinHorizontalRot.x, float.MaxValue);
else
limitedRotation = Vector3.RotateTowards(Vector3.forward, targetPositionInLocalSpace, Mathf.Deg2Rad * maxMinHorizontalRot.y, float.MaxValue);
//Get direction
Vector3 right = limitedRotation;
if (transform.localScale.x < 0.0f)
right.x *= -1.0f;
Quaternion whereToRotate = Quaternion.LookRotation(right);
// Rotate the turret
_turretBase.transform.localRotation = Quaternion.RotateTowards(_turretBase.transform.localRotation, whereToRotate, RotateSpeed * Time.deltaTime);
}
private void TurretGunRotation(Vector3 target)
{
// Get aim position in barrel gameobject local space in relation to aim position world space
Vector3 targetPositionInLocalSpace = _turretBase.transform.InverseTransformPoint(target);
if(isBaseSwitched)
targetPositionInLocalSpace = _gun.transform.InverseTransformPoint(target);
// Set "TargetPositionInLocalSpace" X position to zero, since this is vertical rotation n because we dont need it
targetPositionInLocalSpace.x = 0.0f;
// Store limit value of the rotation
Vector3 limitedRotation = targetPositionInLocalSpace;
// limit turret vertical rotation according to its rotation limit, so how much up and down can it rotate
if (targetPositionInLocalSpace.y >= 0.0f)
limitedRotation = Vector3.RotateTowards(Vector3.forward, targetPositionInLocalSpace, Mathf.Deg2Rad * maxMinVerticalRot.x, float.MaxValue);
else
limitedRotation = Vector3.RotateTowards(Vector3.forward, targetPositionInLocalSpace, Mathf.Deg2Rad * maxMinVerticalRot.y, float.MaxValue);
Vector3 up = limitedRotation;
if (transform.localScale.y < 0.0f)
up.y *= -1.0f;
//Get direction
Quaternion whereToRotate = Quaternion.LookRotation(up);
// Rotate the barrel
_gun.transform.localRotation = Quaternion.RotateTowards(_gun.localRotation, whereToRotate, RotateSpeed * Time.deltaTime);
Vector3 gunTransformPos = _gun.transform.position;
Vector3 gunForward = _gun.transform.forward;
if(isBaseSwitched)
{
gunTransformPos = _turretBase.transform.position;
gunForward = _turretBase.transform.forward;
}
Vector3 fromTo = (target - gunTransformPos).normalized;
if (Vector3.Dot(fromTo, gunForward) < 0.9f)
{
_cantAim = true;
}
else
_cantAim = false;
}
The gun seem to be aiming but to a massive offset. It is not aiming at the center of the ship.
void Update()
{
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
if (!Physics.Raycast(ray, out RaycastHit hit, maxRayDistance))
hit.point = ray.origin + ray.direction * maxRayDistance; // if nothing below the cursor then we just look in the cursor's general direction
RotateTurret(hit.point);
RotateCannon(hit.point);
}
void RotateTurret(Vector3 targetPosition)
{
turret.forward = Vector3.Slerp(turret.forward, targetPosition - turret.position, turretSpeed * Time.deltaTime);
turret.localEulerAngles = new Vector3(0, turret.localEulerAngles.y, 0); // only allow yaw rotation
}
void RotateCannon(Vector3 targetPosition)
{
cannon.forward = Vector3.Slerp(cannon.forward, targetPosition - cannon.position, cannonSpeed * Time.deltaTime);
cannon.localEulerAngles = new Vector3(Mathf.Clamp(-Mathf.DeltaAngle(cannon.localEulerAngles.x, 0), -60, 30), 0, 0); // only allow pitch rotation and clamp it
}