2017-08-01 10:19:34 BattleTiger 阅读数 5365

1.向量转四元数
Quaternion.LookRotation(dir);—>返回值就是一个四元数
2.开始旋转
transform.rotation = Quaternion.Lerp(当前的四元数, 目标四元数, 旋转的速度);
3.普通相机跟随

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

public class CameraMovement : MonoBehaviour {
    /// <summary>
    /// 跟随目标
    /// </summary>
    public Transform followTarget;
    /// <summary>
    /// 方向向量
    /// </summary>
    private Vector3 dir;

    private void Start()
    {
        //获取方向向量
        dir = transform.position - followTarget.position;
    }

    private void Update()
    {
        transform.position = dir + followTarget.position;
    }

}

4.高级相机跟随,保证看到目标的相机最佳视角

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

public class CameraMovement : MonoBehaviour {

    /// <summary>
    /// 俯视距离的偏移量
    /// </summary>
    public float offset = 0.5f;
    /// <summary>
    /// 设置中间的相机位置个数
    /// </summary>
    public int gears = 5;
    /// <summary>
    /// 跟随目标
    /// </summary>
    public Transform followTarget;
    /// <summary>
    /// 方向向量
    /// </summary>
    private Vector3 dir;
    /// <summary>
    /// 待选的相机位置(观察点)
    /// </summary>
    private Vector3[] readyPosition;
    /// <summary>
    /// 射线碰撞检测器
    /// </summary>
    private RaycastHit hit;
    /// <summary>
    /// 相机跟随的移动速度
    /// </summary>
    public int moveSpeed = 1;
    /// <summary>
    /// 相机旋转的速度
    /// </summary>
    public float turnSpeed = 10f;
    private void Start()
    {
        //获取方向向量
        dir = transform.position - followTarget.position;
        //实例化观察点数组
        readyPosition = new Vector3[gears];

    }

    private void Update()
    {
        //相机的起点--->相机最佳视角
        Vector3 begin = dir + followTarget.position;
        //相机的终点--->相机最差视角保证能看到玩家
        Vector3 end = followTarget.position + Vector3.up * (dir.magnitude - offset);
        //把起点和终点放到观察点的数组中
        readyPosition[0] = begin;
        readyPosition[readyPosition.Length - 1] = end;
        //获取相机中间点的位置
        for (int i = 1; i < readyPosition.Length - 1; i++)
        {
            //求中间点各个点的坐标,比例为i / (gears - 1)
            readyPosition[i] = Vector3.Lerp(begin, end, i / (readyPosition.Length - 1));
        }
        //备选方案--->前面所有的观察点都看不到玩家
        //都看不到就把相机放到最佳视角
        Vector3 watchPoint = begin;
        //遍历观察点数组,挑选我们最佳观察点
        for (int i = 0; i < readyPosition.Length; i++)
        {
            if (CheckWatchPoint(readyPosition[i]))
            {
                //设置观察点
                watchPoint = readyPosition[i];
                //得到观察点退出循环
                break;
            }
        }
        //相机平滑移动到最佳观察点
        transform.position = Vector3.Lerp(transform.position, watchPoint, Time.deltaTime * moveSpeed);
        /*
          //旋转的不是很平滑
          //相机旋转到最佳角度看向玩家
          transform.LookAt(followTarget);
         */
        //获取方向向量
        Vector3 lookDir = followTarget.position - watchPoint;
        //获取四元数
        Quaternion lookQua = Quaternion.LookRotation(lookDir);
        //平滑转向玩家
        transform.rotation = Quaternion.Lerp(transform.rotation, lookQua, Time.deltaTime * turnSpeed);
        //固定相机y轴z轴的旋转
        transform.eulerAngles = new Vector3(transform.eulerAngles.x, 0, 0);

    }
    /// <summary>
    /// 检测观察点是否可以看到目标
    /// </summary>
    /// <param name="point">待选的观察点</param>
    /// <returns><c>true</c>看得到<c>false</c>看不到</returns>
    bool CheckWatchPoint(Vector3 point)
    {
        if (Physics.Raycast(point,followTarget.position - point,out hit))
        {
            //如果射线检测到的是玩家
            if (hit.collider.tag == "Player")
            {
                return true;
            }
        }

        return false;
    }

}

相机跟随一直观察角色背部

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

public class CameraFollow : MonoBehaviour {

    public Transform target;
    public float distanceUp = 5f;
    public float distanceAway = 5f;
    public float smooth = 2f;//位置平滑移动值
    public float camDepthSmooth = 2f;
    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        // 鼠标轴控制相机的远近
        if ((Input.mouseScrollDelta.y < 0 && Camera.main.fieldOfView >= 3) || Input.mouseScrollDelta.y > 0 && Camera.main.fieldOfView <= 80)
        {
            Camera.main.fieldOfView += Input.mouseScrollDelta.y * camDepthSmooth * Time.deltaTime;
        }

    }

    void LateUpdate()
    {
        //相机的位置
        Vector3 disPos = target.position + Vector3.up * distanceUp - target.forward * distanceAway;
        transform.position = Vector3.Lerp(transform.position, disPos, Time.deltaTime * smooth);
        //相机的角度
        transform.LookAt(target.position);
    }


}
2018-07-29 17:46:14 w_BlackPanda 阅读数 217

一个简单的相机跟随

先定义其中需要的变量

变量target就是相机的跟随目标

这个方法用于设置跟随目标,一般在跟随物体的子物体下创建一个CamPoint作为目标;

在LateUpdate中设置相机位置,旋转

可以在这里添加判断按下鼠标旋转

最后调节距离的方法

2016-09-21 14:45:11 xzr1526 阅读数 3032

将该脚本挂在要跟随的camera上

将要被跟随的目标设为target,就可以实现了

using UnityEngine;
using System.Collections;

public class FollowTaget : MonoBehaviour
{

    public Transform target;//目标

    private Transform mRoot;//相机

    [SerializeField]
    private float moveSpeed = 5;

    private Vector3 offset;//目标与相机的距离

    void Awake()
    {
        mRoot = this.transform;
        offset = mRoot.position - target.position;
    }

    void LateUpdate()
    {
        mRoot.position = Vector3.Lerp(mRoot.position, target.position + offset, moveSpeed * Time.deltaTime);
    }
}


2018-08-10 13:38:33 ChengTong007 阅读数 2541

在网上搜到的,在这里记录下,以后用,如果有侵权的地方,谅解下!!!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
public class MouseLook : MonoBehaviour 
{
    //定义镜头与角色的初始距离,开始的时候定义成私有变量,我改成公有变量,为了方便在代码面板上修改
    public float m_distanceAway = 4.5f;
    //镜头初始高度
    public float m_distanceUp = 1.5f;
    //镜头改变时的平滑度
    private float m_smooth = 5f;
    //玩家对象
    public Transform m_player;
    //自己
    private Transform m_transsform;
 
    private float maxSuo = 100.0f;//镜头缩放范围
    private float minSuo = 2.0f;
 
    private float maxSD = 20.0f;
    private float minSD = 1f;
    void Start () 
    {
        m_transsform = this.transform;//定义自己
        m_player = GameObject.Find("Player").transform;
    }
    
    
    void Update () 
    {
        Zoom();//缩放
        CameraSet();//相机设置
        //定义一条射线
        RaycastHit hit;
        if (Physics.Linecast(m_player.position + Vector3.up,m_transsform.position,out hit))
        {
            string name = hit.collider.gameObject.tag;
            if (name != "MainCamera")
            {
                //如果射线碰撞的不是相机,那么就取得射线碰撞点到玩家的距离
                float currentDistance = Vector3.Distance(hit.point,m_player.position);
                //如果射线碰撞点小于玩家与相机本来的距离,就说明角色身后是有东西,为了避免穿墙,就把相机拉近
                if (currentDistance < m_distanceAway)
                {
                    m_transsform.position = hit.point;
                }
            }
        }
    }
    /// <summary>
    /// 设置相机
    /// </summary>
    void CameraSet()
    {
        //取得相机旋转的角度
        float m_wangtedRotationAngel = m_player.transform.eulerAngles.y;
        //获取相机移动的高度
        float m_wangtedHeight = m_player.transform.position.y + m_distanceUp;
        //获得相机当前角度
        float m_currentRotationAngle = m_transsform.eulerAngles.y;
        //获取相机当前的高度
        float m_currentHeight = m_transsform.position.y;
        //在一定时间内将当前角度更改为角色面对的角度
        m_currentRotationAngle = Mathf.LerpAngle(m_currentRotationAngle, m_wangtedRotationAngel, m_smooth * Time.deltaTime);
        //更改当前高度
        m_currentHeight = Mathf.Lerp(m_currentHeight, m_wangtedHeight, m_smooth * Time.deltaTime);
        //返回一个Y轴旋转玩家当前角度那么多的度数
        Quaternion m_currentRotation = Quaternion.Euler(0, m_currentRotationAngle, 0);
        //玩家的位置
        Vector3 m_position = m_player.transform.position;
        //相机位置差不多计算出来了
        m_position -= m_currentRotation * Vector3.forward * m_distanceAway;
        //将相机应当到达的高度加进应当到达的坐标,这就是相机的新位置
        m_position = new Vector3(m_position.x, m_currentHeight, m_position.z);
        m_transsform.position = Vector3.Lerp(m_transsform.position, m_position, Time.time);
        //注视玩家
        m_transsform.LookAt(m_player);
    }
 
    /// <summary>
    /// 按鼠标滚轮缩放
    /// </summary>
    void Zoom()
    {
        //实现滑轮拖动
        if (Input.GetAxis("Mouse ScrollWheel") < 0)
        {
            if (Camera.main.fieldOfView <= maxSuo)//缩放的范围
            {
                Camera.main.fieldOfView += 2;
            }
            if (Camera.main.orthographicSize <= maxSD)
            {
                Camera.main.orthographicSize += 0.5f;
            }
        }
 
        //Zoom in
        if (Input.GetAxis("Mouse ScrollWheel") > 0)
        {
            if (Camera.main.fieldOfView >= minSuo)
            {
                Camera.main.fieldOfView -= 2;
            }
            if (Camera.main.orthographicSize >= minSD)
            {
                Camera.main.orthographicSize -= 0.5f;
            }
        }
    }
}
 

