unity3d 摄像机跟随角色时被物体遮挡解决方案
2015-02-01 23:41
387 查看
在看此文章时请先看上面的参考文章。更多精彩请关注【狗刨学习网】
看完以上文章后,你也许会想人家都已经给出所有代码了,你还写个毛啊
别急,现在进入主题
在我的项目中,我采用的是物体遮挡作半透明处理,如果按照上述文章中的思路来写代码的话,那么结果就是当多个物体遮挡角色时,只有第一个物体会半透明,如图:
角色被墙和屋顶遮挡住了,但是可以清楚的看见左下角的墙呈半透明状态,而屋顶依旧不透明
为了解决这个问题,我们不采用上述文章中的 physics.Linecast,在这里我们需要用到 Physics.RaycastAll;使用方法详见圣典
ok,现在我们开始敲代码
首先 ,我们引入命名空间 System.Collections.Generic,然后在声明三个需要用到的变量
<font face="新宋体" size="2">using System.Collections.Generic;//引入命名空间
public class MyCamera1 : MonoBehaviour
{
//观察目标
public Transform Target;
//上次碰撞到的物体
private List<GameObject> lastColliderObject;
//本次碰撞到的物体
private List<GameObject> colliderObject;
}</font>
复制代码
我们需要发射一条射线,这条射线从角色当前位置发射置摄像机的方向
<font face="新宋体" size="2"> /*射线可以从头部起始*/
2
3 //这里是计算射线的方向,从主角发射方向是射线机方向
4 Vector3 aim = Target.position;
5 //得到方向
6 Vector3 ve = (Target.position - transform.position).normalized;
7 float an = transform.eulerAngles.y;
8 aim -= an * ve;
9
10 //在场景视图中可以看到这条射线
11 //Debug.DrawLine(target.position, aim, Color.red);
12
13 RaycastHit[] hit;
14 hit = Physics.RaycastAll(Target.position, aim, 100f);//起始位置、方向、距离</font>
复制代码
射线发送完毕后,我们获取发送射线时碰撞到的所有物体,并且添加进本次碰撞到的物体(colliderObject)变量中
因为我的地图、护栏碰撞(不可见)、地面碰撞(不可见)是三个模型,也就是说地图本身是没有任何碰撞的
所以当碰撞到的物体名为护栏或地面时,就不修改其透明度,因为他本身就不可见
这里我偷懒了,直接判断物体名称,可自行改为判断物体 tag
当视角旋转的时候,射线有时候会碰撞到角色,所以,我们获取 tag 判断是否碰撞的物体为角色
<font face="新宋体" size="2"> 1 //将 colliderObject 中所有的值添加进 lastColliderObject
2 for (int i = 0; i < colliderObject.Count; i++)
3 lastColliderObject.Add(colliderObject[i]);
4
5 colliderObject.Clear();//清空本次碰撞到的所有物体
6 for (int i = 0; i < hit.Length; i++)//获取碰撞到的所有物体
7 {
8 if (hit[i].collider.gameObject.name != "Editable Poly 1"//护栏
9 && hit[i].collider.gameObject.name != "Editable Poly"//地面
10 && hit[i].collider.gameObject.tag != "Player")//角色
11 {
12 //Debug.Log(hit[i].collider.gameObject.name);
13 colliderObject.Add(hit[i].collider.gameObject);
14 SetMaterialsColor(hit[i].collider.gameObject.renderer, 0.4f);//置当前物体材质透明度
15 }
16 }</font>
复制代码
当获取到所碰撞到的所有物体后,我们要修改他的材质透明度,有些物体有很多材质,不知道怎么解决的请看我下面这个方法:
<font face="新宋体" size="2"> 1 /// 置物体所有材质球颜色 <summary>
2 /// 置物体所有材质球颜色
3 /// </summary>
4 /// <param name="_renderer">材质</param>
5 /// <param name="Transpa">透明度</param>
6 private void SetMaterialsColor(Renderer _renderer, float Transpa)
7 {
8 //获取当前物体材质球数量
9 int materialsNumber = _renderer.sharedMaterials.Length;
10 for (int i = 0; i < materialsNumber; i++)
11 {
12 //获取当前材质球颜色
13 Color color = _renderer.materials[i].color;
14
15 //设置透明度 取值范围:0~1; 0 = 完全透明
16 color.a = Transpa;
17
18 //置当前材质球颜色
19 _renderer.materials[i].SetColor("_Color", color);
20 }
21 }</font>
复制代码
如果本次碰撞到的物体存在于上个物体,那么则说明当前物体还处于遮挡角色状态,所以我们赋值为null
<font face="新宋体" size="2"> 1 //上次与本次对比,本次还存在的物体则赋值为null
2 for (int i = 0; i < lastColliderObject.Count; i++)
3 {
4 for (int ii = 0; ii < colliderObject.Count; ii++)
5 {
6 if (colliderObject[ii] != null)
7 {
8 if (lastColliderObject[i] == colliderObject[ii])
9 {
10 lastColliderObject[i] = null;
11 break;
12 }
13 }
14 }
15 }</font>
复制代码
还处于遮挡状态的物体已被赋值为null,那么剩下的物体就是没有处于遮挡状态的,所以我们要重置该物体材质为不透明
<font face="新宋体" size="2">1 //当值为null时则可判断当前物体还处于遮挡状态
2 //值不为null时则可恢复默认状态(不透明)
3 for (int i = 0; i < lastColliderObject.Count; i++)
4 {
5 if (lastColliderObject[i] != null)
6 SetMaterialsColor(lastColliderObject[i].renderer, 1f);//恢复上次物体材质透明度
7 }</font>
复制代码
好了,所有代码已完成,我们看一下运行结果
未遮挡时:
遮挡时:
211731341872056.jpg (91.76 KB, 下载次数: 0)
下载附件 保存到相册
6 小时前 上传
怎么样,有木有感觉很酷炫呢,哈哈哈
看完以上文章后,你也许会想人家都已经给出所有代码了,你还写个毛啊
别急,现在进入主题
在我的项目中,我采用的是物体遮挡作半透明处理,如果按照上述文章中的思路来写代码的话,那么结果就是当多个物体遮挡角色时,只有第一个物体会半透明,如图:
角色被墙和屋顶遮挡住了,但是可以清楚的看见左下角的墙呈半透明状态,而屋顶依旧不透明
为了解决这个问题,我们不采用上述文章中的 physics.Linecast,在这里我们需要用到 Physics.RaycastAll;使用方法详见圣典
ok,现在我们开始敲代码
首先 ,我们引入命名空间 System.Collections.Generic,然后在声明三个需要用到的变量
<font face="新宋体" size="2">using System.Collections.Generic;//引入命名空间
public class MyCamera1 : MonoBehaviour
{
//观察目标
public Transform Target;
//上次碰撞到的物体
private List<GameObject> lastColliderObject;
//本次碰撞到的物体
private List<GameObject> colliderObject;
}</font>
复制代码
我们需要发射一条射线,这条射线从角色当前位置发射置摄像机的方向
<font face="新宋体" size="2"> /*射线可以从头部起始*/
2
3 //这里是计算射线的方向,从主角发射方向是射线机方向
4 Vector3 aim = Target.position;
5 //得到方向
6 Vector3 ve = (Target.position - transform.position).normalized;
7 float an = transform.eulerAngles.y;
8 aim -= an * ve;
9
10 //在场景视图中可以看到这条射线
11 //Debug.DrawLine(target.position, aim, Color.red);
12
13 RaycastHit[] hit;
14 hit = Physics.RaycastAll(Target.position, aim, 100f);//起始位置、方向、距离</font>
复制代码
射线发送完毕后,我们获取发送射线时碰撞到的所有物体,并且添加进本次碰撞到的物体(colliderObject)变量中
因为我的地图、护栏碰撞(不可见)、地面碰撞(不可见)是三个模型,也就是说地图本身是没有任何碰撞的
所以当碰撞到的物体名为护栏或地面时,就不修改其透明度,因为他本身就不可见
这里我偷懒了,直接判断物体名称,可自行改为判断物体 tag
当视角旋转的时候,射线有时候会碰撞到角色,所以,我们获取 tag 判断是否碰撞的物体为角色
<font face="新宋体" size="2"> 1 //将 colliderObject 中所有的值添加进 lastColliderObject
2 for (int i = 0; i < colliderObject.Count; i++)
3 lastColliderObject.Add(colliderObject[i]);
4
5 colliderObject.Clear();//清空本次碰撞到的所有物体
6 for (int i = 0; i < hit.Length; i++)//获取碰撞到的所有物体
7 {
8 if (hit[i].collider.gameObject.name != "Editable Poly 1"//护栏
9 && hit[i].collider.gameObject.name != "Editable Poly"//地面
10 && hit[i].collider.gameObject.tag != "Player")//角色
11 {
12 //Debug.Log(hit[i].collider.gameObject.name);
13 colliderObject.Add(hit[i].collider.gameObject);
14 SetMaterialsColor(hit[i].collider.gameObject.renderer, 0.4f);//置当前物体材质透明度
15 }
16 }</font>
复制代码
当获取到所碰撞到的所有物体后,我们要修改他的材质透明度,有些物体有很多材质,不知道怎么解决的请看我下面这个方法:
<font face="新宋体" size="2"> 1 /// 置物体所有材质球颜色 <summary>
2 /// 置物体所有材质球颜色
3 /// </summary>
4 /// <param name="_renderer">材质</param>
5 /// <param name="Transpa">透明度</param>
6 private void SetMaterialsColor(Renderer _renderer, float Transpa)
7 {
8 //获取当前物体材质球数量
9 int materialsNumber = _renderer.sharedMaterials.Length;
10 for (int i = 0; i < materialsNumber; i++)
11 {
12 //获取当前材质球颜色
13 Color color = _renderer.materials[i].color;
14
15 //设置透明度 取值范围:0~1; 0 = 完全透明
16 color.a = Transpa;
17
18 //置当前材质球颜色
19 _renderer.materials[i].SetColor("_Color", color);
20 }
21 }</font>
复制代码
如果本次碰撞到的物体存在于上个物体,那么则说明当前物体还处于遮挡角色状态,所以我们赋值为null
<font face="新宋体" size="2"> 1 //上次与本次对比,本次还存在的物体则赋值为null
2 for (int i = 0; i < lastColliderObject.Count; i++)
3 {
4 for (int ii = 0; ii < colliderObject.Count; ii++)
5 {
6 if (colliderObject[ii] != null)
7 {
8 if (lastColliderObject[i] == colliderObject[ii])
9 {
10 lastColliderObject[i] = null;
11 break;
12 }
13 }
14 }
15 }</font>
复制代码
还处于遮挡状态的物体已被赋值为null,那么剩下的物体就是没有处于遮挡状态的,所以我们要重置该物体材质为不透明
<font face="新宋体" size="2">1 //当值为null时则可判断当前物体还处于遮挡状态
2 //值不为null时则可恢复默认状态(不透明)
3 for (int i = 0; i < lastColliderObject.Count; i++)
4 {
5 if (lastColliderObject[i] != null)
6 SetMaterialsColor(lastColliderObject[i].renderer, 1f);//恢复上次物体材质透明度
7 }</font>
复制代码
好了,所有代码已完成,我们看一下运行结果
未遮挡时:
遮挡时:
211731341872056.jpg (91.76 KB, 下载次数: 0)
下载附件 保存到相册
6 小时前 上传
怎么样,有木有感觉很酷炫呢,哈哈哈
相关文章推荐
- unity3d 摄像机跟随角色时被物体遮挡解决方案
- unity3d 摄像机跟随角色时被物体遮挡解决方案
- Unity3D 摄像机平滑跟随角色
- unity3d 角色头顶信息3D&2D遮挡解决方案(二)
- Unity3d摄像机跟随角色移动脚本
- unity3d 角色头顶信息3D&2D遮挡解决方案(一)
- 摄像机对物体(角色)的跟随—简短
- unity3d 角色头顶信息3D&2D遮挡解决方案(一)
- unity3d阶段性学习脚本代码(2个是摄像机跟随(2D游戏中的),1个是角色跳跃移动脚本)
- unity3d 角色头顶信息3D&2D遮挡解决方案(二)
- Unity3D 摄像机跟随强烈抖动问题
- Unity3D里实现物体移动到目标点,并且摄像机跟着移动的简单方案
- 摄像机与主角之间遮挡显示处理(Unity3D开发之二十八)
- Unity摄像机跟随角色移动
- 【Unity快速实现小功能】动画系统学习小技巧篇(二)——摄像机跟随角色移动
- unity3D 摄像机跟随
- Unity3d 物体跟随鼠标移动
- Unity3D研究院之处理摄像机与角色之间被挡时的局部透明效果
- OGRE+PhysX仿魔兽世界摄像机(包含碰撞,跟随,防墙体穿透以及摄像头不被遮挡)的实现(10/7更新,封装了下)
- unity 相机跟随物体(角色)