松江新城网站建设,贵阳市 网站建设,网站开发判断是否为手机,深圳游戏公司基于上一篇一种基于体素的射线检测 使用射线处理第三人称摄像头穿模问题 基于体素的第三人称摄像机拉近简单处理 摄像机移动至碰撞点处
简单的从角色身上发射一条射线到摄像机#xff0c;中途遇到碰撞就把摄像机移动至该碰撞点 public void UpdateDistance(float defaultDist…基于上一篇一种基于体素的射线检测 使用射线处理第三人称摄像头穿模问题 基于体素的第三人称摄像机拉近简单处理 摄像机移动至碰撞点处
简单的从角色身上发射一条射线到摄像机中途遇到碰撞就把摄像机移动至该碰撞点 public void UpdateDistance(float defaultDistance){Vector3 from player.position;Vector3 to cameraRoot.position;Vector3 forward (to - from).normalized;Debug.DrawLine(from, to, Color.red);if (BlockPhysics.Raycast(BlockWorld.CurWorld, from, forward, (to - from).magnitude, out hitInfo)){distance cameraRoot.InverseTransformPoint(hitInfo.point).z;}else{distance 0;}curDistance Mathf.Lerp(curDistance, distance, speed * Time.fixedDeltaTime);curDistance Mathf.Clamp(curDistance, 0, defaultDistance);transform.localPosition Vector3.forward * curDistance;}可以明显看到摄像机一半在外面一半在墙里面体验感非常差 可以通过检测摄像机近裁剪面的4个顶点是否在方块或体素内 如果有一个顶点产生碰撞那么就把摄像机向前移动 float GetDistance(float distance){int i 0;int loop 666;virtualCamera.localPosition Vector3.forward * distance;var wrold BlockWorld.CurWorld;while (loop-- 0){UpdateNearClipPlane();for (i 0; i 4; i){if (wrold.HasBlockCollider(Vector3Int.RoundToInt(corners[i])) || wrold.HasVoxelCollider(corners[i])){break;}}if (i 4)break;distance 0.25f;virtualCamera.localPosition Vector3.forward * distance;}return distance;}
通过前移规避穿模问题 当然如果夹角非常小或者在一个狭窄的通道内并不推荐拉近摄像头。 因为拉近已经不能解决问题。这种情况下推荐摄像机观察中心直接固定在方块中心。 从方块中心出发就不用担心角色过于靠近墙壁导致的拉近修复无效
完整代码
using UnityEngine;public class CameraOffset : MonoBehaviour
{public float speed 10;Transform cameraRoot;Transform player;float distance;float curDistance;RaycastHit hitInfo;Camera mainCamera;Transform virtualCamera;Vector3[] corners new Vector3[4];float width;float height;private void Start(){cameraRoot transform.parent;player GameObject.FindGameObjectWithTag(Player).transform;player player.transform.Find(cameraFollow);mainCamera Camera.main;virtualCamera new GameObject(virtualCamera).transform;virtualCamera.transform.SetParent(mainCamera.transform.parent);virtualCamera.localPosition Vector3.zero;virtualCamera.localRotation Quaternion.identity;virtualCamera.localScale Vector3.zero;float halfFOV (mainCamera.fieldOfView * 0.5f) * Mathf.Deg2Rad;float aspect mainCamera.aspect;height mainCamera.nearClipPlane * Mathf.Tan(halfFOV);width height * aspect;}private void OnDrawGizmos(){Gizmos.color Color.red;Gizmos.DrawWireSphere(hitInfo.point, 0.1f);}public void UpdateDistance(float defaultDistance){Vector3 from player.position;Vector3 to cameraRoot.position;Vector3 forward (to - from).normalized;Debug.DrawLine(from, to, Color.red);if (BlockPhysics.Raycast(BlockWorld.CurWorld, from, forward, (to - from).magnitude, out hitInfo)){distance GetDistance(cameraRoot.InverseTransformPoint(hitInfo.point).z);}else{distance 0;}curDistance Mathf.Lerp(curDistance, distance, speed * Time.fixedDeltaTime);curDistance Mathf.Clamp(curDistance, 0, defaultDistance);transform.localPosition Vector3.forward * curDistance;}float GetDistance(float distance){int i 0;int loop 666;virtualCamera.localPosition Vector3.forward * distance;var wrold BlockWorld.CurWorld;while (loop-- 0){UpdateNearClipPlane();for (i 0; i 4; i){if (wrold.HasBlockCollider(Vector3Int.RoundToInt(corners[i])) || wrold.HasVoxelCollider(corners[i])){break;}}if (i 4)break;distance 0.25f;virtualCamera.localPosition Vector3.forward * distance;}return distance;}void UpdateNearClipPlane(){corners[0] virtualCamera.position - (virtualCamera.right * width);corners[0] virtualCamera.up * height;corners[0] virtualCamera.forward * mainCamera.nearClipPlane;corners[1] virtualCamera.position (virtualCamera.right * width);corners[1] virtualCamera.up * height;corners[1] virtualCamera.forward * mainCamera.nearClipPlane;corners[2] virtualCamera.position - (virtualCamera.right * width);corners[2] - virtualCamera.up * height;corners[2] virtualCamera.forward * mainCamera.nearClipPlane;corners[3] virtualCamera.position (virtualCamera.right * width);corners[3] - virtualCamera.up * height;corners[3] virtualCamera.forward * mainCamera.nearClipPlane;}
}