基于体素场景的摄像机穿模处理

2023-10-04 02:15

本文主要是介绍基于体素场景的摄像机穿模处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于上一篇一种基于体素的射线检测
使用射线处理第三人称摄像头穿模问题

基于体素的第三人称摄像机拉近简单处理

摄像机移动至碰撞点处

简单的从角色身上发射一条射线到摄像机,中途遇到碰撞就把摄像机移动至该碰撞点

    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;}
}

这篇关于基于体素场景的摄像机穿模处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1105

相关文章

MyBatis-Plus 中 nested() 与 and() 方法详解(最佳实践场景)

《MyBatis-Plus中nested()与and()方法详解(最佳实践场景)》在MyBatis-Plus的条件构造器中,nested()和and()都是用于构建复杂查询条件的关键方法,但... 目录MyBATis-Plus 中nested()与and()方法详解一、核心区别对比二、方法详解1.and()

Spring Boot @RestControllerAdvice全局异常处理最佳实践

《SpringBoot@RestControllerAdvice全局异常处理最佳实践》本文详解SpringBoot中通过@RestControllerAdvice实现全局异常处理,强调代码复用、统... 目录前言一、为什么要使用全局异常处理?二、核心注解解析1. @RestControllerAdvice2

ModelMapper基本使用和常见场景示例详解

《ModelMapper基本使用和常见场景示例详解》ModelMapper是Java对象映射库,支持自动映射、自定义规则、集合转换及高级配置(如匹配策略、转换器),可集成SpringBoot,减少样板... 目录1. 添加依赖2. 基本用法示例:简单对象映射3. 自定义映射规则4. 集合映射5. 高级配置匹

python中Hash使用场景分析

《python中Hash使用场景分析》Python的hash()函数用于获取对象哈希值,常用于字典和集合,不可变类型可哈希,可变类型不可,常见算法包括除法、乘法、平方取中和随机数哈希,各有优缺点,需根... 目录python中的 Hash除法哈希算法乘法哈希算法平方取中法随机数哈希算法小结在Python中,

电脑提示xlstat4.dll丢失怎么修复? xlstat4.dll文件丢失处理办法

《电脑提示xlstat4.dll丢失怎么修复?xlstat4.dll文件丢失处理办法》长时间使用电脑,大家多少都会遇到类似dll文件丢失的情况,不过,解决这一问题其实并不复杂,下面我们就来看看xls... 在Windows操作系统中,xlstat4.dll是一个重要的动态链接库文件,通常用于支持各种应用程序

SQL Server数据库死锁处理超详细攻略

《SQLServer数据库死锁处理超详细攻略》SQLServer作为主流数据库管理系统,在高并发场景下可能面临死锁问题,影响系统性能和稳定性,这篇文章主要给大家介绍了关于SQLServer数据库死... 目录一、引言二、查询 Sqlserver 中造成死锁的 SPID三、用内置函数查询执行信息1. sp_w

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

Golang 日志处理和正则处理的操作方法

《Golang日志处理和正则处理的操作方法》:本文主要介绍Golang日志处理和正则处理的操作方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录1、logx日志处理1.1、logx简介1.2、日志初始化与配置1.3、常用方法1.4、配合defer

springboot加载不到nacos配置中心的配置问题处理

《springboot加载不到nacos配置中心的配置问题处理》:本文主要介绍springboot加载不到nacos配置中心的配置问题处理,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录springboot加载不到nacos配置中心的配置两种可能Spring Boot 版本Nacos