unity旋转物体的操作

1.在限制的角度范围内进行旋转(或旋转到某个角度)

        例如绕物体的Z轴在-40°~40°之间进行旋转

float max_rotation = 40f;
float min_rotation = -40f;
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
 
Vector3 vector3 = transform.rotation.eulerAngles;
vector3.z -= horizontal * 150f * Time.deltaTime;
vector3.z = (vector3.z + 180f) % 360f - 180f;//将引擎中传入的角度规范化到-180°~180°
vector3.z = Mathf.Clamp(vector3.z, horizontal * min_rotation, -horizontal *        max_rotation);//保持vector3.z在min°~max°之间
transform.rotation = Quaternion.Euler(vector3);

注意!!!
Unity引擎中使用的欧拉角范围在0°~360°
而脚本中的角度的范围却没有这个限制
若脚本中的角度在这个范围外,Unity会在引擎内把该角度转换在这个范围内

所以当脚本中角度为**负数**或**超过**360°**时会转换为0°~360°中对应的角度

例如 在脚本执行完0° - 100°后角度为 (-)100°,但进入引擎后这个角度时就会被转换为(+)260°
若脚本从引擎中重新读取这个角度那么值也会变为(+)260°

脚本执行完0°- 400°后角度为(-)400°,但进入引擎后这个角度时就会被转换为(+)320°,若脚本从引擎中重新读取这个角度那么值也会变为(+)320°

可以使用角度规范化,将引擎中的角度规范化来规避这个问题
例如规范到-180°~180°:

vector3.z = (vector3.z + 180f) % 360f - 180f;

在开头的代码中我想让游戏物体绕Z轴在-40°到+40°之间旋转,但是因为一旦角度小于0°。引擎就会将其转换到0°~360°之间,那么角度将永远也不会小于-40°,导致无法在脚本中判断。
而在角度规范化到-180°~180°后
例如角度转到-50°,引擎中将其转换为310°,脚本接收310°后执行:310°+180°) % 360° - 180° = -50°
将其规范为-50°以此程序可以正常判断

 2.旋转指定角度

方法一: 直接干

例如绕物体Z轴旋转360°

//正转情形
 Vector3 vector3 = transform.rotation.eulerAngles;
 vector3.z += 450f * Time.deltaTime;
 if (vector3.z >= 360f)//
 {
     vector3.z = 0f;
 }
 transform.rotation = Quaternion.Euler(vector3);
//反转情形
 Vector3 vector3 = transform.rotation.eulerAngles;
 vector3.z -= 450f * Time.deltaTime;
 if (vector3.z <= 0f)
 {
     vector3.z = 0f;
 }
 transform.rotation = Quaternion.Euler(vector3);

正转时可以理解物体转到或转过360°时我们将其复原
那么反转时为旋转一周的判断条件为什么是小于0呢
前面说过Unity引擎中使用的欧拉角范围在0°~360°
那么假设第一帧物体转了-40°,那么进入到引擎中角度就会被转换成320°
所以物体在旋转过程中的角度变化为0°→-40°(脚本中)→320°(引擎中)→320°(脚本中)→······→0°(脚本和引擎中,此时已经旋转完一周)→-X°(脚本中,X>0)→(360-X)°(引擎中)
所以当脚本中的角度第二次变为负数时物体就已经旋转一周了。

方法二: 巧用计数器(推荐使用)

我们可以专门设置一个变量来记录已经旋转的角度,等旋转角度达到预期角度时停止旋转
这样我们就可以不必考虑角度的转换问题了nice~

private float rotateCount = 0f;

void rotating()
{
  Vector3 vector3 = transform.rotation.eulerAngles;
  vector3.z += 450f * Time.deltaTime;
  rotateCount += 450 * Time.deltaTime;
 
  if (rotateCount >= 360)
  {
      vector3.z = 0f;
      rotateCount = 0;
  }
  transform.rotation = Quaternion.Euler(vector3);
}

3.注意事项


在旋转完物体后,物体的局部坐标轴也会旋转
我们在使用某些方法移动物体时要注意局部坐标轴的变化
例如下面例子

我在玩家控制脚本中按空格生成了子弹

if(Input.GetKeyDown(KeyCode.Space))
{
    Instantiate(Bullet, firePoint.position, Bullet.transform.rotation);
}

并在子弹控制脚本中控制前进

void Update()
{
    transform.Translate(Vector3.forward * 10f * Time.deltaTime);
}

我预期是想让子弹朝着Z轴方向移动
但实际发现子弹却朝着Y轴方向移动
这是因为在生成子弹时我令其在X轴方向上旋转了90°
这就使Y轴替换了原来Z轴的位置
物体沿Y轴移动

在修正前进方向后恢复正常

void Update()
{
    transform.Translate(Vector3.up * 10f * Time.deltaTime);
}

猜你喜欢

转载自blog.csdn.net/m0_73957834/article/details/135548819