问题
I have a c# script that can rotate a gun to point at the cursor. I needed the gun to flip to the other side of the player when the cursor is above or below the player. I solved this problem with the following script: (inside the update function)
Vector2 weaponDistance = Camera.main.ScreenToWorldPoint(Input.mousePosition) - weapon.transform.position;
float weaponRotation = Mathf.Atan2 (weaponDistance.y, weaponDistance.x) * Mathf.Rad2Deg;
if (weaponRotation < 90f && weaponRotation > -90f)
{
Debug.Log("Facing Right");
weapon.transform.localPosition = leftWeaponPosition;
weapon.transform.localRotation = Quaternion.Euler (0f, 0f, weaponRotation);
}
else
{
Debug.Log("Facing Left");
weapon.transform.localPosition = rightWeaponPosition;
weapon.transform.localRotation = Quaternion.Euler (180f, 0f, -weaponRotation);
}
However, there is a glitch where you can't shoot directly underneath the player. Here is the result. I managed to partly fix the glitch behaviour with the following code: (inside update function)
Vector2 weaponDistance = Camera.main.ScreenToWorldPoint(Input.mousePosition) - weapon.transform.position;
float weaponRotation = Mathf.Atan2 (weaponDistance.y, weaponDistance.x) * Mathf.Rad2Deg;
if (weaponRotation < 90f && weaponRotation > -90f)
{
if (weaponRotation < 65f && weaponRotation > -65f)
{
Debug.Log("Facing Right");
weapon.transform.localPosition = leftWeaponPosition;
}
weapon.transform.localRotation = Quaternion.Euler (0f, 0f, weaponRotation);
}
else
{
if ((weaponRotation > 115f && weaponRotation < 155f) || (weaponRotation > -155f && weaponRotation < -115f))
{
Debug.Log("Facing Left");
weapon.transform.localPosition = rightWeaponPosition;
}
weapon.transform.localRotation = Quaternion.Euler (180f, 0f, -weaponRotation);
}
This time some of the glitching was reduced, and the weapon sprite flipped at the bottom of the screen without going to the other side of the player. However, the glitching effect still happened if the cursor was closer/on top of the player, and it also resulted in weird rotation behaviours. This was the result.
I'm trying to find a solution where the glitchy behaviour is eliminated, you can shoot directly below the player, and the weapon doesn't rotate at the bottom of the player as shown in the second gif example. Thanks!
回答1:
Try to make the constraints smaller and you can decide the side with the mouse position. Cut your screen in half and there is your decision then adjust the angle.
回答2:
There are two ways I managed to solve the problem. The first is just changing the weaponDistance variable, so that instead of finding the difference between the cursor and the weapon, find the difference between the cursor and the player. So it's basically replacing:
Vector2 weaponDistance = Camera.main.ScreenToWorldPoint(Input.mousePosition) - weapon.transform.position;
with
Vector2 weaponDistance = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
This stops the glitch, and you can also shoot directly above the player. However, there is still some weird behaviour where the gun flips before moving to the other side of the player. Another one is when the cursor is on the player the gun points outwards. I fixed the first issue by rewriting the logic of the code. In the following code, the gun always rotates towards the cursor. It checks how close the cursor is to the player, and if the cursor is close enough to the weapon, it rotates the weapon without switching the side. This prevents the glitch. However, this has the gun rotate without flipping if the cursor is close to the player. Meaning that the gun will rotate over the player's sprite in some instances.
weaponDistance = Camera.main.ScreenToWorldPoint(Input.mousePosition) - weapon.transform.position;
weaponRotation = Mathf.Atan2(weaponDistance.y, weaponDistance.x) * Mathf.Rad2Deg;
if (isFacingRight)
{
if (weaponRotation < 115f && weaponRotation > -115f)
{
weapon.transform.localPosition = rightWeaponPosition;
weapon.transform.localRotation = Quaternion.Euler(0f, 0f, weaponRotation);
}
else
{
if (Vector2.Distance(transform.localPosition, Camera.main.ScreenToWorldPoint(Input.mousePosition)) < 0.8f)
weapon.transform.localRotation = Quaternion.Euler(0f, 0f, weaponRotation);
else
isFacingRight = false;
}
}
else
{
if ((weaponRotation > 65f && weaponRotation < 180f) || (weaponRotation > -180f && weaponRotation < -65f))
{
weapon.transform.localPosition = leftWeaponPosition;
weapon.transform.localRotation = Quaternion.Euler(180f, 0f, -weaponRotation);
}
else
{
if (Vector2.Distance(transform.localPosition, Camera.main.ScreenToWorldPoint(Input.mousePosition)) < 0.8f)
weapon.transform.localRotation = Quaternion.Euler(0f, 0f, weaponRotation);
else
isFacingRight = true;
}
}
The next option is using the same logic, but utilises the original fix where weaponDistance is calculated using the player's position rather than the weapon's position. However, if the cursor is on the player, the gun will point outwards from the player's position rather than from the gun's position to the cursor. Here is the code:
weaponDistance = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
weaponRotation = Mathf.Atan2(weaponDistance.y, weaponDistance.x) * Mathf.Rad2Deg;
if (isFacingRight)
{
if (weaponRotation < 115f && weaponRotation > -115f)
{
weapon.transform.localPosition = rightWeaponPosition;
weapon.transform.localRotation = Quaternion.Euler(0f, 0f, weaponRotation);
}
else
isFacingRight = false;
}
else
{
if ((weaponRotation > 65f && weaponRotation < 180f) || (weaponRotation > -180f && weaponRotation < -65f))
{
weapon.transform.localPosition = leftWeaponPosition;
weapon.transform.localRotation = Quaternion.Euler(180f, 0f, -weaponRotation);
}
else
isFacingRight = true;
}
来源:https://stackoverflow.com/questions/62243913/rotating-a-gun-while-flipping-it-in-unity