Entonces, tengo una nave con un "punto duro" adjunto en el que se pueden colocar armas. Una vez colocados, apuntan a la posición del mouse y tienen un rango de rotación restringido: Ver aquí
El rango de rotación se basa en minAngle y maxAngle, y se calcula mediante eulerAngles.z de la ranura del punto fijo principal, más/menos el modificador de ángulo (en este caso, 20). Tuve que hacer un extraño vudú rotacional (ver OneEightyToThreeSixty() en el fragmento de código) para que el ángulo de visualización del mouse coincidiera con el mismo formato que minAngle/maxAngle.
el ángulo entraba como -180 -> 180 grados en lugar de 0 -> 360 como la rotación del punto duro. Escribió un método para convertirlo a 360 durante el tiempo de ejecución.
He reescrito este guión más veces de las que puedo contar, pero finalmente me encontré con este problema.
Como puede ver, para 270 grados de la rotación de 360, la orientación y las restricciones funcionan perfectamente. Pero en el cuarto superior derecho de la rotación, todo se vuelve loco.
He probado tantas implementaciones diferentes, pero todas parecen tener este problema constante. No puedo entender lo que me estoy perdiendo. Aquí está el código:
public class HardpointSlot : MonoBehaviour { public HardpointController ship; public GameObject hardpoint; public float minAngle; public float maxAngle; public float angle; public float offsetAngle; public bool switched; void Update() { AimAtMouse(); } public void AimAtMouse() { Vector3 dir = Input.mousePosition - Camera.main.WorldToScreenPoint(transform.position); angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg; minAngle = (transform.eulerAngles.z - 20) + 90f; maxAngle = (transform.eulerAngles.z + 20) + 90f; angle = OneEightyToThreeSixty(angle); if (angle < minAngle) { angle = minAngle; } else if (angle > maxAngle) { angle = maxAngle; } hardpoint.transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward); } public float OneEightyToThreeSixty(float angle) { float newAngle = 0f; if (angle >= 0 && angle <= 180) { return angle; } else { return newAngle = 360 + angle; } } }Tan rápido resumen:
¿Algunas ideas? ¿Me estoy perdiendo algo muy obvio?
Adoptaría otro enfoque, haciendo uso de Vector3.SignedAngle para obtener el ángulo desde la dirección neutral hasta la dirección del mouse. Luego, useMathf.Clamp para sujetarlo entre los límites y luego Quaternion.AngleAxis para crear la dirección resultante. Finalmente, use Quaternion.LookRotation para asignar la rotación a la transformación del punto fijo:
public class HardpointSlot : MonoBehaviour { [SerializeField] HardpointController ship; [SerializeField] GameObject hardpoint; [SerializeField] float minAngle; [SerializeField] float maxAngle; [SerializeField] float angle; void Update() { AimAtMouse(); } public void AimAtMouse() { Vector3 dir = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position; // flatten z axis dir.z = 0; Vector3 neutralDir = transform.up; float angle = Vector3.SignedAngle(neutralDir, dir, Vector3.forward); minAngle = -20f; maxAngle = 20f; angle = Mathf.Clamp(angle, minAngle, maxAngle); // rotate neutral dir by the clamped angle dir = Quaternion.AngleAxis(angle, Vector3.forward) * neutralDir; // set the rotation so that local up points in dir direction // and local forward in global forward hardpoint.transform.rotation = Quaternion.LookRotation(Vector3.forward, dir); } }