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;
}
}

时间: 2024-12-19 12:48:33

RPG角色相机控制的相关文章

Unity3D第三视觉角色相机控制

经过一段时间的学习,学得以下第三视觉相机控制方法,当设置相机初始高度较高的状态下,相机有由高到低的效果,适合做为外景相机,如果是做室内相机,需要另外设计.将这个分享给大家,同时希望得到阅读者宝贵的意见,废话不多说,贴代码: /// <summary> /// Created by Hong Youwei /// Created in 2015.3.25 /// </summary> using UnityEngine; using System.Collections; publi

Unity 2D游戏相机控制(水平,竖直,角色居中三种模式)

做2D游戏的时候,无非有三种模式,一种是只有竖直向上,一种是只有水平方向,一种是有水平又有竖直方向,我最近做游戏多关卡模式,不同模式就有着不一样的相机控制,按照平时的写法,也许有很多人就一下子写了三个相机脚本,现在我用了一个枚举类型来控制三个不一样的相机,贴代码: /// <summary> ///CameraCtrl ///Created by Wang YuTing /// </summary> using UnityEngine; using System.Collectio

unity3d 第三人称视角的人物移动以及相机控制

何谓第三人称?就像这样: 用wasd控制人物移动,同时保持在相机的中心.用鼠标右键与滚轮控制相机的角度和距离. 先说一下人物的移动: 首先给作为主角的单位加上 Charactor Controller组件,并调整胶囊型的碰撞体刚好包裹住主角(有其是脚底,除非你想看到你的主角能遁地,或飞行) 然后给你的人物加上控制的脚本~ using UnityEngine; using System.Collections; public class move_controll : MonoBehaviour

Unity之2D游戏界面相机控制

之前写的关于2D游戏界面相机的水平.竖直.以人为中心三种模式的相机控制,我写着写着,总感觉相机适配有点繁琐,而且适配得不怎么好,多平台的时候因为资源有限我也不知道有没有完全适配,今天给大家分享一下我今天写的一个2D游戏场景相机适配,感觉挺好的,有需要的可以用着试试看,接下来我贴上代码: using UnityEngine; using System.Collections; public class CameraControl_2D : MonoBehaviour { // 默认屏幕大小 flo

OpenGL教程翻译 第十五课 相机控制(二)

OpenGL教程翻译 第十五课 相机控制(二) 原文地址:http://ogldev.atspace.co.uk/(源码请从原文主页下载) Background 在这一节中我们将使用鼠标来控制相机的方向,从而得我们的相机控制更加完善.相机有不同的自由程度,这与其设计有关.在本教程中我们将要实现的是与第一人称游戏中相似的相机控制(如枪战类游戏).这意味着我们将可以使相机完成360度的旋转(绕着Y轴),这与我们的头部向左转向右转.身体转一整圈类似.除此之外我们也能使相机向上或者向下倾斜以获得更好的向

OpenGL教程翻译 第十四课 相机控制(一)

OpenGL教程翻译 第十四课 相机控制(一) 原文地址:http://ogldev.atspace.co.uk/(源码请从原文主页下载) Background 在之前的教程中我们学习了如何在三维场景中的任何地方放置相机.那么我们下一步就应该学着去控制这个相机.相机可以向任何方向自由移动.我们可以用鼠标和键盘控制相机--鼠标控制视口方向,键盘控制我们的位置.这些都和第一人称视角相似.这一章我们主要来学习鼠标和键盘的控制. 我们仍然使用上下左右四个方向键.记住,我们的相机的变换取决于位置.targ

基于K8s Jenkins CICD和RBAC角色权限控制

说明 最近在做 k8s 相关迁移工作,对于 k8s 权限控制和流程自动化方面参考了一些大佬的文章.下面分享些经典实例文章, 望大家共同进步- 分享 k8s系列教程3 - 安全管理(认证和授权) 上文介绍了一些加密和解密一些原理,k8s 授权结构和原理,大家可以参考下- Kubernetes RBAC角色权限控制 上文是 k8s 角色授权控制经典实例文章,重点了解下- 基于Kubernetes Jenkins CICD 上文基于 Jenkins 流程自动化可以参考下,结合上面两篇文章可以更加深入了

php_ThinkPHP的RBAC(基于角色权限控制)详解

一.什么是RBAC 基于角色的访问控制(Role-Based Access Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注. 在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限.这就极大地简化了权限的管理. 在一个组织中,角色是为了完成各种工作而创造,用户则依据它的责任和资格来被指派相应的角色,用户可以很容易地从一个角色被指派到另一个角色.角色可依新的需求和系统的合并而赋予新的权限,而权限也可根据需要而从某角色中回收.角色与角色的关

Opengl_12_相机控制

1,使用键盘控制位置的移动没有使用glutSpecialFunc,glutKeyboardFunc因为我这个win32程序. 2,相机类里面定义了相机的三个方向成员:位置(position),target向量和up向量前后移动是最简单的,因为这俩种移动方向和tartget向量在一条线上,我们只需要从起始位置加上或者减去一定数量的tartget向量即可实现前后移动,target向量本身不会变化.在加减之前我们是使用一个常量'步长' const static float STEP_SCALE = 1