如何在Unity3D中实现第三人称相机不穿过墙体与物体?
解决方案
你的思路是对的,第三人称相机防穿墙最稳定的实现就是用射线检测,之前添加碰撞体的方案不生效是因为代码直接赋值transform.position相当于瞬移物体,Unity物理引擎不会对这种位置变化做碰撞响应。
具体实现步骤
- 新增3个公共变量方便调试:最大相机距离、障碍物层级、相机防撞偏移量
- 计算相机的理想位置后,从玩家观察点向理想相机位置发射线检测
- 若射线碰到障碍物,将相机位置调整到碰撞点靠近玩家一侧,避免贴墙触发裁剪
修改后完整代码
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityStandardAssets.Characters.ThirdPerson; public class ThirdPersonInput : MonoBehaviour { public FixedJoystick LeftJoystick; public FixedButton Button; public FixedTouchField TouchField; // 新增防撞相关参数 [Header("相机防撞设置")] public float maxCameraDistance = 3f; public LayerMask obstacleLayer; public float cameraCollisionOffset = 0.2f; protected ThirdPersonUserControl Control; protected float CameraAngle; protected float CameraAngleSpeed = 0.2f; // 相机观察点:玩家头顶位置 private Vector3 LookAtPoint => transform.position + Vector3.up * 2f; void Start() { Control = GetComponent<ThirdPersonUserControl>(); } void Update() { Control.m_Jump = Button.Pressed; Control.Hinput = LeftJoystick.Direction.x; Control.Vinput = LeftJoystick.Direction.y; CameraAngle += TouchField.TouchDist.x * CameraAngleSpeed; // 计算相机理想位置 Vector3 idealCamPos = transform.position + Quaternion.AngleAxis(CameraAngle, Vector3.up) * new Vector3(0, 3, -maxCameraDistance); Vector3 finalCamPos = idealCamPos; // 射线检测障碍物 if (Physics.Linecast(LookAtPoint, idealCamPos, out RaycastHit hit, obstacleLayer)) { // 碰撞时把相机放到碰撞点往玩家方向偏移的位置,避免贴墙 finalCamPos = hit.point + (LookAtPoint - hit.point).normalized * cameraCollisionOffset; } Camera.main.transform.position = finalCamPos; Camera.main.transform.rotation = Quaternion.LookRotation(LookAtPoint - Camera.main.transform.position, Vector3.up); } }
配置说明
- 在Inspector面板中把
obstacleLayer设置为你场景中墙体、障碍物所在的层级,不要勾选玩家所在层级,避免射线检测到玩家自身导致相机异常拉近 - 可以根据测试效果调整
cameraCollisionOffset的大小,避免相机贴墙时出现场景裁剪问题
内容的提问来源于stack exchange,提问作者Vipul Rathod
相关产品推荐
相关产品推荐

