Unity3D_Camera摄像机跟随之物体遮挡处理方案
引言:想必大家都玩过RPG类型的游戏,那么有没有注意到当角色摄像机被物体遮挡后会怎样?游戏开发者当然不会就这样让角色一直被遮挡,否则那样你得有多难受啊(看不到角色、辨别不了方向),那你有没有想过是怎样处理的呢?细心的你肯定发现一般都是将遮挡物体置为透明,或者是将摄像机拉近(绝地求生?),接下来就讨论一下吧!
摄像机拉近
不多说了,注释很详细了
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LookAtObject : MonoBehaviour {
private Transform transformOfTargetObject;//目标物体
private Vector3 offset;//摄像机对于角色的差量
private Vector3 targetPosition;//计算后得到的摄像机位置
private float speed=5;//摄像机拉近速度
private bool isCloser=false;//控制是否拉近
private float dis;//用于记录当前距离,以判断是否达到不碰的临界
void Start () {
//初始化
transformOfTargetObject=GameObject.Find("Cube").GetComponent<Transform>();
offset=gameObject.transform.position-transformOfTargetObject.position;
dis=Vector3.Distance(gameObject.transform.position,transformOfTargetObject.position);
}
void Update () {
//获得由物体射向摄像机的射线以及碰到的所有物体hits
Vector3 dir = -(transformOfTargetObject.position - transform.position).normalized;
RaycastHit[] hits;
hits = Physics.RaycastAll(transformOfTargetObject.position, dir, Vector3.Distance(transformOfTargetObject.position,transform.position));
//有碰到且物体没有移走,就拉近
if(hits.Length>0&&dis>Vector3.Distance(gameObject.transform.position,transformOfTargetObject.position))
{
isCloser=true;
}
else
{
isCloser=false;
}
if(isCloser)
{
//拉近
gameObject.transform.position=Vector3.Lerp(gameObject.transform.position,hits[0].point,Time.deltaTime*speed);;
gameObject.transform.LookAt(transformOfTargetObject);
isCloser=false;
}
else
{
//正常跟随
targetPosition=transformOfTargetObject.position+transformOfTargetObject.TransformDirection(offset);
gameObject.transform.position=Vector3.Lerp(gameObject.transform.position,targetPosition,Time.deltaTime*speed);
gameObject.transform.LookAt(transformOfTargetObject);
}
}
}
结果:
二、置为透明
在第三人称摄像机跟随下进行测试(我的博客里有说过)摄像机跟随
不多说了,注释很详细了
在这里插入代码片using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CollisionHandling : MonoBehaviour {
public Transform player_Transform;//玩家角色
private List<GameObject> collideredObjects;//本次射线hit到的GameObject
private List<GameObject> bufferOfCollideredObjects;//上次射线hit到的GameObject
void Start () {
collideredObjects=new List<GameObject>();
bufferOfCollideredObjects=new List<GameObject>();
}
// Update is called once per frame
void Update () {
bufferOfCollideredObjects.Clear();
for(int temp=0;temp<collideredObjects.Count; temp++)
{
bufferOfCollideredObjects.Add(collideredObjects[temp]);//得到上次的
}
collideredObjects.Clear();
//发射射线
Vector3 dir = -(player_Transform.position - transform.position).normalized;
RaycastHit[] hits;
hits = Physics.RaycastAll(player_Transform.position, dir, Vector3.Distance(player_Transform.position,transform.position));
Debug.DrawLine(player_Transform.position, transform.position, Color.red);//让其显示以便观测
for(int i=0;i<hits.Length;i++)
{
if(hits[i].collider.gameObject.name!="Plane"&&hits[i].collider.gameObject.name!="Cube")
{
collideredObjects.Add(hits[i].collider.gameObject);//得到现在的
}
}
//把上次的还原,这次的透明
for(int i=0;i<bufferOfCollideredObjects.Count;i++)
{
SetMaterialsColor(bufferOfCollideredObjects[i].GetComponent<Renderer>(),false);
}
for(int i=0;i<collideredObjects.Count;i++)
{
SetMaterialsColor(collideredObjects[i].GetComponent<Renderer>(),true);
}
}
//是否搞透明
void SetMaterialsColor(Renderer r,bool isClear)
{
if(isClear)
{
int materialsNumber = r.sharedMaterials.Length;
for (int i = 0; i < materialsNumber; i++)
{
r.materials[i].shader = Shader.Find("Transparent/Diffuse");
Color tempColor = r.materials[i].color;
tempColor.a = 0.4f;
r.materials[i].color = tempColor;
}
}
else
{
int materialsNumber = r.sharedMaterials.Length;
for (int i = 0; i < materialsNumber; i++)
{
r.materials[i].shader = Shader.Find("Transparent/Diffuse");
Color tempColor = r.materials[i].color;
tempColor.a = 1f;
r.materials[i].color = tempColor;
}
}
}
}
结果: