2
\$\begingroup\$

I am currently trying to rotate the weapons of a spaceship towards the mouse position, but in order to avoid the collision of projectiles with the ship I want to limit the angle the weapon can turn.

I've tried doing this:

    Vector3 mousePos = Input.mousePosition;
    float range = 100.0f;
    float rotStep = 0.1f;

    Vector3 positionOnScreen = Camera.main.ScreenToWorldPoint(mousePos + Vector3.forward * range);

    Vector3 targetDir = positionOnScreen - transform.position;
    Vector3 newDir = Vector3.RotateTowards(transform.forward, targetDir, rotStep * Time.deltaTime, 0.0f);

    Quaternion lookRot = Quaternion.LookRotation(newDir);

    float xAngle = lookRot.eulerAngles.x;
    if (xAngle > 10 && xAngle <= 180)
    {
        xAngle = 10;
    }
    else if (xAngle < 350 && xAngle > 180)
    {
        xAngle = 350;
    }

    float yAngle = lookRot.eulerAngles.y;
    if (yAngle > 10 && yAngle <= 180)
    {
        yAngle = 10;
    }
    else if (yAngle < 350 && yAngle > 180)
    {
        yAngle = 350;
    }

    float zAngle = lookRot.eulerAngles.z;
    if (zAngle > 10 && zAngle <= 180)
    {
        zAngle = 10;
    }
    else if (zAngle < 350 && zAngle > 180)
    {
        zAngle = 350;
    }

    lookRot.eulerAngles =new Vector3(xAngle, yAngle, zAngle);
    transform.rotation = lookRot;

The problem here is that I don't know how to limit the rotation angle since it's not the same depending on the ship rotation (for example if it's (0, 0 , 0) or (-90, -90, -90)). I've tried using transform.localRotation too, but still happens the same. Do you how could I limit the rotation regardless of the ship rotation?

\$\endgroup\$
2

2 Answers 2

0
\$\begingroup\$

I think you should use the LocalRotation. because from what I see you are only checking the rotation of the cannons in world space, not locally.

\$\endgroup\$
3
  • \$\begingroup\$ As I said in my question, I've already tried using transform.LocalRotation, but the results where not what I wanted. I will try again, just in case I did something wrong. Regarding the issue of projectiles colliding with the ship I've solved It by using Spherecasts from the weapon and checking if they collide with their same ship. I know it's not the exact solución to this, but maybe will help somebody \$\endgroup\$
    – Hector
    Oct 18, 2019 at 11:23
  • \$\begingroup\$ ah im sorry my bad i missed that. what you could maybe do is compare the rotation of the cannons to the rotation of the ship and if it goes past a set limit like if(cannon.rotation.y <= ship.rotation.y + 45 && cannon.rotation.y >= ship.rotation.y + -45 ) \$\endgroup\$ Oct 18, 2019 at 12:06
  • \$\begingroup\$ It seems that indeed I wasn't using the right LocalRotation. I tried with Quaternion localLookRot = lookRot * Quaternion.Inverse(transform.parent.rotation); But the results were not right. \$\endgroup\$
    – Hector
    Oct 18, 2019 at 16:46
0
\$\begingroup\$

Here's a way to do this with local rotation, expressing our limits symmetrically about our initial orientation to avoid the problems described in this answer.

public float yawRange;
public float pitchRange;

// Cache our initial rotation in Start, to use it as the center of our range.
Quaternion _neutralRotation;

void Start() {
    _neutralRotation = transform.localRotation;
}

void Update() {
    // The first part proceeds as before.
    Vector3 mousePos = Input.mousePosition;
    float range = 100.0f;
    float rotStep = 0.1f;

    Vector3 positionInWorld = Camera.main.ScreenToWorldPoint(mousePos + Vector3.forward * range);

    // Then we transform into our parent's local space, to get an offset from our local position.
    Vector3 positionInParent = transform.parent.InverseTransformPoint(positionInWorld);

    Vector3 targetDir = positionInParent - transform.localPosition;
    
    Vector3 newDir = Vector3.RotateTowards(transform.forward, targetDir, rotStep * Time.deltaTime, 0.0f);

    // We convert this into a rotation space where Euler angles (0, 0, 0) describe the orientation 
    // at the center of our range, so we get symmetric behaviour in all directions from here.
    Vector3 relativeToCenter = (Quaternion.Inverse(_neutralRotation) * newDir).normalized;

    // We extract the Euler angles that describe this direction, and clamp them.    
    float yaw = Mathf.Atan2(relativeToCenter.x, relativeToCenter.z) * Mathf.Rad2Deg;
    float pitch = Mathf.Asin(relativeToCenter.y) * Mathf.Rad2Deg;;

    yaw = Mathf.Clamp(yaw, -yawRange, yawRange);
    pitch = Mathf.Clamp(pitch, -pitchRange, pitchRange);

    // We apply this clamped rotation relative to our center, relative to our parent.
    transform.localRotation = _neutralRotation * Quaternion.Euler(pitch, yaw, 0);
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .