在3D游戏开发的过程中,第三人称的摄像机是不可逃避的问题。
1.我先献上摄像机缩放,跟随,右键调节角度的代码:
主要是利用差值计算来改变位置,很简单,没什么可说的。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LookAtPlayer : MonoBehaviour {
private GameObject target;
private Vector3 offset;
void Start () {
target = GameObject.FindGameObjectWithTag("Player");
offset = target.transform.position - this.transform.position;
}
void LateUpdate()
{
this.transform.position = target.transform.position - offset;
Rotate();
Scale();
}
//缩放
private void Scale()
{
float dis = offset.magnitude;
dis += Input.GetAxis("Mouse ScrollWheel") * 5;
if (dis < 1.5f || dis > 5)
{
return;
}
offset = offset.normalized * dis;
}
//左右上下移动
private void Rotate()
{
if (Input.GetMouseButton(0))
{
Vector3 pos = transform.position;
Vector3 rot = transform.eulerAngles;
//围绕原点旋转,也可以将Vector3.zero改为 target.position,就是围绕观察对象旋转
transform.RotateAround(target.transform.position, Vector3.up, Input.GetAxis("Mouse X") * 10);
// transform.RotateAround(target.transform.position, Vector3.left, Input.GetAxis("Mouse Y") * 10);
float x = transform.eulerAngles.x;
// float y = transform.eulerAngles.y;
Debug.Log("x=" + x);
//Debug.Log("y=" + y);
//控制移动范围
if (x < 20 || x > 45)
{
transform.position = pos;
transform.eulerAngles = rot;
}
// 更新相对差值
offset = target.transform.position - this.transform.position;
}
}
}
2.献上视线受阻透明化处理的代码
基本原理就是从摄像机发出射线到主角或相反方向,射线碰撞到的gameObject组,改变其材质颜色的透明度。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraHandle : MonoBehaviour {
private Transform player_Transform;//玩家角色
private GameObject Player;
private List<GameObject> collideredObjects;//本次射线hit到的GameObject
private List<GameObject> bufferOfCollideredObjects;//上次射线hit到的GameObject
void Start () {
collideredObjects=new List<GameObject>();
bufferOfCollideredObjects=new List<GameObject>();
Player = GameObject.FindGameObjectWithTag("Player");
}
// Update is called once per frame
void Update () {
bufferOfCollideredObjects.Clear();
for(int temp=0;temp<collideredObjects.Count; temp++)
{
bufferOfCollideredObjects.Add(collideredObjects[temp]);//得到上次的
}
collideredObjects.Clear();
//发射射线
player_Transform = Player.transform;
Vector3 dir = (transform.position - player_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.tag!="Player")
{
collideredObjects.Add(hits[i].collider.gameObject);//得到现在的
SetMaterialsColor(collideredObjects[i].GetComponent<Renderer>(),true);
}
}
//上次与本次对比,本次还存在的物体则赋值为null
for (int i = 0; i < bufferOfCollideredObjects.Count; i++)
{
for (int j = 0; j < collideredObjects.Count; j++)
{
if (collideredObjects[j] != null)
{
if (bufferOfCollideredObjects[i].name == collideredObjects[j].name)
{
bufferOfCollideredObjects[i] = null;
break;
}
}
}
}
//把上次的还原,这次的透明
for (int i = 0; i < bufferOfCollideredObjects.Count; i++)
{
if (bufferOfCollideredObjects != null)
{
print(bufferOfCollideredObjects[i].name);
SetMaterialsColor(bufferOfCollideredObjects[i].GetComponent<Renderer>(),false);
}
}
}
//是否搞透明
void SetMaterialsColor(Renderer r,bool isClear)
{
if(isClear)
{
int materialsNumber = r.sharedMaterials.Length;
for (int i = 0; i < materialsNumber; i++)
{
Color _color = r.materials[i].color;
_color.a = 0.6f;
r.materials[i].SetColor("_Color", _color);
}
}
else
{
int materialsNumber = r.sharedMaterials.Length;
for (int i = 0; i < materialsNumber; i++)
{
Color _color = r.materials[i].color;
_color.a = 1.0f;
r.materials[i].SetColor("_Color", _color);
}
}
}
}
注意的是:如果本次遮挡物中存在上次遮挡物,则置为空,否则会存在闪烁问题。