您的位置:首页 > 移动开发 > Unity3D

unity3d_角色与障碍物遮挡

2015-06-03 19:07 459 查看
最近的项目有涉及到关于角色与障碍物的遮挡与显示问题:

个人能想到的解决方法有两种:

①从摄像机发射与角色连接射线,判断射线碰撞的go,将其材质改为半透明。

②shader

第一种方法:我有找到两篇相关的文章

1.雨松momo:http://www.xuanyusong.com/archives/1991

2.时间比较久,忘记出处了,不过是根据momo的文章改编的。

第二篇的代码:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class ObjectOcclusion : MonoBehaviour
{
//观察目标
public Transform Target;

//上次碰撞的物体
private List<GameObject> lastColliderObject = new List<GameObject>();
//本次碰撞到的物体
private List<GameObject> colliderObject = new List<GameObject>();

void LateUpdate()
{
//这里是计算射线的方向,从主角发射方向是射线机方向
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 中所有的值添加进 lastColliderObject
for (int i = 0; i < colliderObject.Count; i++)
lastColliderObject.Add(colliderObject[i]);

colliderObject.Clear();//清空本次碰撞到的所有物体

//获取碰撞到的所有物体
for (int i = 0; i < hit.Length; i++)
{
if(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);
}
}

//上次与本次对比,本次还存在的物体则赋值为null
for (int i = 0; i < lastColliderObject.Count; i++)
{
for (int j = 0; j < colliderObject.Count; j++)
{
if (colliderObject [j] != null)
{
if (lastColliderObject [i] == colliderObject [j])
{
lastColliderObject [i] = null;
break;
}
}
}
}

//当值为null时则可判断当前物体还处于遮挡状态
//值不为null时则可恢复默认状态(不透明)
for (int i = 0; i < lastColliderObject.Count; i++)
{
if (lastColliderObject [i] != null)
SetMaterialsColor (lastColliderObject [i].renderer, 1f);
}
}

//设置透明度
private void SetMaterialsColor(Renderer _renderer, float Transpa)
{
//获取当前物体材质球数量
int materialsNumber = _renderer.sharedMaterials.Length;

for (int i = 0; i < materialsNumber; i++)
{
//获取当前材质球颜色
Color color = _renderer.materials[i].color;

//设置透明度  取值范围:0~1;  0 = 完全透明
color.a = Transpa;

//置当前材质球颜色
_renderer.materials[i].SetColor("_Color", color);
//_renderer.materials[i].color = color;
}
}
}
此脚本,要先设置go的材质为“Transport/Diffuse”,嫌麻烦的话,可以在代码中动态更换。

缺陷:当go比较多,角色移动过去会有很明显的闪烁现象。

第二种方法:写shader,这是我一直想干的事,苦于能力不够,一直未能解决。

直到momo新更新了片文章:http://www.xuanyusong.com/archives/3466

momo的这篇文章也是转载的,同时也有改动

shader代码:

Shader "Custom/PlayerDiffuse" {
Properties {
_NotVisibleColor ("NotVisibleColor (RGB)", Color) = (0.3,0.3,0.3,1)
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "Queue" = "Geometry+500" "RenderType"="Opaque" }
LOD 200

Pass {
ZTest Greater
Lighting Off
ZWrite Off
//   Color [_NotVisibleColor]
Blend SrcAlpha OneMinusSrcAlpha
SetTexture [_MainTex] { ConstantColor [_NotVisibleColor] combine constant * texture }

}

Pass {
ZTest LEqual
Material {
Diffuse (1,1,1,1)
Ambient (1,1,1,1)
}
Lighting Off
SetTexture [_MainTex] { combine texture }
}

}
FallBack "Diffuse"
}
可以直接挂在角色上,可能会有违和感,只要稍稍改一下角色材质的透明度以及灰度值就好。

其实最初解决的办法是小伙伴想出来的:他有找一个雾化shader(笼罩整个场景),挂载2个main camera,一个用来渲染整个场景(包括角色),一个用来单独渲染角色。起初可以用,到后来不知为什么会出现bug,就是只显示渲染角色的camera的图像,没办法后面采用shader的方法来做。

差不多关于角色与障碍物的遮挡的显示就到这了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: