简介 在unity3d中,有多种方式可以改变物体的坐标,实现移动的目的,其本质是每帧修改物体的position。
Transform 组件用于描述物体在空间中的状态,它包括 位置(position), 旋转(rotation)和 缩放(scale)。 其实所有的移动都会导致position的改变,这里所说的通过Transform组件来移动物体,指的是直接操作Transform来控制物体的位置(position)。
该方法可以将物体从当前位置,移动到指定位置,并且可以选择参照的坐标系。 当需要进行坐标系转换时,可以考虑使用该方法以省去转换坐标系的步骤。
public function Translate(translation: Vector3, relativeTo: Space = Space.Self): void;
缺点:无 优点:有一定的惯性感,同样8向平滑,
使用Horizontal与Vertical 1 2 3 4 5 6 7 8 9 10 11 12 void transMove_GetAxis (){ float h = Input.GetAxis("Horizontal" ) * speed * Time.deltaTime; float v = Input.GetAxis("Vertical" ) * speed * Time.deltaTime; Vector3 move = new Vector3(h, 0 , v); transform.Translate(move); }
使用forward,back,left,right 同样为transform.Translate()方法, 不过是将Input GetKey()改为GetAxis(), 官方给出的示例:public static float GetAxis (string axisName); 如果将轴映射到鼠标,该值会有所不同,并且不会在-1…1 的范围内。 此时,该值为当前鼠标增量乘以轴灵敏度。 通常,正值表示鼠标向右/向下移动,负值表示鼠标向左/向上移动。该值与帧率无关 使用该值时,您无需担心帧率变化问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void transMove_keycode() { // 如果我们按下W if (Input.GetKey(KeyCode.W)) { transform.Translate(Vector3.forward * speed * Time.deltaTime); } if (Input.GetKey(KeyCode.A)) { transform.Translate(Vector3.left * speed * Time.deltaTime); } if (Input.GetKey(KeyCode.S)) { transform.Translate(Vector3.back * speed * Time.deltaTime); } if (Input.GetKey(KeyCode.D)) { transform.Translate(Vector3.right * speed * Time.deltaTime); } }
有时重新赋值position能更快实现我们的目标。(快)
方法 :transform.position与transform.localPosition的加减 缺点:整体移动观感较为僵硬,设置Key键代码重复率高,输入受帧率影响 优点:8向移动较为平滑,I/O反馈及时手感还不错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 void transMove_position (){ if (Input.GetKey(KeyCode.W)) { transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y, transform.localPosition.z + speed * Time.deltaTime); } if (Input.GetKey(KeyCode.A)) { transform.localPosition = new Vector3(transform.localPosition.x - speed * Time.deltaTime, transform.localPosition.y, transform.localPosition.z); } if (Input.GetKey(KeyCode.S)) { transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y, transform.localPosition.z - speed * Time.deltaTime); } if (Input.GetKey(KeyCode.D)) { transform.localPosition = new Vector3(transform.localPosition.x + speed * Time.deltaTime, transform.localPosition.y, transform.localPosition.z); } }
通过vector3来移动 Vector3.Lerp, Vector3.Slerp, Vector3.MoveTowards Vector3 既可以表示三维空间中的一个点,也可以表示一个向量。这三个方法均为插值方法, Lerp为线性插值,Slerp为球形插值, MoveTowards在Lerp的基础上增加了限制最大速度功能。 当需要从指定A点移动到B点时,可以考虑时候这些方法。
Lerp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public Transform startPoint;//起始点 public Transform endPoint;//终止点 private float startTime;//开始运行时间 private float btDistance;//点间距 void start(){ startTime=Time.time; btDistance = Vector3.Distance(startPoint.position, endPoint.position); } void v3Move_lerp() { // v3-lerp线性插值 float moved = (Time.time - startTime) * speed;//运行开始时间乘以速度已走路程 float fractionOfBtDistance = moved / btDistance; //百分比 =已经走过的路程/ 两点之间的距离—??% //令物体现在的位置 = 线性插值计算出一定速度下物体在两点间长度的百分之多少 transform.position = Vector3.Lerp(startPoint.position, endPoint.position, fractionOfBtDistance); }
Slerp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public Transform startPoint;//起始点 public Transform endPoint;//终止点 private float startTime;//开始运行时间 private float btDistance;//点间距 void start(){ startTime=Time.time; btDistance = Vector3.Distance(startPoint.position, endPoint.position); } void v3Move_Slerp() { // The center of the arc Vector3 center = (startPoint.position + endPoint.position) * 0.5F; // move the center a bit downwards to make the arc vertical center -= new Vector3(0, 1, 0); // Interpolate over the arc relative to center Vector3 riseRelCenter = startPoint.position - center; Vector3 setRelCenter = endPoint.position - center; // The fraction of the animation that has happened so far is // equal to the elapsed time divided by the desired time for // the total journey. float fracComplete = (Time.time - startTime) / btDistance; transform.position = Vector3.Slerp(riseRelCenter, setRelCenter, fracComplete); transform.position += center; }
Vector3.SmoothDamp 该方法是可以平滑的从A逐渐移动到B点,并且可以控制速度,最常见的用法是相机跟随目标。
1 2 3 4 5 6 7 8 public Transform target; private Vector3 vt = Vector3.zero; public float smoothTime = 5; void v3Move_SmoothDamp() { transform.position = Vector3.SmoothDamp(transform.position, target.position, ref vt, smoothTime); }
通过Rigidbody组件移动物体 Rigidbody组件用于模拟物体的物理状态,比如物体受重力影响,物体被碰撞后的击飞等等。
注意:关于Rigidbody的调用均应放在FixedUpdate方法中,该方法会在每一次执行物理模拟前被调用。
Rigidbody.velocity 设置刚体速度可以让物体运动并且忽略静摩擦力,这会让物体快速从静止状态进入运动状态。(有惯性)
1 rb.velocity += new Vector3(0, 0, speed);
Rigidbody.AddForce 给刚体添加一个方向的力,这种方式适合模拟物体在外力的作用下的运动状态。
1 2 3 4 5 6 void rbMove3() { // 直接给物体一个力 // 这种方法比起移动更适合去做一些炮弹、子弹、冷兵器对物体造成的冲击效果 rb.AddForce(new Vector3(0, 0, 10)); }
Rigidbody.MovePosition ` 刚体受到物理约束的情况下,移动到指定点。
1 2 3 4 5 6 7 8 void rbMove2() { // 逻辑上看成不断高频传送 float h = Input.GetAxis("Horizontal") * speed * Time.deltaTime; //获取水平方向的输入键 float v = Input.GetAxis("Vertical") * speed * Time.deltaTime; //获取垂直方向的输入键 // update 中卡 放到fixedUpdete中 rb.MovePosition(transform.position + new Vector3(h, 0, v)); }
通过CharacterController组件移动物体 CharacterController用于控制第一人称或第三人称角色的运动,使用这种方式可以模拟人的一些行为,比如限制角色爬坡的最大斜度,步伐的高度等。
CharacterController.SimpleMove 用于模拟简单运动,并且自动应用重力,返回值表示角色当前是否着地。
CharacterController.Move 模拟更复杂的运动,重力需要通过代码实现,返回值表示角色与周围的碰撞信息。
【波仔羔训练营-03】Unity的9种移动方式,看似简单实则…_哔哩哔哩_bilibili
Unity Movement Tutorials (catlikecoding.com)
(转)Unity3D中移动物体位置的几种方法 - 哆啦任意门 - 博客园 (cnblogs.com)
【完结】Unity基础教程系列——Unity物体运动11篇 - 知乎 (zhihu.com)