unity3d 摄像机跟随角色时被物体遮挡解决方案
参考文章:http://www.xuanyusong.com/archives/1991
在看此文章时请先看上面的参考文章
看完以上文章后,你也许会想人家都已经给出所有代码了,你还写个毛啊
别急,现在进入主题
在我的项目中,我采用的是物体遮挡作半透明处理,如果按照上述文章中的思路来写代码的话,那么结果就是当多个物体遮挡角色时,只有第一个物体会半透明,如图:

角色被墙和屋顶遮挡住了,但是可以清楚的看见左下角的墙呈半透明状态,而屋顶依旧不透明
为了解决这个问题,我们不采用上述文章中的 physics.Linecast,在这里我们需要用到 Physics.RaycastAll;使用方法详见圣典
ok,现在我们开始敲代码
首先 ,我们引入命名空间 System.Collections.Generic,然后在声明三个需要用到的变量
using System.Collections.Generic;//引入命名空间 public class MyCamera1 : MonoBehaviour
{
//观察目标
public Transform Target; //上次碰撞到的物体
private List<GameObject> lastColliderObject; //本次碰撞到的物体
private List<GameObject> colliderObject;
}
我们需要发射一条射线,这条射线从角色当前位置发射置摄像机的方向
/*射线可以从头部起始*/
//这里是计算射线的方向,从主角发射方向是射线机方向
Vector3 aim = Target.position;
//得到方向
Vector3 ve = (Target.position - transform.position).normalized;
float an = transform.eulerAngles.y;
aim -= an * ve;
//在场景视图中可以看到这条射线
//Debug.DrawLine(target.position, aim, Color.red);
RaycastHit[] hit;
hit = Physics.RaycastAll(Target.position, aim, 100f);//起始位置、方向、距离
射线发送完毕后,我们获取发送射线时碰撞到的所有物体,并且添加进本次碰撞到的物体(colliderObject)变量中
因为我的地图、护栏碰撞(不可见)、地面碰撞(不可见)是三个模型,也就是说地图本身是没有任何碰撞的
所以当碰撞到的物体名为护栏或地面时,就不修改其透明度,因为他本身就不可见
这里我偷懒了,直接判断物体名称,可自行改为判断物体 tag
当视角旋转的时候,射线有时候会碰撞到角色,所以,我们获取 tag 判断是否碰撞的物体为角色
//将 colliderObject 中所有的值添加进 lastColliderObject
for (int i = ; i < colliderObject.Count; i++)
lastColliderObject.Add(colliderObject[i]); colliderObject.Clear();//清空本次碰撞到的所有物体
for (int i = ; i < hit.Length; i++)//获取碰撞到的所有物体
{
if (hit[i].collider.gameObject.name != "Editable Poly 1"//护栏
&& hit[i].collider.gameObject.name != "Editable Poly"//地面
&& hit[i].collider.gameObject.tag != "Player")//角色
{
//Debug.Log(hit[i].collider.gameObject.name);
colliderObject.Add(hit[i].collider.gameObject);
SetMaterialsColor(hit[i].collider.gameObject.renderer, 0.4f);//置当前物体材质透明度
}
}
当获取到所碰撞到的所有物体后,我们要修改他的材质透明度,有些物体有很多材质,不知道怎么解决的请看我下面这个方法:
/// 置物体所有材质球颜色 <summary>
/// 置物体所有材质球颜色
/// </summary>
/// <param name="_renderer">材质</param>
/// <param name="Transpa">透明度</param>
private void SetMaterialsColor(Renderer _renderer, float Transpa)
{
//获取当前物体材质球数量
int materialsNumber = _renderer.sharedMaterials.Length;
for (int i = ; i < materialsNumber; i++)
{
//获取当前材质球颜色
Color color = _renderer.materials[i].color; //设置透明度 取值范围:0~1; 0 = 完全透明
color.a = Transpa; //置当前材质球颜色
_renderer.materials[i].SetColor("_Color", color);
}
}
如果本次碰撞到的物体存在于上个物体,那么则说明当前物体还处于遮挡角色状态,所以我们赋值为null
//上次与本次对比,本次还存在的物体则赋值为null
for (int i = ; i < lastColliderObject.Count; i++)
{
for (int ii = ; ii < colliderObject.Count; ii++)
{
if (colliderObject[ii] != null)
{
if (lastColliderObject[i] == colliderObject[ii])
{
lastColliderObject[i] = null;
break;
}
}
}
}
还处于遮挡状态的物体已被赋值为null,那么剩下的物体就是没有处于遮挡状态的,所以我们要重置该物体材质为不透明
//当值为null时则可判断当前物体还处于遮挡状态
//值不为null时则可恢复默认状态(不透明)
for (int i = ; i < lastColliderObject.Count; i++)
{
if (lastColliderObject[i] != null)
SetMaterialsColor(lastColliderObject[i].renderer, 1f);//恢复上次物体材质透明度
}
好了,所有代码已完成,我们看一下运行结果
未遮挡时:

遮挡时:

