Unity移动方法总结
在Unity3D中,有多重方式可以改变物体的坐标,实现移动的目的,其本质是每帧改变物体的position。
- 通过Transform组件移动物体
Transform组件用于描述物体在空间中的状态,它包括位置(position),旋转(rotation)和缩放(scale)。
其实所有的移动都会导致position的改变,这里所说的通过Transform组件来移动物体,指的是直接操作Transform来控制物体的位置(position)。
API:
//物体以relativeTo为参照系,根据translation的向量移动。如果relativeTo缺省将以Space.Self为默认值,还可以设置为Space.World和gameObject.transform。
function Translate (translation : Vector3, relativeTo : Space = Space.Self) : void
//相对坐标系空间:当relativeTo设置为空或者为Space.Self,表示该物体沿着自己本地坐标进行运动。当设置为Space.World,表示该物体沿着世界坐标系进行运动。
//相对其他物体坐标:当relativeTo设置为移动参考物体的gameObject.transform时,物体根据gameObject的坐标系进行相对运动。设置为Camera.main.transform时,相对主相机进行运动。
//两种形式
public void Translate(Vector3 translation, Space relativeTo = Space.Self);
public void Translate(float x, float y, float z, Space relativeTo = Space.Self);
示例:
function Update() {
//导弹相对于战斗机Fighter以Speed的速度向前运动,Vector3.forward在此时表示导弹的正前方
transform.Translate(Vector3.forward * Speed * Time.deltaTime, Fighter.transform);
}
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow)) //上移
{
transform.Translate(Vector3.up * speed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow)) //下移
{
transform.Translate(Vector3.down * speed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow)) //左移
{
transform.Translate(Vector3.left * speed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow)) //右移
{
transform.Translate(Vector3.right * speed * Time.deltaTime);
}
//使用上下方向键或者W、S键来控制前后移动
float translation = Input.GetAxis("Vertical") * speed * Time.deltaTime;
//使用左右方向键或者A、D键来控制左右旋转
float rotation = Input.GetAxis("Horizontal") * rotationSpeed * Time.deltaTime;
- 通过Rigidbody组件移动物体
Rigidbody组件用于模拟物体的物理状态,比如物体受重力影响、物体被碰撞后的击飞和通过增加物体的受力以达到物理效果等等。
注意,关于Rigidbody的调用均应放在FixedUpdate方法中,该方法会在每一次执行物理模拟前被调用。
(1)Rigidbody.velocity
设置刚体速度可以让物体运动并且忽略静摩擦力,这会让物体快速从静止状态进入运动状态。
void Start () {
gameObject.GetComponent<Rigidbody>().velocity = Vector3.forward * MoveSpeed;
}
(2)Rigidbody.AddForce/AddForcePosition
给刚体添加一个方向的力,这种方式适合模拟物体在外力的作用下的运动状态。
//第一个例子
void Start(){
rd = this.GetComponent<Rigidbody>();//给变量赋值刚体对象
}
void FixedUpdate() {
float h = Input.GetAxis("Horizontal"); //得到键盘左右控制
float v = Input.GetAxis("Vertical"); //得到键盘上下控制
rd.AddForce(new Vector3(h,0,v)*force);//对物体施加力
}
//另一个例子
void Update(){
if(Input.GetMouseButton(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray, out hit))
{
if(hit.collider.name =="Cube")
{
Vector3 direction = hit.transform.position - obj.transform.position;
//发射炮弹
obj.GetComponent<Rigidbody>().AddForceAtPosition(direction, hit.transform.position,ForceMode.Impulse); //三个参数,分别为力、位置、力的方式
}
}
}
}
(3)Rigidbody.MovePosition
刚体受到物理约束的情况下,移动到指定点position。
void FixedUpdate() {
//让刚体rb向前运动Time.deltaTime距离
rb.MovePosition(transform.position + transform.forward * Time.deltaTime);
}
- 通过Vector3方法移动物体
Vector3既可以表示三维空间中的一个点,也可以表示一个向量。
Lerp为线性插值,Slerp为球形插值,MoveTowards在Lerp的基础上增加了限制最大速度功能。当需要从指定A点移动到B点时,可以考虑时候这些方法。
(1)Vector3.Lerp()
API:
static function Lerp(transform.position, target, MoveSpeed * Time.deltaTime) : Vector3;
示例:
void Start () {
public float MoveSpeed = 0.1f;
public Vector3 target = new Vector3(20, transform.position.y, 20);
}
void Update () {
gameObject.transform.localPosition = Vector3.Lerp(transform.position, Target, MoveSpeed * Time.deltaTime);
}
(2)Vector3.MoveTowards()
MoveTowards增加了限制最大速度功能。
API:
static function MoveTowards(current: Vector3, target: Vector3, maxDistanceDelta: float) : Vector3;
示例:
void Start () {
public float MoveSpeed = 0.1f;
public Vector3 target = new Vector3(20, transform.position.y, 20);
}
void Update () {
gameobject.transform.position = Vector3.MoveTowards(transform.position, target, MoveSpeed * Time.deltaTime);
}
(3)Vector3.SmoothDamp()
该方法是可以平滑的从A逐渐移动到B点,并且可以控制速度,最常见的用法是相机跟随目标。
API:
//在smoothTime的时间间隔内以当前的移动速度currentVelocity,从current移动到target
//需要注意的是currentVelocity值一般在开始时指定为零向量,每次调用该方法时该方法会自动给currentVelocity赋值
static function SmoothDamp (current : Vector3, target : Vector3, ref currentVelocity : Vector3, smoothTime : float) : Vector3
示例:
void Start () {
public Transform target;
public float smoothTime = 0.3F;
private Vector3 velocity = Vector3.zero;
}
void Update () {
//定义一个目标位置在目标变换的上方并且在后面
Vector3 targetPosition = target.TransformPoint(new Vector3(0, 5, -10));
//平滑地移动摄像机朝向目标位置
gameobject.transform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref velocity, smoothTime);
}
- 使用CharacterController组件控制角色移动
Unity使用CharacterController(角色控制器)来控制角色骨骼运动,包括移动、跳跃以及各种动作。CharacterController比较复杂。
CharacterController用于控制第一人称或第三人称角色的运动,使用这种方式可以模拟人的一些行为,比如限制角色爬坡的最大斜度,步伐的高度等。
CharacterController.SimpleMove:
用于模拟简单运动,并且自动应用重力,返回值表示角色当前是否着地。
CharacterController.Move:
模拟更复杂的运动,重力需要通过代码实现,返回值表示角色与周围的碰撞信息。