Unity - A计划(永久有效期) 扫二维码继续学习 二维码时效为半小时

(197评价)
价格: 4431.00元
siki老师以及各位大神,麻烦看看这个是肿么个情况??
sdhexu发起了话题2017-06-13
4
回复
475
浏览

为了实现角色被遮挡时,让遮挡物变透明的效果,就是下图的效果,我把墙体的材质设置成了透明模式,见下图:

材质渲染模式见下图:经过测试发现,只有将材质设置为这种,或者将shader改为任意一种Transparent路径下的一种,才能用代码去修改物体材质的alpha值,才能让物体变透明。。其他模式均不能透明。但是,这是了这种模式之后,就存在了下面的问题:


请看,当摄像机一定角度时(不一定什么角度总之很奇葩),设置了透明模式的物体渲染就会有问题,比如下面的:看上去貌似错位了一样。。


但是当你转一下摄像机角度,看上去就好像又变正常了。。。。


大神,麻烦赐教这是肿么回事,怎么避免这种情况??或者有什么其他的方法让物体变透明??

所有回复
  • sdhexu 2017-06-13
    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);
            }
        }
    }
    

    另外,附上我摄像机控制的代码,还有变透明代码:

     

    还有-5条回复,点击查看
    你还没有登录,请先登录注册
  • siki 2017-06-13

    可以使用这个半透明的插件

    https://www.assetstore.unity3d.com/en/#!/content/24707

    也可以在淘宝或者百度找找破解版本

    还有-5条回复,点击查看
    你还没有登录,请先登录注册
  • siki 2017-06-13

    你的这个设置为半透明后,渲染的先后顺序错乱了,先渲染右边的墙,这样就显示的很奇怪

    • sdhexu 2017-06-14

      您推荐的这个工具貌似挺强大,但是研究了半天还是没有研究好。。。

      (0) 回复
    还有-4条回复,点击查看
    你还没有登录,请先登录注册
发表回复
你还没有登录,请先 登录或 注册!