怎么样,有木有感觉很酷炫呢,哈哈哈
最后,附上完整代码链接:http://pan.baidu.com/s/1gdGLwiv 密码:pbrd
原文链接:http://www.cnblogs.com/shenggege/p/4113316.html
unity3d 摄像机跟随角色时被物体遮挡解决方案的更多相关文章
- unity3d 角色头顶信息3D&2D遮挡解决方案(一)
先上效果图,只凭文字描述,脑补应该有些困难- - 如图:有三个角色(我们暂且从左到右叫它们A.B.C),一个2D UI(中间动作选择的框框),一个cube(右边的方块) cube挡住了角色C的头顶信息 ...
- unity3d 角色头顶信息3D&2D遮挡解决方案(二)
在阅读本文之前请先阅读上一篇文章:http://www.cnblogs.com/shenggege/p/4179012.html 本来一篇文章就可以说完了,但是上次只是实现了已知的一些功能 后来在实际 ...
- Unity3D中的高级摄像机跟随
在Unity3D中,先调整MainCamera在场景中的位置,然后把脚本挂到MainCamera上,摄像机跟随分为简单的摄像机跟随和高级摄像机跟随. 简单摄像机跟随: public class Cam ...
- 关于Unity3D中鼠标移动指定物体的解决方案
一.鼠标拾取物体的原理 在Unity3D当中,想要在观察面(Aspect)中拾取物体(有碰撞属性)的方法一般如下: 1.声明一个观察的摄像机.一个从摄像机原点出发的射线Ray以及一个用于检测碰撞的Ra ...
- unity3d 摄像机抖动效果 CameraShake
unity3d 摄像机抖动效果 ,利用脚本直接控制:当然也可以选择使用dotween插件,但到不至于为了使用仅一个功能,就导入了一个插件: 脚本示例: using UnityEngine; using ...
- 关于Unity中的小案例之运动的小船以及摄像机跟随技术(专题五)
实例步骤 1.创建Unity项目和文件目录,保存场景 场景搭建 2.导入美术做好的资源包(第68) a: 导入地形资源包terrain.unitypackage,把里面的Map/Prefabs/Ter ...
- 2D游戏摄像机跟随不出界
做2D游戏的时候碰上摄像机要跟随人物时要防止摄像机看到界面外的黑幕,直接上代码. using System.Collections; using System.Collections.Generic; ...
- Unity3D 相机跟随主角移动
这里给主相机绑定一个脚本. 脚本写为: using UnityEngine; using System.Collections; public class camerafollow : MonoBeh ...
- unity3d 通过添加rigidBody来指明物体是动态的,以避免cache开销
unity3d 通过添加rigidBody来指明物体是动态的,以避免cache开销. 如果不添加rigidBody,则unity会认为它是静态的,会对物理计算进行cache,但如果此物体实际上tran ...
随机推荐
- VS Code 中 HTML 文档注释 js 语句异常
今天用 VS Code 编辑 html 文档时,发现快捷键注释 js 代码显示成 “<!-- …… -->”,怀疑是不是因为安装了某个插件,随后排查出系 Jinja 所致,将其禁用之后就 ...
- 使用vue自定义组件以及动态时间
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 【洛谷P1367】蚂蚁
蚂蚁 [题目描述] 在一根无限长的木棍上,用n只蚂蚁,每只蚂蚁有一个初始位置和初始朝向,蚂蚁们以每秒一个单位的速度向前移动,当两只蚂蚁相遇时,它们会掉头(掉头时间忽略不计).现给出每只蚂蚁的初始位置和 ...
- c#数据库连接池Hikari重构升级
Hikari是我自定义的数据库连接池,前面已经提供了地址.因为c#的连接池按照规范的ADO.NET里面实现定义的.由数据库官方提供,但是实现方式就不知道了,反正没有看出来,估计一般是连接类实现的,但是 ...
- 搜索框反射型xss问题解决(网站开发)
什么是反射型XSS XSS又叫CSS (Cross Site Script) ,跨站脚本攻击.它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的h ...
- php第五节(字符串函数和时间、日期函数)
<?php //查找字符串函数 // strpos() 查找字符第一次出现的位置 重点区分大小写 //stripos — 查找字符串首次出现的位置(不区分大小写) //strrpos — 计算指 ...
- php第四节(循环和函数)
<?php //循环有 for(){}.有while(){} 有do{}while().foreach(){}循环 //1.for(){} for($i=0;$i<=9;$i++){ ec ...
- ABAP术语-Data Browser
Data Browser 原文:http://www.cnblogs.com/qiangsheng/archive/2008/01/21/1046858.html Tool for displayin ...
- C# register global hotkey ,onekey 注册多个全局热键以及单个全局热键
我们需要用非Hook的方法,来给我们的app 或者winform注册热键. 就像下面的 , 欧陆词典注册的一个热键F6一样, 在winform最小化的情况下,也能够全局响应热键. 这里使用系统API来 ...
- Vue使用json-server来进行后端数据模拟
正开发过程中 前后端分离或者不分离 ,接口多半是之后与页面的开发 ,所以建立rest的APL的接口 给前端提供虚拟的数据是非常必要的 所以这里我使用了json-server作为工具,支持CORS和JS ...