2017-07-14 15:14:39 GaoHeShun 阅读数 3486

    去年在一个项目中遇到摄像机的跟随问题,摄像机跟随方式有成千上百种,那么怎样让Camera始终能够看到玩家,而不被游戏中的场景遮挡住?

在网上看到很多例子,大部分使用了插值,有的是当遮挡物遮挡Canera以后拉近和玩家的距离,我个人感觉这对于Player模型细腻的游戏来说还好,但是如果是一些轻型的游戏来说,就会有点尴尬,因为当遮挡物距离玩家很近的话,摄像机会和player拉的很近,所以完全报漏了模型的粗糙程度.后来参考了Unity官方教程<<秘密行动>>里面的Camera跟随方案,今天把它摘出来分享一下,希望对大家伙有所帮助:

大体的原理:

   不改变摄像机和Player距离,改变角度.在player的正上方和正后方四分之一圆的范围内进行插值.


当有遮挡物时候:摄像机会从事先从预设的点里面找到可以看到player的点,然后继续跟随player,如图,位置3是Camera的最佳位置


具体实现:

using UnityEngine;
using System.Collections;


public class CameraMovement : MonoBehaviour  //将这个脚本附加到你的maincamera(或其他任何你想使用的相机)
{
	//这个脚本使用Unity秘密教程中引入的一些概念。

	public float smooth = 1.5f;         //照相机能赶上的相对速度。
	
	
	private Transform ball;           // The ball's position.
	private Vector3 relativeCameraPosition;       // 摄像机相对于球得点
	private float relativeCameraDistance;      // 摄像机现对于球 的距离
	private Vector3 newCameraPosition;             // 新位置点是否能到达摄像机
	
	
	void Start ()
	{
		// Set up the values that remain unchanged during the entire level

		//设置在整个级别中保持不变的值。 
		ball = GameObject.FindGameObjectWithTag(Tags.ball).transform;
		if (ball == null) {Debug.LogError ("<color=blue>Marble Kit error:</color>: There needs exactly one object with the tag 'Ball' in the scene");}

		relativeCameraPosition = transform.position - ball.position;//摄像机的相对位置
		relativeCameraDistance = relativeCameraPosition.magnitude - 0.5f; // to look (roughly) at the center of the ball (1m ball size)摄像机看向求得距离
	}
	
	
	void FixedUpdate ()
	{
		//摄影机在FixedUpdate(因为游戏物理将在FixedUpdate,球移动相机应该做的)
		Vector3 standardPosition = ball.position + relativeCameraPosition; // 获得当前摄像机的目标位置
		Vector3 topPosition = ball.position + Vector3.up * relativeCameraDistance; //直接在球顶上取得位置
		
		//  在标准位置和顶部位置之间放置一组可能的摄像机位置。
		//  
		//如果相机不能从标准位置看到玩家,它会尝试所有其他位置,直到它可以看到球员againn。

		Vector3[] cameraPoints = new Vector3[5];

		cameraPoints[0] = standardPosition;
		cameraPoints[1] = Vector3.Lerp(standardPosition, topPosition, 0.25f); // Lerp is used here to interpolate
		cameraPoints[2] = Vector3.Lerp(standardPosition, topPosition, 0.5f);  // 0, 25, 50, 75, 100% the line between standard and top position
		cameraPoints[3] = Vector3.Lerp(standardPosition, topPosition, 0.75f);
		cameraPoints[4] = topPosition;
		
		//检查所有相机点,直到摄像机看到球。
		for(int i = 0; i < cameraPoints.Length; i++)
		{
			if(CameraSeesBall(cameraPoints[i]))
				break;
		}
		
		// Smoothly transition to the new camera point over time平稳过渡到新相机点随着时间的推移
		transform.position = Vector3.Lerp(transform.position, newCameraPosition, smooth * Time.deltaTime);
		
		// Reposition camera to look at the ball
		CameraLookAtBall();
	}
	
	
	bool CameraSeesBall (Vector3 checkPosition)
	{
		RaycastHit hit;
		
		//Raycast from Camera to the ball and see if it finds it

		if(Physics.Raycast(checkPosition, ball.position - checkPosition, out hit,relativeCameraDistance))
			if(hit.transform != ball)
				return false;
		
		//this is the new position for the camera
		newCameraPosition = checkPosition;
		return true;
	}
	
	
	void CameraLookAtBall()
	{
		// 创建一个向量和旋转从相机向玩家。
		Vector3 relativeBallPosition = ball.position - transform.position;
		Quaternion lookAtRotation = Quaternion.LookRotation(relativeBallPosition, Vector3.up);
		
		//平滑调整相机
		transform.rotation = Quaternion.Lerp(transform.rotation, lookAtRotation, smooth * Time.deltaTime);
	}
}


以上代码参考了官方案例"秘密行动"

没有更多推荐了,返回首页