unity3d俯视角简易移动控制脚本及其易错点小分享
Posted viko_cake
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity3d俯视角简易移动控制脚本及其易错点小分享相关的知识,希望对你有一定的参考价值。
涉及方法:
-
本文分别采用了 ‘collider+rigidbody’ / ‘character controller’ 两种方式共四种情况来分享
-
在代码中input采用unity基本的“Horizontal”+“Vertical”输入获取(unity新的那个input system用过包但还没自己实际了解过嘿嘿(●ˇ∀ˇ●))
-
如果是collider+rigidbody的话,使用的是rigidbody的MovePosition()方法
如果是character controller的话使用的是该控制器的simplemove函数(对应还有一个move函数,区别在于simplemove在被调用时将使物体具备重力,move函数则和translate相似。)
-
对于鼠标控制方向的情况通过raycast+getpoint方法获取当前主摄像机与鼠标产生的射线找到与平面的交点,然后使用transform组件的LookAt方法调整朝向。
【使用character controller】准备:
- 在unity中创建好基本的平面和胶囊作为场景和角色(蓝色为z轴,代表transform.forward,即正面)
- 为平面添加collider(带2d的是2D项目使用的组件),为胶囊(角色)添加character controller(新建的胶囊会自带一个collider1,在添加character controller后会自带另一个collider2,所以可以将collider1删掉)
【使用character controller】编写move脚本:
第一种情况:角色移动方向与角色朝向一致:
一些细节和注意事项都写在代码注释中辣~
using UnityEngine;
/**
* 功能:角色移动控制[角色移动时永远朝正面]
*
*/
public class move : MonoBehaviour
//速度变量
public float speed;
//定义角色控制器
public CharacterController cc;
void Start()
//组件cc变量
cc = transform.GetComponent<CharacterController>();
//速度赋值
speed = 10;
void Update()
//调用移动方法
move_by_cc();
void move_by_cc()
//水平方向的输入获取(即A-D键或←→键)
float x = Input.GetAxisRaw("Horizontal");
//垂直方面的输入获取
float z = Input.GetAxisRaw("Vertical");
/* GetAxis()的返回值初始为0,在-1到1之间变化,对应的GetAxisRaw()则不会变化,直接返回1或-1 */
/*上面的input使用GetAxis()时在松开按键后角色会继续移动一小部分距离,会产生一种“冰面滑动”的效果,
使用GetAxisRaw()的话则即按即动,即松即停*/
if (Mathf.Abs(x)>0.1f || Mathf.Abs(z) > 0.1f)
//移动方向
Vector3 toward_dir = new Vector3(x, 0, z);
//角色朝向与移动方向一致
transform.LookAt(transform.position + toward_dir);
//不同于move函数,这里以秒为单位不能*Time.deltatime,不然会无法移动
cc.SimpleMove(transform.forward * speed);
第二种情况:角色移动方向可以不与角色朝向一致(键盘控制移动,鼠标控制朝向):
一些细节和注意事项都写在代码注释中辣~
using UnityEngine;
/**
* 功能:角色移动控制[键盘控制移动,鼠标控制朝向]
*
*/
public class move2 : MonoBehaviour
//速度变量
public float speed;
//定义角色控制器
public CharacterController cc;
//摄像机
public Camera viewCamera;
void Start()
//组件cc变量
cc = transform.GetComponent<CharacterController>();
//速度赋值
speed = 5;
//当前主摄像机
viewCamera = Camera.main;
void Update()
//调用移动方法
move_by_cc();
void move_by_cc()
/*移动部分*/
//水平方向的输入获取(即A-D键或←→键)
float x = Input.GetAxisRaw("Horizontal");
//垂直方面的输入获取
float z = Input.GetAxisRaw("Vertical");
/* GetAxis()的返回值初始为0,在-1到1之间变化,对应的GetAxisRaw()则不会变化,直接返回1或-1 */
/*上面的input使用GetAxis()时在松开按键后角色会继续移动一小部分距离,会产生一种“滑滑”的效果,
使用GetAxisRaw()的话则即按即动,即送即停*/
if (Mathf.Abs(x) > 0.1f || Mathf.Abs(z) > 0.1f)
//移动方向
Vector3 toward_dir = new Vector3(x,0,z);
//不同于move函数,这里以秒为单位不能*Time.deltatime,不然会无法移动
//(normalized指单位化,即此时该向量不具备大小仅具备方向)
cc.SimpleMove(toward_dir.normalized * speed);
/*鼠标朝向部分*/
//生成从摄像机发射的射线,该射线穿过当前鼠标位置【因为视角透视原因,鼠标位置并不能代表实际我们希望的朝向,所以需要通过射线找到与平面的实际交点】
Ray ray = viewCamera.ScreenPointToRay(Input.mousePosition);
//创建一个平面,第一个参数和第二个参数构成法线,且平面穿过第二个参数点
Plane groundPlane = new Plane(Vector3.up, Vector3.zero);
//平面与射线相交返回发射点到相交点的距离
float rayDistance;
Vector3 point = Vector3.zero;
//Raycast计算相交点并返回距离
if (groundPlane.Raycast(ray, out rayDistance))
//获取到射线与平面的相交点,耶~
point = ray.GetPoint(rayDistance);
//指示线打印-用于测试
//Debug.DrawLine(ray.origin, point, Color.red);
//角色朝向-鼠标预期方向
Vector3 heightCorrectedPoint = new Vector3(point.x, transform.position.y, point.z);
transform.LookAt(heightCorrectedPoint);
------------------------------------------------------------------另一种方式------------------------------------------------------------------
【使用collider+rigidbody】准备:
- 在unity中创建好基本的平面和胶囊作为场景和角色(蓝色为z轴,代表transform.forward,即正面)
- 为平面添加collider(带2d的是2D项目使用的组件),为胶囊(角色)添加collider和rigidbody(带2d的是2D项目使用的组件)并锁定x,z轴的旋转防止角色倒下。
【使用collider+rigidbody】】编写move脚本:
第一种情况:角色移动方向与角色朝向一致:
一些细节和注意事项都写在代码注释中辣~
using UnityEngine;
/**
* 功能:角色移动控制[角色移动时永远朝正面]
*
*/
public class move3 : MonoBehaviour
//速度变量
public float speed;
//Rb刚体
public Rigidbody rb;
void Start()
//组件rb变量
rb = transform.GetComponent<Rigidbody>();
//速度赋值
speed = 7;
//【将Update函数修改为FixedUpdate,并且deltaTime修改为fixedDeltatime移动似乎会流畅一些,感觉有一点点变化,但是也不确定是不是心理作用】
void Update()
//调用移动方法
move_by_rb();
void move_by_rb()
//水平方向的输入获取(即A-D键或←→键)
float x = Input.GetAxisRaw("Horizontal");
//垂直方面的输入获取
float z = Input.GetAxisRaw("Vertical");
/* GetAxis()的返回值初始为0,在-1到1之间变化,对应的GetAxisRaw()则不会变化,直接返回1或-1 */
/*上面的input使用GetAxis()时在松开按键后角色会继续移动一小部分距离,会产生一种“滑滑”的效果,
使用GetAxisRaw()的话则即按即动,即送即停*/
if (Mathf.Abs(x) > 0.1f || Mathf.Abs(z) > 0.1f)
//移动方向
Vector3 toward_dir = new Vector3(x, 0, z);
//角色朝向移动方向
transform.LookAt(transform.position + toward_dir);
//MovePosition方法,以帧为单位,记得*Time.deltaTime哦~(normalized指单位化,即此时该向量不具备大小仅具备方向)
rb.MovePosition(rb.position + toward_dir.normalized * speed * Time.deltaTime);
第二种情况:角色移动方向可以不与角色朝向一致(键盘控制移动,鼠标控制朝向):
一些细节和注意事项都写在代码注释中辣~
using UnityEngine;
/**
* 功能:角色移动控制[角色移动时永远朝正面]
*
*/
public class move4 : MonoBehaviour
//速度变量
public float speed;
//Rb刚体
public Rigidbody rb;
//摄像机
public Camera viewCamera;
void Start()
//组件rb变量
rb = transform.GetComponent<Rigidbody>();
//速度赋值
speed = 7;
//主摄像机
viewCamera = Camera.main;
//【将Update函数修改为FixedUpdate,并且deltaTime修改为fixedDeltatime移动似乎会流畅一些,感觉有一点点变化,但是也不确定是不是心理作用】
void Update()
//调用移动方法
move_by_rb();
void move_by_rb()
/*移动部分*/
//水平方向的输入获取(即A-D键或←→键)
float x = Input.GetAxisRaw("Horizontal");
//垂直方面的输入获取
float z = Input.GetAxisRaw("Vertical");
/* GetAxis()的返回值初始为0,在-1到1之间变化,对应的GetAxisRaw()则不会变化,直接返回1或-1 */
/*上面的input使用GetAxis()时在松开按键后角色会继续移动一小部分距离,会产生一种“滑滑”的效果,
使用GetAxisRaw()的话则即按即动,即送即停*/
if (Mathf.Abs(x) > 0.1f || Mathf.Abs(z) > 0.1f)
//移动方向
Vector3 toward_dir = new Vector3(x, 0, z);
//MovePosition方法,以帧为单位,记得*Time.deltaTime哦~(normalized指单位化,即此时该向量不具备大小仅具备方向)
rb.MovePosition(rb.position + toward_dir.normalized * speed * Time.deltaTime);
/*鼠标朝向部分*/
//生成从摄像机发射的射线,该射线穿过当前鼠标位置【因为视角透视原因,鼠标位置并不能代表实际我们希望的朝向,所以需要通过射线找到与平面的实际交点】
Ray ray = viewCamera.ScreenPointToRay(Input.mousePosition);
//创建一个平面,第一个参数和第二个参数构成法线,且平面穿过第二个参数点
Plane groundPlane = new Plane(Vector3.up, Vector3.zero);
//平面与射线相交返回发射点到相交点的距离
float rayDistance;
Vector3 point = Vector3.zero;
//Raycast计算相交点并返回距离
if (groundPlane.Raycast(ray, out rayDistance))
//获取到射线与平面的相交点,耶~
point = ray.GetPoint(rayDistance);
//指示线打印-用于测试
//Debug.DrawLine(ray.origin, point, Color.red);
//角色朝向-鼠标预期方向
Vector3 heightCorrectedPoint = new Vector3(point.x, transform.position.y, point.z);
transform.LookAt(heightCorrectedPoint);
以上就是本次的分享内容辣~(●ˇ∀ˇ●),可以看到两种方式的本质操作是没有什么较大的区别的,仅在于准备部分的不同和代码中对应组件的调用不同而已,不过这里还要告诉大家的是,一般使用character controller是为了自定义一些更‘游戏化’的物理效果,而collider+rigidbody的方法则更偏向于真实物理世界,但是很多时候游戏不一定越真实就越舒服。
以上是关于unity3d俯视角简易移动控制脚本及其易错点小分享的主要内容,如果未能解决你的问题,请参考以下文章