官方文档
链接如下:
Unity官方文档的 Transform.up 链接
测试过程
- 测试方法:提取刚体,坐标系,Space模式为参数,使用上下左右表示物体移动和旋转,测试不同情况的位移和旋转,Console选择Collapse模式
测试脚本 TestScript 如下:
using System;
using UnityEngine;
public enum Coordinate
{
TransUp,
VectorUp
}
public enum MovePattern
{
SetRigidVelocity,
SetTranslate
}
public enum SpaceSet
{
SelfSpace,
WorldSpace
}
public class TestScript : MonoBehaviour
{
public MovePattern MyMovePattern;
public Coordinate MyCoordinate;
public SpaceSet MySpace;
public Rigidbody Rigidbody;
public float Speed = 10f;
void Update()
{
// 首先看移动模式,在使用刚体,且模式为 Dynamic 时,不要使用 Transform.Translate 或者 MovePosition 等直接位移的函数,
// 直接位移是违背物理规律的,Velocity 将不会随位移而改变,必须受力或者直接调整 Velocity数值 才能改变 Velocity
SelectTestFunction(MyMovePattern, MyCoordinate, MySpace);
}
private void SelectTestFunction(MovePattern myMove, Coordinate myCo, SpaceSet mySpaceSet)
{
#region 刚体 & Transform.Up & Self
if (myMove == MovePattern.SetRigidVelocity && myCo == Coordinate.TransUp && mySpaceSet == SpaceSet.SelfSpace)
{
Debug.Log("本次测试模式:刚体 Dynamic ,使用坐标 Transform.Up , 旋转的 Space 模式为 Self ");
// 如果没有按任何键位,每帧给速度归零
if (!Input.anyKey)
{
Rigidbody.velocity = Vector3.zero;
}
// 上下左右移动
if (Input.GetKey(KeyCode.UpArrow))
{
Rigidbody.velocity = transform.up * Speed;
}
if (Input.GetKey(KeyCode.DownArrow))
{
Rigidbody.velocity = -transform.up * Speed;
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(new Vector3(0, 0, 1) * Time.deltaTime * Speed, Space.Self);
}
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(new Vector3(0, 0, -1) * Time.deltaTime * Speed, Space.Self);
}
}
#endregion
#region 刚体 & Transform.Up & World
if (myMove == MovePattern.SetRigidVelocity && myCo == Coordinate.TransUp && mySpaceSet == SpaceSet.WorldSpace)
{
Debug.Log("本次测试模式:刚体 Dynamic ,使用坐标 Transform.Up , 旋转的 Space 模式为 World ");
// 如果没有按任何键位,每帧给速度归零
if (!Input.anyKey)
{
Rigidbody.velocity = Vector3.zero;
}
// 上下左右移动
if (Input.GetKey(KeyCode.UpArrow))
{
Rigidbody.velocity = transform.up * Speed;
}
if (Input.GetKey(KeyCode.DownArrow))
{
Rigidbody.velocity = -transform.up * Speed;
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(new Vector3(0, 0, 1) * Time.deltaTime * Speed, Space.World);
}
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(new Vector3(0, 0, -1) * Time.deltaTime * Speed, Space.World);
}
}
#endregion
#region 刚体 & Vector.Up & Self
if (myMove == MovePattern.SetRigidVelocity && myCo == Coordinate.VectorUp && mySpaceSet == SpaceSet.SelfSpace)
{
Debug.Log("本次测试模式:刚体 Dynamic ,使用坐标 Vector3.Up , 旋转的 Space 模式为 Self ");
// 如果没有按任何键位,每帧给速度归零
if (!Input.anyKey)
{
Rigidbody.velocity = Vector3.zero;
}
// 上下左右移动
if (Input.GetKey(KeyCode.UpArrow))
{
Rigidbody.velocity = Vector3.up * Speed;
}
if (Input.GetKey(KeyCode.DownArrow))
{
Rigidbody.velocity = -Vector3.up * Speed;
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(new Vector3(0, 0, 1) * Time.deltaTime * Speed, Space.Self);
}
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(new Vector3(0, 0, -1) * Time.deltaTime * Speed, Space.Self);
}
}
#endregion
#region 刚体 & Vector.Up & World
if (myMove == MovePattern.SetRigidVelocity && myCo == Coordinate.VectorUp && mySpaceSet == SpaceSet.WorldSpace)
{
Debug.Log("本次测试模式:刚体 Dynamic ,使用坐标 Vector3.Up , 旋转的 Space 模式为 World ");
// 如果没有按任何键位,每帧给速度归零
if (!Input.anyKey)
{
Rigidbody.velocity = Vector3.zero;
}
// 上下左右移动
if (Input.GetKey(KeyCode.UpArrow))
{
Rigidbody.velocity = Vector3.up * Speed;
}
if (Input.GetKey(KeyCode.DownArrow))
{
Rigidbody.velocity = -Vector3.up * Speed;
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(new Vector3(0, 0, 1) * Time.deltaTime * Speed, Space.World);
}
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(new Vector3(0, 0, -1) * Time.deltaTime * Speed, Space.World);
}
}
#endregion
#region Tranlate & Transform.Up & Self
if (myMove == MovePattern.SetTranslate && myCo == Coordinate.TransUp && mySpaceSet == SpaceSet.SelfSpace)
{
Debug.Log("本次测试模式:SetTranslate ,使用坐标 Transform.Up , 旋转的 Space 模式为 Self ");
// 上下左右移动
if (Input.GetKey(KeyCode.UpArrow))
{
transform.Translate(transform.up * Time.deltaTime * Speed);
}
if (Input.GetKey(KeyCode.DownArrow))
{
transform.Translate(-transform.up * Time.deltaTime * Speed);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(new Vector3(0, 0, 1) * Time.deltaTime * Speed, Space.Self);
}
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(new Vector3(0, 0, -1) * Time.deltaTime * Speed, Space.Self);
}
}
#endregion
#region Tranlate & Transform.Up & World
if (myMove == MovePattern.SetTranslate && myCo == Coordinate.TransUp && mySpaceSet == SpaceSet.WorldSpace)
{
Debug.Log("本次测试模式:SetTranslate ,使用坐标 Transform.Up , 旋转的 Space 模式为 World ");
// 上下左右移动
if (Input.GetKey(KeyCode.UpArrow))
{
transform.Translate(transform.up * Time.deltaTime * Speed);
}
if (Input.GetKey(KeyCode.DownArrow))
{
transform.Translate(-transform.up * Time.deltaTime * Speed);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(new Vector3(0, 0, 1) * Time.deltaTime * Speed, Space.World);
}
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(new Vector3(0, 0, -1) * Time.deltaTime * Speed, Space.World);
}
}
#endregion
#region Tranlate & Vector3.Up & Self
if (myMove == MovePattern.SetTranslate && myCo == Coordinate.VectorUp && mySpaceSet == SpaceSet.SelfSpace)
{
Debug.Log("本次测试模式:SetTranslate ,使用坐标 Vector3.Up , 旋转的 Space 模式为 Self ");
// 上下左右移动
if (Input.GetKey(KeyCode.UpArrow))
{
transform.Translate(Vector3.up * Time.deltaTime * Speed);
}
if (Input.GetKey(KeyCode.DownArrow))
{
transform.Translate(-Vector3.up * Time.deltaTime * Speed);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(new Vector3(0, 0, 1) * Time.deltaTime * Speed, Space.Self);
}
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(new Vector3(0, 0, -1) * Time.deltaTime * Speed, Space.Self);
}
}
#endregion
#region Tranlate & Vector3.Up & World
if (myMove == MovePattern.SetTranslate && myCo == Coordinate.VectorUp && mySpaceSet == SpaceSet.WorldSpace)
{
Debug.Log("本次测试模式:SetTranslate ,使用坐标 Vector3.Up , 旋转的 Space 模式为 World ");
// 上下左右移动
if (Input.GetKey(KeyCode.UpArrow))
{
transform.Translate(Vector3.up * Time.deltaTime * Speed);
}
if (Input.GetKey(KeyCode.DownArrow))
{
transform.Translate(-Vector3.up * Time.deltaTime * Speed);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(new Vector3(0, 0, 1) * Time.deltaTime * Speed, Space.World);
}
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(new Vector3(0, 0, -1) * Time.deltaTime * Speed, Space.World);
}
}
#endregion
}
}
测试场景物体布局如下图:
测试结果
当脚本控制的物体没有父对象时
刚体速度和Translate对比
相同点:
- 旋转的Space模式不会影响任何结果,没有父物体的情况下,Space.World 和 Space.Self 是一样的,这很正常
- Transform.up 实际上是 Scene 窗口中 Local 模式下的绿色轴(Y轴)的方向
- Vector3.up 则是世界坐标Y轴,Scene 窗口中 Global 模式下的绿色轴,无论物体是否旋转,都只会在Y轴上移动,不会改变X的值
不同点:
- 在Transform.up方向上,当物体旋转后,刚体会沿着这个Y轴移动,但是Translate不是Y轴方向,会有偏移,实际情况如下图 :
当脚本控制物体有父对象,且有旋转和偏移量时
父对象沿Z轴每秒旋转30°,子物体Y轴偏移2个单位
刚体速度运动
Transform.up
- 当自身没有额外旋转时,Transform.up 实际上是 Scene 窗口中 Local 模式下的绿色轴(Y轴)的方向,Space.World 和 Space.Self 对此没有影响(至少总体的运动轨迹是一样的),但是最终方向都会受到父对象的旋转影响,而有偏移。
- 当自身再旋转90°时,也是和上面一样
Vector3.up
- 当自身没有额外旋转时,还是在世界坐标Global的Y轴上,Space.World 和 Space.Self 对此没有影响(至少总体的运动轨迹是一样的),最终位置会受到父对象的旋转影响。
- 当自身再旋转90°时,也是和上面一样
Translate位移
Transform.up
- 无论是否有额外旋转,Space.World 和 Space.Self 都会有影响,且不好判断具体移动行为
Vector3.up
- 无论是否有额外旋转,还是还是在世界坐标Global的Y轴上,Space.World 和 Space.Self 对此没有影响(至少总体的运动轨迹是一样的),最终位置会受到父对象的旋转影响。
父对象Z轴旋转60°,子物体Y轴偏移2个单位
刚体速度运动
Transform.up
- 当自身没有额外旋转时,Transform.up 实际上是 Scene 窗口中 Local 模式下的绿色轴(Y轴)的方向,Space.World 和 Space.Self 对此没有影响,只改变Transform的Y值,X值虽然会变化,但是为极小数,或者是错误数字,如下图所示,过程中可能刚好出现0,或者是极小数
文章来源:https://www.toymoban.com/news/detail-774325.html
- 当自身再旋转90°时,X和Y轴的值都会改变,如果只拖动Position的Y值,最终方向为Scene 窗口中 Local 模式下的绿色轴(Y轴)的方向反向旋转90°。
Vector3.up
- 当自身没有额外旋转时,还是在世界坐标Global的Y轴上直接移动
- 当自身再旋转90°时,也是和上面一样
Translate位移
Transform.up
- 无论是Space.World 或者 Space.Self,且是否旋转90°,都不是Scene窗口中任意一个坐标轴的方向
Vector3.up
- 此时无论是Space.World 或者 Space.Self,都是Scene 窗口中 Local 模式下的绿色轴(Y轴)的方向移动,即Position的X值不变,只变化Y值,
- 自身旋转90°之后,在Scene窗口中查看,依旧是 Local 模式下的绿色轴(Y轴)的方向移动,但是实际Position的X和Y值都会改变
测试总结
- 开发过程中尽量避免以下情况:
- 子物体和父物体都有旋转角度,需要开发者计算实际角度
- 子物体和父物体都是持续旋转的,无法使用简单的计算得出最终结果
- 子物体和父物体既有旋转又有位移,没必要,此种情况应该是可以优化的
- 开发过程中尽量保持只有一个值是随时间变化的。
- 虽然官方文档中编写Transform.up的解释为:The green axis of the transform in world space。经过测试后可以理解为物体自身的Transform的Y轴方向。
- 根据以上结果,如果使用了刚体,速度方向为Transform.up时,通常可以达到物体自身的Y轴方向,Space优先使用World。
- 特殊情况是使用Translate方法位移时,自身没有旋转的情况下,采用Vector3.up的方向可以达到只改变Position的Y值的方法。
- 以上仅仅为简单测试,得出的结果不是非常精准的,具体项目中的位移和旋转可能更复杂,情况也可能不一样。根据目前的结果来看,笔者认为在遇到此类情况时,优先采用刚体速度进行位移,且选择Space.World,如果不符合实际情况再调整尝试。
- 如果有大佬进行过测试且能准确的描述最终运动轨迹,请留下评论指教,不胜感激。
使用案例参考
2D旋转武器及升级详解文章来源地址https://www.toymoban.com/news/detail-774325.html
到了这里,关于关于 Unity 的 Transform.up 和 Vector3.Up 的测试的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!