相机围绕物体旋转,并且有Y轴角度限制

相机围绕物体旋转,并且有Y轴角度限制,可通过parameters.offset 修改使目标物不在画面中心

using UnityEngine;

using System.Collections;

using System.Collections.Generic;

using UnityEngine.EventSystems;

using UnityEngine.UI;

public class CameraController : MonoBehaviour

{

public static CameraController instance;

public Transform ModelRoot; //目标物

public Transform[] targets; //空物体

HideInInspector

public int index; // 当前的场景

private int comeBack = 0; // 返回主页计数

private Transform curtarget; // 当前摄像机锁定的目标

复制代码
[System.Serializable]
public class CameraParameters 
{
    public bool smoothFollow;   //  是否开启平滑跟随
    public float followSpeed;   // 跟随速度
    public float distance;      // 相机的初始距离
    public float minDistance;   // 最小距离
    public float maxDistance;   // 最大距离
    public float zoomSpeed;     // 缩放速度
    public float zoomSensitivity;     // 缩放灵敏度
    public float rotationSensitivity; // 旋转灵敏度
    public float yMinLimit; // 垂直最小值
    public float yMaxLimit; // 垂直最大值
    public Vector3 offset;  // 偏移量

    public float inFade = 0.6f;     //  材质淡入
    public float outFade = 1.0f;    //  材质淡出
}

public CameraParameters parameters;  //  相机相关参数

public float x { get; private set; } // 相机X方向旋转量
public float y { get; private set; } // 相机Y方向旋转量
public float distanceTarget { get; private set; } // 目标距离 

private Vector3 position;
private Quaternion rotation = Quaternion.identity;
private Vector3 smoothPosition;
private Camera cam;
[HideInInspector]
public bool isRay = true;  //  射线检测开关,在主场景才开启射线拾取
private GameObject rayTarget;
//  设备开机相关参数
public static bool isStart = false;

void Awake()
{
    instance = this;
    parameters = new CameraParameters();
    InitCameraParaDefault();  //    设置相机的默认参数

    index = 0;
    curtarget = targets[index];
    Vector3 angles = transform.eulerAngles;
    x = angles.y;
    y = angles.x;
    //目标距离
    distanceTarget = parameters.distance;
    smoothPosition = transform.position;

    cam = Camera.main;
}

void Update()
{
    if (isRay)
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//从摄像机发出到点击坐标的射线
        RaycastHit hitInfo;
        if (Physics.Raycast(ray, out hitInfo))
        {
            Debug.DrawLine(ray.origin, hitInfo.point, Color.blue);//划出射线,只有在scene视图中才能看到

            rayTarget = hitInfo.collider.gameObject;
        }
        else
        {
            rayTarget = null;
        }
    }

    UpdateTransform();
}


#region 相机控制脚本
//  默认的相机参数设置
private void InitCameraParaDefault()
{
    parameters.smoothFollow = false;
    parameters.followSpeed = 2.0f;
    parameters.minDistance = 0.0f;
    parameters.maxDistance = 10.0f;
    parameters.distance = 2f;
    parameters.zoomSpeed = 10.0f;
    parameters.zoomSensitivity = 1.0f;
    parameters.rotationSensitivity = 3.5f;
    parameters.yMinLimit = 0;
    parameters.yMaxLimit = 8;
    parameters.offset = new Vector3(-1.31f, 0.18f, -10.44f);

}

//  单个模型场景的相机参数设置 
/// <summary>
/// maxDistance参数大于或等于distance参数
/// </summary>
/// <param name="distance"></param>
/// <param name="minDistance"></param>
/// <param name="maxDistance"></param>
/// <param name="offsetY"></param>
private void InitCameraParaOneModel(float distance, float minDistance, float maxDistance, float offsetY = 0.0f)
{
    parameters.smoothFollow = false;
    parameters.followSpeed = 5.0f;
    parameters.minDistance = minDistance;
    parameters.maxDistance = maxDistance;
    parameters.distance = distance;
    parameters.zoomSpeed = 5.0f;
    parameters.zoomSensitivity = 1.0f;
    parameters.rotationSensitivity = 3.5f;
    parameters.yMinLimit = 0;
    parameters.yMaxLimit = 8;
    parameters.offset = new Vector3(0.0f, offsetY, 0.0f);
}
void LateUpdate()
{
    UpdateInput();
}

// 获取用户鼠标信息
public void UpdateInput()
{
    if (curtarget == null || !cam.enabled) return;

    bool rotate = Input.GetMouseButton(0);  //  判断鼠标是否右键按下

    //delta rotation
    if (rotate)
    {
        x += Input.GetAxis("Mouse X") * parameters.rotationSensitivity;
        y = ClampAngle(y - Input.GetAxis("Mouse Y") * parameters.rotationSensitivity, parameters.yMinLimit, parameters.yMaxLimit);
    }

    // Distance
    distanceTarget = Mathf.Clamp(distanceTarget + zoomAdd, parameters.minDistance, parameters.maxDistance);
}

// 更新相机位置
public void UpdateTransform()
{
    UpdateTransform(Time.deltaTime);
}

public void UpdateTransform(float deltaTime)
{
    if (curtarget == null || !cam.enabled) return;

    // Distance
    parameters.distance += (distanceTarget - parameters.distance) * parameters.zoomSpeed * deltaTime;
    // Rotation 
    rotation = Quaternion.AngleAxis(x, Vector3.up) * Quaternion.AngleAxis(y, Vector3.right);

    // Smooth follow
    if (!parameters.smoothFollow) smoothPosition = curtarget.position;
    else smoothPosition = Vector3.Lerp(smoothPosition, curtarget.position, deltaTime * parameters.followSpeed);

    // Position
    position = smoothPosition + rotation * (parameters.offset - Vector3.forward * parameters.distance);

    // Translating the camera
    transform.position = position;
    transform.rotation = rotation;
}

// Zoom input  放大缩小
private float zoomAdd
{
    get
    {
        float scrollAxis = Input.GetAxis("Mouse ScrollWheel");

        if (scrollAxis > 0) return -parameters.zoomSensitivity;
        if (scrollAxis < 0) return parameters.zoomSensitivity;
        return 0;
    }
}

// Clamping Euler angles
private float ClampAngle(float angle, float min, float max)
{
    if (angle < -360) angle += 360;
    if (angle > 360) angle -= 360;
    return Mathf.Clamp(angle, min, max);
}
#endregion

}

相关推荐
ghost1432 小时前
C#学习第22天:网络编程
开发语言·学习·c#
神仙别闹3 小时前
基于C#实现中央定位服务器的 P2P 网络聊天系统
服务器·网络·c#
阿蒙Amon4 小时前
DevExpress&WinForms-TreeList-数据绑定
c#·devexpress·winforms
慢一点会很快5 小时前
【FFmpeg】介绍+安装+VisualStudio配置FFMpeg库
ide·ffmpeg·visual studio
bicijinlian6 小时前
.Net HttpClient 使用代理功能
c#·.net·httpclient·.net httpclient·httpclient 代理
敲代码的 蜡笔小新10 小时前
【行为型之中介者模式】游戏开发实战——Unity复杂系统协调与通信架构的核心秘诀
unity·设计模式·c#·中介者模式
程序猿多布10 小时前
使用Visual Studio将C#程序发布为.exe文件
c#·visual studio
老衲有点帅12 小时前
C#多线程Thread
开发语言·c#
PascalMing13 小时前
C# 通过脚本实现接口
c#·codeanalysis·接口派生
敲代码的 蜡笔小新17 小时前
【行为型之观察者模式】游戏开发实战——Unity事件驱动架构的核心实现策略
观察者模式·unity·设计模式·c#