unity第三人称视角下使用手柄的摄像机控制及防穿墙
有关手柄的设置参考下面这个帖子,这里不再重复
要让相机跟随角色,首先可以让相机成为角色的子物体,或在初始时得到相机与角色的偏移量,在运动过程中让角色的位置加上这个偏移量即可。为了更好适应角色所处环境及实现其他功能,可以采用以下方法:
创建一个空物体Empty,在Empty下创建一个子物体Position,最后使相机成为Position的子物体。接下来我们需要设置这几个物体(在代码中),让Empty的position等于人物的position,让Position的位置等于人物的位置的Y方向加1.0f(其实可以随意设置)unity摄像机旋转,再把相机设置到合适的位置使之看向角色(设置相机可以在Scene模式下设置)。
创建一个C#脚本,将其挂载在Empty上,定义以下变量像素游戏素材,并在Start方法中获取刚才设置的物体的Transform组件以及相机与Postion的偏移量
private Transform charactor;//获取当前角色
private Transform pos;//获取Empty的子物体pos
private Vector3 offset;//获取初始时镜头相对于pos的偏移量
private float R_H;//获取摇杆的返回值-水平轴
private float R_V;//获取摇杆的返回值-垂直轴
private float lookAngle;//镜头说水平旋转的角度
private float tiltAngle;//镜头垂直旋转的角度(实质为父物体pos的垂直旋转角度)
private float moveSpeed = 10f;//用于设置镜头跟随的速度
private float turnSpeed = 1.5f;//用于设置镜头在两个方向上旋转的角度
private Transform mainCamera;
// Use this for initialization
void Start()
{
charactor = GameObject.FindGameObjectWithTag("Charactor").GetComponent();
pos = GameObject.FindGameObjectWithTag("Pos").GetComponent();
mainCamera = GameObject.FindGameObjectWithTag("MainCamera").GetComponent();
offset = mainCamera.position - pos.position;
}
相机跟随角色可以采用以下方法:
private void FollowCharactor(float deltaTime)
{
//注意需要把offset转为pos的局部坐标
mainCamera.position = Vector3.Lerp(mainCamera.position, pos.position + pos.TransformDirection(offset), deltaTime * moveSpeed);
}
引入deltaTime参数和Lerp方法可以使镜头变换更加平滑顺畅
接下来是控制镜头左右和上下旋转,镜头的水平方向旋转由Empty控制,垂直方向的旋转由pos控制,这么做可以防止镜头注视角色的时候旋转出现问题,比如在自身Z轴上发生旋转
private void HandleCameraRotate()
{
transform.position = charactor.position;//设定水平旋转角度
lookAngle += R_H * turnSpeed;
transform.localEulerAngles = new Vector3(0, lookAngle, 0);//将得到的角度赋值给empty的localEulerAngles
tiltAngle -= turnSpeed * R_V;//设定垂直旋转角度
tiltAngle = Mathf.Clamp(tiltAngle, -80, 50);//对旋转角度加以限制
pos.localEulerAngles = new Vector3(tiltAngle, pos.localEulerAngles.y, pos.localEulerAngles.z);//将得到的角度赋值给pos的localEulerAngles
}
这样基本的控制就做完了,可以在Update()方法中调用(实测FixedUpdate和LateUpdate方法中调用效果不好)
void Update()
{
R_H = Input.GetAxis("Horizontal_Right");
R_V = Input.GetAxis("Vertical_Right");
HandleCameraRotate();
FollowCharactor(Time.deltaTime);
}
对于防镜头穿墙的方法,这是我个人想出来的可能算是比较简单的一种写法2d素材,在Update中调用即可
从pos的位置开始unity摄像机旋转,创建一条指向相机的射线,长度为offset,判断射线碰撞到的物体的标签
private void AvoidCrossWall()
{
RaycastHit hit;
if (Physics.Raycast(pos.position, mainCamera.position - pos.position, out hit, offset.magnitude))
{
if (hit.collider.tag == "Obstacle")
{
mainCamera.position = hit.point;
}
}
}
本方法需要把不想让墙穿过的所有物体的标签设置为Obstacle
文章来源:https://blog.csdn.net/qq_45919090/article/details/109393562