为了实现角色被遮挡时,让遮挡物变透明的效果,就是下图的效果,我把墙体的材质设置成了透明模式,见下图:
材质渲染模式见下图:经过测试发现,只有将材质设置为这种,或者将shader改为任意一种Transparent路径下的一种,才能用代码去修改物体材质的alpha值,才能让物体变透明。。其他模式均不能透明。但是,这是了这种模式之后,就存在了下面的问题:
请看,当摄像机一定角度时(不一定什么角度总之很奇葩),设置了透明模式的物体渲染就会有问题,比如下面的:看上去貌似错位了一样。。
但是当你转一下摄像机角度,看上去就好像又变正常了。。。。
大神,麻烦赐教这是肿么回事,怎么避免这种情况??或者有什么其他的方法让物体变透明??
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraViewControll : MonoBehaviour {
[SerializeField]
private Transform m_target; // 目标
[SerializeField]
private float m_roteSpeed = 5.0f; // 视角旋转速度
[SerializeField]
private float m_zoomSpeed = 5.0f; // 视角缩放速度
private Vector3 m_offset; // 摄像机到角色的偏移
private RaycastHit[] m_lastHits; // 上次渲染时遮挡角色的物体(用于恢复透明度)
void Start () {
if (m_target == null) {
m_target = GameObject.Find ("Player").transform;
if (m_target == null) {
Debug.LogError ("Target Player Not Set");
}
}
transform.LookAt (m_target);
m_offset = transform.position - m_target.position;
}
// Update is called once per frame
void Update () {
// 重新计算位置
transform.position = m_offset + m_target.position;
// 右键按下时,处理视角旋转
if (Input.GetMouseButton (1)) {
Vector3 pos = transform.position;
Quaternion rot = transform.rotation;
float h = Input.GetAxis ("Mouse X");
float v = - Input.GetAxis ("Mouse Y");
transform.RotateAround (m_target.position, m_target.up, h * m_roteSpeed );
transform.RotateAround (m_target.position, transform.right, v * m_roteSpeed );
float a = transform.rotation.eulerAngles.x;
if (a <= 10 || a >= 80) {
transform.position = pos;
transform.rotation = rot;
} else {
m_offset = transform.position - m_target.position;
}
}
// 处理视角缩放
float d = - Input.GetAxis ("Mouse ScrollWheel");
if (d > 0.01f || d < -0.01f) {
float distance = m_offset.magnitude;
distance = Mathf.Clamp ( distance + d * m_zoomSpeed, 3, 20 );
transform.position = ( m_offset.normalized * distance ) + m_target.position;
m_offset = transform.position - m_target.position;
}
// 判断遮挡
CheckMask();
}
void CheckMask()
{
// 用射线检测所有挡在摄像机和角色之间的物体。
RaycastHit[] hits = Physics.RaycastAll(m_target.position, m_offset.normalized, m_offset.magnitude );
// 如果上次保存了遮挡物,求出上次跟这次的差集,就是说上次遮挡了但这次没遮挡的物体,然后恢复他们的透明度。
if( m_lastHits != null && m_lastHits.Length > 0 )
{
if (hits.Length > 0)
{
var needShow = m_lastHits.Except(hits);
foreach (var i in needShow)
{
SetTransparent( i.transform.GetComponent<Renderer>(), 1);
}
}
else
{
foreach( var i in m_lastHits )
{
SetTransparent(i.transform.GetComponent<Renderer>(), 1);
}
}
}
// 如果本次检测到有遮挡物体,求出本次与上次遮挡物的差集,就是说新增的遮挡物,设置他们的透明度为0.3
if (hits.Length > 0)
{
if( m_lastHits == null || m_lastHits.Length <= 0 )
{
foreach( var i in hits )
{
SetTransparent(i.transform.GetComponent<Renderer>(), 0.3f);
}
}
else
{
var needHide = hits.Except(m_lastHits);
foreach( var i in needHide )
{
SetTransparent(i.transform.GetComponent<Renderer>(), 0.3f);
}
}
}
// 保存本次的遮挡物列表
m_lastHits = hits;
}
// 设置物体材质的透明度
void SetTransparent( Renderer render, float alpha )
{
for( int i = render.sharedMaterials.Length - 1; i >= 0; -- i )
{
Color col = render.materials[i].color;
col.a = alpha;
render.materials[i].SetColor("_Color", col);
}
}
}
另外,附上我摄像机控制的代码,还有变透明代码: