zoukankan      html  css  js  c++  java
  • RPG角色相机控制

    using UnityEngine;
    using System.Collections;

    public class RPG_Camera : MonoBehaviour {

    public static RPG_Camera instance;

    public Transform cameraPivot;//相对人物的位置参考点,可以在任务头顶上
    public float distance = 5f;
    public float distanceMax = 30f;
    public float mouseSpeed = 8f;
    public float mouseScroll = 15f;
    public float mouseSmoothingFactor = 0.08f;
    public float camDistanceSpeed = 0.7f;
    public float camBottomDistance = 1f;
    public float firstPersonThreshold = 0.8f;
    public float characterFadeThreshold = 1.8f;

    private Vector3 desiredPosition;
    private float desiredDistance;
    private float lastDistance;
    private float mouseX = 0f;
    private float mouseXSmooth = 0f;
    private float mouseXVel;
    private float mouseY = 0f;
    private float mouseYSmooth = 0f;
    private float mouseYVel;
    private float mouseYMin = -89.5f;
    private float mouseYMax = 89.5f;
    private float distanceVel;
    private bool camBottom;
    private bool constraint;

    private static float halfFieldOfView;
    private static float planeAspect;
    private static float halfPlaneHeight;
    private static float halfPlaneWidth;

    void Awake() {
    instance = this;
    }


    void Start() {
    distance = Mathf.Clamp(distance, 0.05f, distanceMax);
    desiredDistance = distance;

    halfFieldOfView = (Camera.main.fieldOfView / 2) * Mathf.Deg2Rad;
    planeAspect = Camera.main.aspect;
    halfPlaneHeight = Camera.main.nearClipPlane * Mathf.Tan(halfFieldOfView);
    halfPlaneWidth = halfPlaneHeight * planeAspect;

    mouseX = 0f;
    mouseY = 15f;
    }


    public static void CameraSetup() {
    GameObject cameraUsed;
    GameObject cameraPivot;
    RPG_Camera cameraScript;

    if (Camera.main != null)
    cameraUsed = Camera.main.gameObject;
    else {
    cameraUsed = new GameObject("Main Camera");
    cameraUsed.AddComponent<Camera>();
    cameraUsed.tag = "MainCamera";
    }

    if (!cameraUsed.GetComponent("RPG_Camera"))
    cameraUsed.AddComponent<RPG_Camera>();
    cameraScript = cameraUsed.GetComponent("RPG_Camera") as RPG_Camera;

    cameraPivot = GameObject.Find("cameraPivot") as GameObject;
    cameraScript.cameraPivot = cameraPivot.transform;
    }


    void LateUpdate() {
    if (cameraPivot == null) {
    Debug.Log("Error: No cameraPivot found! Please read the manual for further instructions.");
    return;
    }

    GetInput();

    GetDesiredPosition();

    PositionUpdate();

    CharacterFade();
    }


    void GetInput() {

    if (distance > 0.1) { // distance > 0.05 would be too close, so 0.1 is fine
    Debug.DrawLine(transform.position, transform.position - Vector3.up * camBottomDistance, Color.green);
    camBottom = Physics.Linecast(transform.position, transform.position - Vector3.up * camBottomDistance);
    }

    bool constrainMouseY = camBottom && transform.position.y - cameraPivot.transform.position.y <= 0;

    if (Input.GetMouseButton(0) || Input.GetMouseButton(1)) {
    Cursor.visible = false; // if you want the cursor behavior of the version 1.0, change this line to "Screen.lockCursor = true;"

    mouseX += Input.GetAxis("Mouse X") * mouseSpeed;

    if (constrainMouseY) {
    if (Input.GetAxis("Mouse Y") < 0)
    mouseY -= Input.GetAxis("Mouse Y") * mouseSpeed;
    } else
    mouseY -= Input.GetAxis("Mouse Y") * mouseSpeed;
    } else
    Cursor.visible = true; // if you want the cursor behavior of the version 1.0, change this line to "Screen.lockCursor = false;"

    mouseY = ClampAngle(mouseY, -89.5f, 89.5f);
    mouseXSmooth = Mathf.SmoothDamp(mouseXSmooth, mouseX, ref mouseXVel, mouseSmoothingFactor);
    mouseYSmooth = Mathf.SmoothDamp(mouseYSmooth, mouseY, ref mouseYVel, mouseSmoothingFactor);

    if (constrainMouseY)
    mouseYMin = mouseY;
    else
    mouseYMin = -89.5f;

    mouseYSmooth = ClampAngle(mouseYSmooth, mouseYMin, mouseYMax);


    if (Input.GetMouseButton(1))
    RPG_Controller.instance.transform.rotation = Quaternion.Euler(RPG_Controller.instance.transform.eulerAngles.x, Camera.main.transform.eulerAngles.y, RPG_Controller.instance.transform.eulerAngles.z);

    desiredDistance = desiredDistance - Input.GetAxis("Mouse ScrollWheel") * mouseScroll;

    if (desiredDistance > distanceMax)
    desiredDistance = distanceMax;

    if (desiredDistance < 0.05)
    desiredDistance = 0.05f;
    }


    void GetDesiredPosition() {
    distance = desiredDistance;
    desiredPosition = GetCameraPosition(mouseYSmooth, mouseXSmooth, distance);

    float closestDistance;
    constraint = false;

    closestDistance = CheckCameraClipPlane(cameraPivot.position, desiredPosition);

    if (closestDistance != -1) {
    distance = closestDistance;
    desiredPosition = GetCameraPosition(mouseYSmooth, mouseXSmooth, distance);

    constraint = true;
    }


    distance -= Camera.main.nearClipPlane;

    if (lastDistance < distance || !constraint)
    distance = Mathf.SmoothDamp(lastDistance, distance, ref distanceVel, camDistanceSpeed);

    if (distance < 0.05)
    distance = 0.05f;

    lastDistance = distance;

    desiredPosition = GetCameraPosition(mouseYSmooth, mouseXSmooth, distance); // if the camera view was blocked, then this is the new "forced" position
    }


    void PositionUpdate() {
    transform.position = desiredPosition;

    if (distance > 0.05)
    transform.LookAt(cameraPivot);
    }


    void CharacterFade() {
    if (RPG_Animation.instance == null)
    return;

    if (distance < firstPersonThreshold)
    RPG_Animation.instance.GetComponent<Renderer>().enabled = false;

    else if (distance < characterFadeThreshold) {
    RPG_Animation.instance.GetComponent<Renderer>().enabled = true;

    float characterAlpha = 1 - (characterFadeThreshold - distance) / (characterFadeThreshold - firstPersonThreshold);
    if (RPG_Animation.instance.GetComponent<Renderer>().material.color.a != characterAlpha)
    RPG_Animation.instance.GetComponent<Renderer>().material.color = new Color(RPG_Animation.instance.GetComponent<Renderer>().material.color.r, RPG_Animation.instance.GetComponent<Renderer>().material.color.g, RPG_Animation.instance.GetComponent<Renderer>().material.color.b, characterAlpha);

    } else {

    RPG_Animation.instance.GetComponent<Renderer>().enabled = true;

    if (RPG_Animation.instance.GetComponent<Renderer>().material.color.a != 1)
    RPG_Animation.instance.GetComponent<Renderer>().material.color = new Color(RPG_Animation.instance.GetComponent<Renderer>().material.color.r, RPG_Animation.instance.GetComponent<Renderer>().material.color.g, RPG_Animation.instance.GetComponent<Renderer>().material.color.b, 1);
    }
    }


    Vector3 GetCameraPosition(float xAxis, float yAxis, float distance) {
    Vector3 offset = new Vector3(0, 0, -distance);
    Quaternion rotation = Quaternion.Euler(xAxis, yAxis, 0);
    return cameraPivot.position + rotation * offset;
    }


    float CheckCameraClipPlane(Vector3 from, Vector3 to) {
    var closestDistance = -1f;

    RaycastHit hitInfo;

    ClipPlaneVertexes clipPlane = GetClipPlaneAt(to);

    Debug.DrawLine(clipPlane.UpperLeft, clipPlane.UpperRight);
    Debug.DrawLine(clipPlane.UpperRight, clipPlane.LowerRight);
    Debug.DrawLine(clipPlane.LowerRight, clipPlane.LowerLeft);
    Debug.DrawLine(clipPlane.LowerLeft, clipPlane.UpperLeft);

    Debug.DrawLine(from, to, Color.red);
    Debug.DrawLine(from - transform.right * halfPlaneWidth + transform.up * halfPlaneHeight, clipPlane.UpperLeft, Color.cyan);
    Debug.DrawLine(from + transform.right * halfPlaneWidth + transform.up * halfPlaneHeight, clipPlane.UpperRight, Color.cyan);
    Debug.DrawLine(from - transform.right * halfPlaneWidth - transform.up * halfPlaneHeight, clipPlane.LowerLeft, Color.cyan);
    Debug.DrawLine(from + transform.right * halfPlaneWidth - transform.up * halfPlaneHeight, clipPlane.LowerRight, Color.cyan);


    if (Physics.Linecast(from, to, out hitInfo) && hitInfo.collider.tag != "Player")
    closestDistance = hitInfo.distance - Camera.main.nearClipPlane;

    if (Physics.Linecast(from - transform.right * halfPlaneWidth + transform.up * halfPlaneHeight, clipPlane.UpperLeft, out hitInfo) && hitInfo.collider.tag != "Player")
    if (hitInfo.distance < closestDistance || closestDistance == -1)
    closestDistance = Vector3.Distance(hitInfo.point + transform.right * halfPlaneWidth - transform.up * halfPlaneHeight, from);

    if (Physics.Linecast(from + transform.right * halfPlaneWidth + transform.up * halfPlaneHeight, clipPlane.UpperRight, out hitInfo) && hitInfo.collider.tag != "Player")
    if (hitInfo.distance < closestDistance || closestDistance == -1)
    closestDistance = Vector3.Distance(hitInfo.point - transform.right * halfPlaneWidth - transform.up * halfPlaneHeight, from);

    if (Physics.Linecast(from - transform.right * halfPlaneWidth - transform.up * halfPlaneHeight, clipPlane.LowerLeft, out hitInfo) && hitInfo.collider.tag != "Player")
    if (hitInfo.distance < closestDistance || closestDistance == -1)
    closestDistance = Vector3.Distance(hitInfo.point + transform.right * halfPlaneWidth + transform.up * halfPlaneHeight, from);

    if (Physics.Linecast(from + transform.right * halfPlaneWidth - transform.up * halfPlaneHeight, clipPlane.LowerRight, out hitInfo) && hitInfo.collider.tag != "Player")
    if (hitInfo.distance < closestDistance || closestDistance == -1)
    closestDistance = Vector3.Distance(hitInfo.point - transform.right * halfPlaneWidth + transform.up * halfPlaneHeight, from);


    return closestDistance;
    }


    float ClampAngle(float angle, float min, float max) {
    while (angle < -360 || angle > 360) {
    if (angle < -360)
    angle += 360;
    if (angle > 360)
    angle -= 360;
    }

    return Mathf.Clamp(angle, min, max);
    }


    public struct ClipPlaneVertexes {
    public Vector3 UpperLeft;
    public Vector3 UpperRight;
    public Vector3 LowerLeft;
    public Vector3 LowerRight;
    }


    public static ClipPlaneVertexes GetClipPlaneAt(Vector3 pos) {
    var clipPlane = new ClipPlaneVertexes();

    if (Camera.main == null)
    return clipPlane;

    Transform transform = Camera.main.transform;
    float offset = Camera.main.nearClipPlane;

    clipPlane.UpperLeft = pos - transform.right * halfPlaneWidth;
    clipPlane.UpperLeft += transform.up * halfPlaneHeight;
    clipPlane.UpperLeft += transform.forward * offset;

    clipPlane.UpperRight = pos + transform.right * halfPlaneWidth;
    clipPlane.UpperRight += transform.up * halfPlaneHeight;
    clipPlane.UpperRight += transform.forward * offset;

    clipPlane.LowerLeft = pos - transform.right * halfPlaneWidth;
    clipPlane.LowerLeft -= transform.up * halfPlaneHeight;
    clipPlane.LowerLeft += transform.forward * offset;

    clipPlane.LowerRight = pos + transform.right * halfPlaneWidth;
    clipPlane.LowerRight -= transform.up * halfPlaneHeight;
    clipPlane.LowerRight += transform.forward * offset;


    return clipPlane;
    }


    public void RotateWithCharacter() {
    float rotation = Input.GetAxis("Horizontal") * RPG_Controller.instance.turnSpeed;
    mouseX += rotation;
    }
    }

  • 相关阅读:
    git 远程仓库 and 分支管理
    oracle 导入导出dmp
    sql if else 用法
    设置session超时的三种方式
    eclipse定制工具栏,修改工具栏
    cxf实例异常
    js 表格插入指定行
    iframe 调用父页面元素
    iframe页面刷新
    frame 和 iframe
  • 原文地址:https://www.cnblogs.com/xwwFrank/p/4647464.html
Copyright © 2011-2022 走看看