赞
踩
using UnityEngine; public class PlayerController : MonoBehaviour { //[SerializeField] //Transform playerInputSpace = default; [SerializeField, Range(0f, 100f)] float maxSpeed = 10f; [SerializeField, Range(0f, 100f)] float maxAcceleration = 10f, maxAirAcceleration = 1f; [SerializeField, Range(0f, 10f)] float jumpHeight = 2f; [SerializeField, Range(0, 5)] int maxAirJumps = 0; [SerializeField, Range(0, 90)] float maxGroundAngle = 25f, maxStairsAngle = 50f; [SerializeField, Range(0f, 100f)] float maxSnapSpeed = 100f; [SerializeField, Min(0f)] float probeDistance = 1f; [SerializeField] LayerMask probeMask = -1, stairsMask = -1; Rigidbody body; Vector3 velocity, desiredVelocity; bool desiredJump; Vector3 contactNormal, steepNormal; int groundContactCount, steepContactCount; bool OnGround => groundContactCount > 0; bool OnSteep => steepContactCount > 0; int jumpPhase; float minGroundDotProduct, minStairsDotProduct; int stepsSinceLastGrounded, stepsSinceLastJump; Camera Maincamera; void OnValidate() { minGroundDotProduct = Mathf.Cos(maxGroundAngle * Mathf.Deg2Rad); minStairsDotProduct = Mathf.Cos(maxStairsAngle * Mathf.Deg2Rad); } void Awake() { body = GetComponent<Rigidbody>(); OnValidate(); Maincamera = Camera.main; } void Update() { Vector2 playerInput; playerInput.x = Input.GetAxis("Horizontal"); playerInput.y = Input.GetAxis("Vertical"); playerInput = Vector2.ClampMagnitude(playerInput, 1f); Vector3 forward = Vector3.ProjectOnPlane(Maincamera.transform.forward, Vector3.up); forward.y = 0f; forward.Normalize(); Vector3 right = Maincamera.transform.right; right.y = 0f; right.Normalize(); desiredVelocity = (forward * playerInput.y + right * playerInput.x) * maxSpeed; desiredJump |= Input.GetButtonDown("Jump"); } void FixedUpdate() { UpdateState(); AdjustVelocity(); if (desiredJump) { desiredJump = false; Jump(); } body.velocity = velocity; ClearState(); } void ClearState() { groundContactCount = steepContactCount = 0; contactNormal = steepNormal = Vector3.zero; } void UpdateState() { stepsSinceLastGrounded += 1; stepsSinceLastJump += 1; velocity = body.velocity; if (OnGround || SnapToGround() || CheckSteepContacts()) { stepsSinceLastGrounded = 0; if (stepsSinceLastJump > 1) { jumpPhase = 0; } if (groundContactCount > 1) { contactNormal.Normalize(); } } else { contactNormal = Vector3.up; } } bool SnapToGround() { if (stepsSinceLastGrounded > 1 || stepsSinceLastJump <= 2) { return false; } float speed = velocity.magnitude; if (speed > maxSnapSpeed) { return false; } if (!Physics.Raycast( body.position, Vector3.down, out RaycastHit hit, probeDistance, probeMask )) { return false; } if (hit.normal.y < GetMinDot(hit.collider.gameObject.layer)) { return false; } groundContactCount = 1; contactNormal = hit.normal; float dot = Vector3.Dot(velocity, hit.normal); if (dot > 0f) { velocity = (velocity - hit.normal * dot).normalized * speed; } return true; } bool CheckSteepContacts() { if (steepContactCount > 1) { steepNormal.Normalize(); if (steepNormal.y >= minGroundDotProduct) { steepContactCount = 0; groundContactCount = 1; contactNormal = steepNormal; return true; } } return false; } void AdjustVelocity() { Vector3 xAxis = ProjectOnContactPlane(Vector3.right).normalized; Vector3 zAxis = ProjectOnContactPlane(Vector3.forward).normalized; float currentX = Vector3.Dot(velocity, xAxis); float currentZ = Vector3.Dot(velocity, zAxis); float acceleration = OnGround ? maxAcceleration : maxAirAcceleration; float maxSpeedChange = acceleration * Time.deltaTime; float newX = Mathf.MoveTowards(currentX, desiredVelocity.x, maxSpeedChange); float newZ = Mathf.MoveTowards(currentZ, desiredVelocity.z, maxSpeedChange); velocity += xAxis * (newX - currentX) + zAxis * (newZ - currentZ); } void Jump() { Vector3 jumpDirection; if (OnGround) { jumpDirection = contactNormal; } else if (OnSteep) { jumpDirection = steepNormal; jumpPhase = 0; } else if (maxAirJumps > 0 && jumpPhase <= maxAirJumps) { if (jumpPhase == 0) { jumpPhase = 1; } jumpDirection = contactNormal; } else { return; } stepsSinceLastJump = 0; jumpPhase += 1; float jumpSpeed = Mathf.Sqrt(-2f * Physics.gravity.y * jumpHeight); jumpDirection = (jumpDirection + Vector3.up).normalized; float alignedSpeed = Vector3.Dot(velocity, jumpDirection); if (alignedSpeed > 0f) { jumpSpeed = Mathf.Max(jumpSpeed - alignedSpeed, 0f); } velocity += jumpDirection * jumpSpeed; } void OnCollisionEnter(Collision collision) { EvaluateCollision(collision); } void OnCollisionStay(Collision collision) { EvaluateCollision(collision); } void EvaluateCollision(Collision collision) { float minDot = GetMinDot(collision.gameObject.layer); for (int i = 0; i < collision.contactCount; i++) { Vector3 normal = collision.GetContact(i).normal; if (normal.y >= minDot) { groundContactCount += 1; contactNormal += normal; } else if (normal.y > -0.01f) { steepContactCount += 1; steepNormal += normal; } } } Vector3 ProjectOnContactPlane(Vector3 vector) { return vector - contactNormal * Vector3.Dot(vector, contactNormal); } float GetMinDot(int layer) { return (stairsMask & (1 << layer)) == 0 ? minGroundDotProduct : minStairsDotProduct; } }
using UnityEngine; [RequireComponent(typeof(Camera))] public class OrbitCamera : MonoBehaviour { [SerializeField] Transform focus = default; [SerializeField, Range(1f, 20f)] float distance = 5f; [SerializeField, Min(0f)] float focusRadius = 5f; [SerializeField, Range(0f, 1f)] float focusCentering = 0.5f; [SerializeField, Range(1f, 360f)] float rotationSpeed = 90f; [SerializeField, Range(-89f, 89f)] float minVerticalAngle = -45f, maxVerticalAngle = 45f; //[SerializeField, Min(0f)] //float alignDelay = 5f; //[SerializeField, Range(0f, 90f)] //float alignSmoothRange = 45f; [SerializeField] LayerMask obstructionMask = -1; Camera regularCamera; Vector3 focusPoint, previousFocusPoint; Vector2 orbitAngles = new Vector2(45f, 0f); float lastManualRotationTime; Vector3 CameraHalfExtends { get { Vector3 halfExtends; halfExtends.y = regularCamera.nearClipPlane * Mathf.Tan(0.5f * Mathf.Deg2Rad * regularCamera.fieldOfView); halfExtends.x = halfExtends.y * regularCamera.aspect; halfExtends.z = 0f; return halfExtends; } } void OnValidate() { if (maxVerticalAngle < minVerticalAngle) { maxVerticalAngle = minVerticalAngle; } } void Awake() { regularCamera = GetComponent<Camera>(); focusPoint = focus.position; transform.localRotation = Quaternion.Euler(orbitAngles); } void LateUpdate() { UpdateFocusPoint(); Quaternion lookRotation; if (ManualRotation()) { ConstrainAngles(); lookRotation = Quaternion.Euler(orbitAngles); } else { lookRotation = transform.localRotation; } Vector3 lookDirection = lookRotation * Vector3.forward; Vector3 lookPosition = focusPoint - lookDirection * distance; Vector3 rectOffset = lookDirection * regularCamera.nearClipPlane; Vector3 rectPosition = lookPosition + rectOffset; Vector3 castFrom = focus.position; Vector3 castLine = rectPosition - castFrom; float castDistance = castLine.magnitude; Vector3 castDirection = castLine / castDistance; if (Physics.BoxCast( castFrom, CameraHalfExtends, castDirection, out RaycastHit hit, lookRotation, castDistance, obstructionMask )) { rectPosition = castFrom + castDirection * hit.distance; lookPosition = rectPosition - rectOffset; } transform.SetPositionAndRotation(lookPosition, lookRotation); } bool ManualRotation() { Vector2 input = new Vector2( -Input.GetAxis("Mouse Y"), Input.GetAxis("Mouse X") ); const float e = 0.001f; if (input.x < -e || input.x > e || input.y < -e || input.y > e) { orbitAngles += rotationSpeed * Time.unscaledDeltaTime * input; lastManualRotationTime = Time.unscaledTime; return true; } return false; } void ConstrainAngles() { orbitAngles.x = Mathf.Clamp(orbitAngles.x, minVerticalAngle, maxVerticalAngle); if (orbitAngles.y < 0f) { orbitAngles.y += 360f; } else if (orbitAngles.y >= 360f) { orbitAngles.y -= 360f; } } void UpdateFocusPoint() { previousFocusPoint = focusPoint; Vector3 targetPoint = focus.position; if (focusRadius > 0f) { float distance = Vector3.Distance(targetPoint, focusPoint); float t = 1f; if (distance > 0.01f && focusCentering > 0f) { t = Mathf.Pow(1f - focusCentering, Time.unscaledDeltaTime); } if (distance > focusRadius) { t = Mathf.Min(t, focusRadius / distance); } focusPoint = Vector3.Lerp(targetPoint, focusPoint, t); } else { focusPoint = targetPoint; } } }
using UnityEngine; using System.Collections; #if UNITY_EDITOR using UnityEditor; #endif namespace SSS_Demo { [ExecuteInEditMode] public class OrbitCamera : MonoBehaviour { [Header("Frames between savings")] public int Frequency = 50; public Transform target; /*[HideInInspector] */ public float distance = 5.0f; public float Distance { get { return PlayerPrefs.GetFloat("Camera Distance " + this.GetInstanceID().ToString(), distance); } set { PlayerPrefs.SetFloat("Camera Distance " + this.GetInstanceID().ToString(), value); } } float idistance; public float RotationSpeed = 120.0f; bool CursorOnScreen; [Range(.1f, 1)] public float ZoomSpeed = 1; //Vector3 VirtualPivot = Vector3.zero; //[SerializeField] /*[HideInInspector] */ public Vector3 virtualPivot; public Vector3 VirtualPivot { get { Vector3 _Vector; _Vector.x = PlayerPrefs.GetFloat("Camera VirtualPivot X " + this.GetInstanceID(), virtualPivot.x); _Vector.y = PlayerPrefs.GetFloat("Camera VirtualPivot Y " + this.GetInstanceID(), virtualPivot.y); _Vector.z = PlayerPrefs.GetFloat("Camera VirtualPivot Z " + this.GetInstanceID(), virtualPivot.z); return _Vector; } set { PlayerPrefs.SetFloat("Camera VirtualPivot X " + this.GetInstanceID(), value.x); PlayerPrefs.SetFloat("Camera VirtualPivot Y " + this.GetInstanceID(), value.y); PlayerPrefs.SetFloat("Camera VirtualPivot Z " + this.GetInstanceID(), value.z); } } [Range(0, .1f)] public float PanSpeed = .1f; float x = 0, ix = 0.0f; float y = 0, iy = 0.0f; //[SerializeField] [HideInInspector] public Vector3 rotation; private float preFingerDis = 0; private Vector3 preFinger1Pos = Vector3.zero; private Vector3 preFinger2Pos = Vector3.zero; private bool twoPress = false; public Vector3 Rotation { get { Vector3 RotVector; RotVector.x = PlayerPrefs.GetFloat("Camera Rotation X " + this.GetInstanceID(), gameObject.transform.eulerAngles.x); RotVector.y = PlayerPrefs.GetFloat("Camera Rotation Y " + this.GetInstanceID(), gameObject.transform.eulerAngles.y); RotVector.z = PlayerPrefs.GetFloat("Camera Rotation Z " + this.GetInstanceID(), gameObject.transform.eulerAngles.z); return RotVector; } set { PlayerPrefs.SetFloat("Camera Rotation X " + this.GetInstanceID(), value.x); PlayerPrefs.SetFloat("Camera Rotation Y " + this.GetInstanceID(), value.y); PlayerPrefs.SetFloat("Camera Rotation Z " + this.GetInstanceID(), value.z); } } //[SerializeField] [HideInInspector] public Vector3 position; public Vector3 Position { get { Vector3 _Vector; _Vector.x = PlayerPrefs.GetFloat("Camera Position X " + this.GetInstanceID(), gameObject.transform.position.x); _Vector.y = PlayerPrefs.GetFloat("Camera Position Y " + this.GetInstanceID(), gameObject.transform.position.y); _Vector.z = PlayerPrefs.GetFloat("Camera Position Z " + this.GetInstanceID(), gameObject.transform.position.z); return _Vector; } set { PlayerPrefs.SetFloat("Camera Position X " + this.GetInstanceID(), value.x); PlayerPrefs.SetFloat("Camera Position Y " + this.GetInstanceID(), value.y); PlayerPrefs.SetFloat("Camera Position Z " + this.GetInstanceID(), value.z); } } void Start() { Vector3 angles = transform.eulerAngles; x = angles.y; y = angles.x; ix = x; iy = y; idistance = distance; } bool TimeSnap(int Frames) { bool refresh = true; if (Application.isPlaying) { refresh = Time.frameCount <= 3 || (Time.frameCount % (1 + Frames)) == 0; return refresh; } else return true; } void Update() { bool LMB = Input.GetMouseButton(0); bool RMB = Input.GetMouseButton(1); bool MMB = Input.GetMouseButton(2); if (target && Application.isPlaying) { Quaternion Qrotation = Quaternion.Euler(y, x, 0); // 手指触控 if (Input.touchCount > 1) { Vector3 tempPosition1 = Input.GetTouch(0).position; //计算出当前两点触摸点的位置 Vector3 tempPosition2 = Input.GetTouch(1).position; var fingerDis = Vector3.Distance(tempPosition1, tempPosition2); if (Input.GetTouch(0).phase == TouchPhase.Moved && Input.GetTouch(1).phase == TouchPhase.Moved) { // Zoom if (Mathf.Abs(fingerDis - preFingerDis) > 5) { twoPress = true; if (fingerDis > preFingerDis) { distance -= ZoomSpeed * 0.05f; } else { distance += ZoomSpeed * 0.05f; } } // Pan var dir = tempPosition1 - preFinger1Pos; var dir2 = tempPosition2 - preFinger2Pos; if (dir.magnitude > 1 && dir2.magnitude > 1) { twoPress = true; var dirUnit = dir.normalized; var dir2Unit = dir2.normalized; var similar = Vector3.Dot(dirUnit, dir2Unit); if (similar > 0.8) { var distanceToTarget = Vector3.Distance(transform.position, target.position); distanceToTarget = distanceToTarget * 0.06f; virtualPivot -= Qrotation * new Vector3( dirUnit.x * PanSpeed * distanceToTarget, dirUnit.y * PanSpeed * distanceToTarget, 0); } } } preFingerDis = fingerDis; preFinger1Pos = tempPosition1; preFinger2Pos = tempPosition2; } if (Input.touchCount < 1) { twoPress = false; } if (Input.touchCount == 1 && twoPress == false) { x += Input.GetAxis("Mouse X") * RotationSpeed * 0.02f; y -= Input.GetAxis("Mouse Y") * RotationSpeed * 0.02f; } #if UNITY_EDITOR if ( /*Input.GetKey(KeyCode.LeftAlt) && */LMB) { x += Input.GetAxis("Mouse X") * RotationSpeed * 0.02f; y -= Input.GetAxis("Mouse Y") * RotationSpeed * 0.02f; } // zoom draggin' if ( /*Input.GetKey(KeyCode.LeftAlt) && */RMB) { //drag mouse to add and sub distance distance += Input.GetAxis("Mouse Y") * ZoomSpeed * 0.15f; } // pan if ( /*Input.GetKey(KeyCode.LeftAlt) && */MMB) { // VirtualPivot.x += Input.GetAxis("Mouse X") * PanSpeed; // VirtualPivot.y -= Input.GetAxis("Mouse Y") * PanSpeed; virtualPivot -= Qrotation * new Vector3(Input.GetAxis("Mouse X") * PanSpeed, Input.GetAxis("Mouse Y") * PanSpeed, 0); } //zoom mouse wheel if (MouseScreenCheck()) distance -= Input.GetAxis("Mouse ScrollWheel") * ZoomSpeed; #endif /*Vector3*/ position = Qrotation * new Vector3(0.0f, 0.0f, -distance) + target.position + virtualPivot; transform.rotation = Qrotation; transform.position = position; if (TimeSnap(Frequency)) { VirtualPivot = virtualPivot; Rotation = transform.eulerAngles; rotation = Rotation; Position = transform.position; position = Position; Distance = distance; } } if (target == null) print("Set a target in the orbit camera"); // print( Event.current.keyCode); if ( /*Input.GetKey(KeyCode.F) ||*/ Input.GetKey(KeyCode.R)) ResetCam(); } void ResetCam() { // print("Control"); // if (Input.GetKey(KeyCode.F) || Input.GetKey(KeyCode.R)) { // print("F"); VirtualPivot = Vector3.zero; virtualPivot = Vector3.zero; x = ix; y = iy; distance = idistance; } } void OnEnable() { //ResetCam(); rotation = Rotation; transform.eulerAngles = rotation; position = Position; transform.position = Position; distance = Distance; virtualPivot = VirtualPivot; } public bool MouseScreenCheck() { var view = GetComponent<Camera>().ScreenToViewportPoint(Input.mousePosition); var isOutside = view.x < 0 || view.x > 1 || view.y < 0 || view.y > 1; return !isOutside; } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。